ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_cmd.cpp
Revision: 1.18
Committed: 2004-04-20T19:39:03Z (20 years, 7 months ago) by cebix
Branch: MAIN
CVS Tags: release_3-1
Changes since 1.17: +1 -1 lines
Log Message:
- fixed URL in package
- "ver" command displays correct program name

File Contents

# User Rev Content
1 cebix 1.1 /*
2 cebix 1.9 * mon_cmd.cpp - cxmon standard commands
3 cebix 1.1 *
4 cebix 1.17 * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig
5 cebix 1.2 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 cebix 1.1 */
20    
21 cebix 1.2 #include "sysdeps.h"
22 cebix 1.1
23 cebix 1.4 #include <stdlib.h>
24    
25 cebix 1.1 #include "mon.h"
26     #include "mon_cmd.h"
27 cebix 1.7 #include "mon_disass.h"
28 cebix 1.1
29 hellwig 1.6 #ifndef VERSION
30 cebix 1.12 #define VERSION "3"
31 hellwig 1.6 #endif
32    
33 cebix 1.1
34     /*
35     * range_args = [expression] [[COMMA] expression] END
36     *
37     * Read start address to "adr", end address to "end_adr".
38     * "adr" defaults to '.', "end_adr" defaults to '.'+def_range
39     *
40     * true: OK, false: Error
41     */
42    
43 gbeauche 1.11 static bool range_args(uintptr *adr, uintptr *end_adr, uint32 def_range)
44 cebix 1.1 {
45     *adr = mon_dot_address;
46     *end_adr = mon_dot_address + def_range;
47    
48     if (mon_token == T_END)
49     return true;
50     else {
51     if (!mon_expression(adr))
52     return false;
53     *end_adr = *adr + def_range;
54     if (mon_token == T_END)
55     return true;
56     else {
57     if (mon_token == T_COMMA) mon_get_token();
58     if (!mon_expression(end_adr))
59     return false;
60     return mon_token == T_END;
61     }
62     }
63     }
64    
65    
66     /*
67     * byte_string = (expression | STRING) {COMMA (expression | STRING)} END
68     */
69    
70 cebix 1.16 static bool byte_string(uint8 *&str, uintptr &len)
71 cebix 1.1 {
72 gbeauche 1.11 uintptr value;
73 cebix 1.1
74 cebix 1.16 static const int GRANULARITY = 16; // must be a power of 2
75     str = NULL;
76 cebix 1.1 len = 0;
77     goto start;
78    
79     for (;;) {
80     if (mon_token == T_COMMA) {
81     mon_get_token();
82    
83     start:
84     if (mon_token == T_STRING) {
85     uint8 *p = (uint8 *)mon_string;
86 cebix 1.16 unsigned n = strlen(mon_string);
87     str = (uint8 *)realloc(str, (len + n - 1 + GRANULARITY) & ~(GRANULARITY - 1));
88     memcpy(str + len, mon_string, n);
89     len += n;
90 cebix 1.1 mon_get_token();
91     } else if (mon_expression(&value)) {
92 cebix 1.16 str = (uint8 *)realloc(str, (len + GRANULARITY) & ~(GRANULARITY - 1));
93     str[len] = value;
94 cebix 1.1 len++;
95 cebix 1.16 } else {
96     if (str)
97     free(str);
98 cebix 1.1 return false;
99 cebix 1.16 }
100 cebix 1.1
101 cebix 1.16 } else if (mon_token == T_END) {
102 cebix 1.1 return true;
103 cebix 1.16 } else {
104 cebix 1.1 mon_error("',' expected");
105 cebix 1.16 if (str)
106     free(str);
107 cebix 1.1 return false;
108     }
109     }
110     }
111    
112    
113     /*
114     * Convert character to printable character
115     */
116    
117     static inline uint8 char2print(uint8 c)
118     {
119     return (c >= 0x20 && c <= 0x7e) ? c : '.';
120     }
121    
122    
123     /*
124     * Show version
125     * ver
126     */
127    
128     void version(void)
129     {
130 cebix 1.18 fprintf(monout, "cxmon V" VERSION "\n");
131 cebix 1.1 }
132    
133    
134     /*
135     * Redirect output
136     * o [file]
137     */
138    
139     void redir_output(void)
140     {
141     // Close old file
142     if (monout != monerr) {
143     fclose(monout);
144     monout = monerr;
145     return;
146     }
147    
148     // No argument given?
149     if (mon_token == T_END)
150     return;
151    
152     // Otherwise open file
153     if (mon_token == T_STRING) {
154     mon_get_token();
155     if (mon_token != T_END) {
156     mon_error("Too many arguments");
157     return;
158     }
159     if (!(monout = fopen(mon_string, "w")))
160     mon_error("Unable to open file");
161     } else
162     mon_error("'\"' around file name expected");
163     }
164    
165    
166     /*
167     * Compute and display expression
168     * ? expression
169     */
170    
171     void print_expr(void)
172     {
173 gbeauche 1.11 uintptr val;
174 cebix 1.1
175     if (!mon_expression(&val))
176     return;
177     if (mon_token != T_END) {
178     mon_error("Too many arguments");
179     return;
180     }
181    
182     if (val > 0x7fffffff) {
183 cebix 1.3 fprintf(monout, "Hex unsigned: $%08x\n"
184     "Hex signed : -$%08x\n"
185     "Dec unsigned: %u\n"
186     "Dec signed : %d\n", val, -val, val, val);
187 cebix 1.1 fprintf(monout, "Char : '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val));
188     } else {
189 cebix 1.3 fprintf(monout, "Hex : $%08x\n"
190     "Dec : %d\n", val, val);
191 cebix 1.1 fprintf(monout, "Char: '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val));
192     }
193     }
194    
195    
196     /*
197     * Execute shell command
198     * \ "command"
199     */
200    
201     void shell_command(void)
202     {
203     if (mon_token != T_STRING) {
204     mon_error("'\"' around command expected");
205     return;
206     }
207     mon_get_token();
208     if (mon_token != T_END) {
209     mon_error("Too many arguments");
210     return;
211     }
212     system(mon_string);
213     }
214    
215    
216     /*
217     * Memory dump
218     * m [start [end]]
219     */
220    
221     #define MEMDUMP_BPL 16 // Bytes per line
222    
223     void memory_dump(void)
224     {
225 gbeauche 1.11 uintptr adr, end_adr;
226 cebix 1.1 uint8 mem[MEMDUMP_BPL + 1];
227    
228     mem[MEMDUMP_BPL] = 0;
229    
230     if (!range_args(&adr, &end_adr, 16 * MEMDUMP_BPL - 1)) // 16 lines unless end address specified
231     return;
232    
233     while (adr <= end_adr && !mon_aborted()) {
234 gbeauche 1.11 fprintf(monout, "%0*lx:", 2 * sizeof(adr), mon_use_real_mem ? adr: adr % mon_mem_size);
235 cebix 1.1 for (int i=0; i<MEMDUMP_BPL; i++, adr++) {
236     if (i % 4 == 0)
237 cebix 1.3 fprintf(monout, " %08x", mon_read_word(adr));
238 cebix 1.1 mem[i] = char2print(mon_read_byte(adr));
239     }
240     fprintf(monout, " '%s'\n", mem);
241     }
242    
243     mon_dot_address = adr;
244     }
245    
246    
247     /*
248     * ASCII dump
249     * i [start [end]]
250     */
251    
252     #define ASCIIDUMP_BPL 64 // Bytes per line
253    
254     void ascii_dump(void)
255     {
256 gbeauche 1.11 uintptr adr, end_adr;
257 cebix 1.1 uint8 str[ASCIIDUMP_BPL + 1];
258    
259     str[ASCIIDUMP_BPL] = 0;
260    
261     if (!range_args(&adr, &end_adr, 16 * ASCIIDUMP_BPL - 1)) // 16 lines unless end address specified
262     return;
263    
264     while (adr <= end_adr && !mon_aborted()) {
265 gbeauche 1.13 fprintf(monout, "%0*lx:", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
266 cebix 1.1 for (int i=0; i<ASCIIDUMP_BPL; i++, adr++)
267     str[i] = char2print(mon_read_byte(adr));
268     fprintf(monout, " '%s'\n", str);
269 cebix 1.5 }
270    
271     mon_dot_address = adr;
272     }
273    
274    
275     /*
276     * Binary dump
277     * b [start [end]]
278     */
279    
280     void binary_dump(void)
281     {
282 gbeauche 1.11 uintptr adr, end_adr;
283 cebix 1.5 uint8 str[9];
284    
285     str[8] = 0;
286    
287     if (!range_args(&adr, &end_adr, 7)) // 8 lines unless end address specified
288     return;
289    
290     while (adr <= end_adr && !mon_aborted()) {
291 gbeauche 1.13 fprintf(monout, "%0*lx:", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
292 cebix 1.5 uint8 b = mon_read_byte(adr);
293     for (int m=0x80, i=0; i<8; m>>=1, i++)
294     str[i] = (b & m) ? '*' : '.';
295     fprintf(monout, " '%s'\n", str);
296     adr++;
297 cebix 1.1 }
298    
299     mon_dot_address = adr;
300     }
301    
302    
303     /*
304     * Disassemble
305     * d [start [end]]
306     * d65 [start [end]]
307     * d68 [start [end]]
308     * d80 [start [end]]
309     * d86 [start [end]]
310 cebix 1.9 * d8086 [start [end]]
311 cebix 1.1 */
312    
313     enum CPUType {
314     CPU_PPC,
315     CPU_6502,
316     CPU_680x0,
317 cebix 1.9 CPU_Z80,
318 cebix 1.8 CPU_80x86_32,
319 gbeauche 1.13 CPU_80x86_16,
320     CPU_x86_64
321 cebix 1.1 };
322    
323     static void disassemble(CPUType type)
324     {
325 gbeauche 1.11 uintptr adr, end_adr;
326 cebix 1.1
327     if (!range_args(&adr, &end_adr, 16 * 4 - 1)) // 16 lines unless end address specified
328     return;
329    
330     switch (type) {
331     case CPU_PPC:
332     while (adr <= end_adr && !mon_aborted()) {
333     uint32 w = mon_read_word(adr);
334 gbeauche 1.13 fprintf(monout, "%0*lx: %08x\t", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size, w);
335 cebix 1.1 disass_ppc(monout, mon_use_real_mem ? adr : adr % mon_mem_size, w);
336     adr += 4;
337     }
338     break;
339    
340     case CPU_6502:
341     while (adr <= end_adr && !mon_aborted()) {
342     uint8 op = mon_read_byte(adr);
343     uint8 lo = mon_read_byte(adr + 1);
344     uint8 hi = mon_read_byte(adr + 2);
345 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
346 cebix 1.1 adr += disass_6502(monout, mon_use_real_mem ? adr : adr % mon_mem_size, op, lo, hi);
347     }
348     break;
349    
350     case CPU_680x0:
351     while (adr <= end_adr && !mon_aborted()) {
352 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
353 cebix 1.7 adr += disass_68k(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
354 cebix 1.1 }
355     break;
356    
357 cebix 1.9 case CPU_Z80:
358 cebix 1.1 while (adr <= end_adr && !mon_aborted()) {
359 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
360 cebix 1.9 adr += disass_z80(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
361 cebix 1.1 }
362     break;
363    
364 gbeauche 1.13 case CPU_x86_64:
365     while (adr <= end_adr && !mon_aborted()) {
366     fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
367     adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 64);
368     }
369     break;
370    
371 cebix 1.8 case CPU_80x86_32:
372 cebix 1.1 while (adr <= end_adr && !mon_aborted()) {
373 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
374     adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 32);
375 cebix 1.8 }
376     break;
377    
378     case CPU_80x86_16:
379     while (adr <= end_adr && !mon_aborted()) {
380 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
381     adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 16);
382 cebix 1.1 }
383     }
384    
385     mon_dot_address = adr;
386     }
387    
388     void disassemble_ppc(void)
389     {
390     disassemble(CPU_PPC);
391     }
392    
393     void disassemble_6502(void)
394     {
395     disassemble(CPU_6502);
396     }
397    
398     void disassemble_680x0(void)
399     {
400     disassemble(CPU_680x0);
401     }
402    
403 cebix 1.9 void disassemble_z80(void)
404 cebix 1.1 {
405 cebix 1.9 disassemble(CPU_Z80);
406 cebix 1.1 }
407    
408 cebix 1.8 void disassemble_80x86_32(void)
409     {
410     disassemble(CPU_80x86_32);
411     }
412    
413     void disassemble_80x86_16(void)
414 cebix 1.1 {
415 cebix 1.8 disassemble(CPU_80x86_16);
416 cebix 1.1 }
417    
418 gbeauche 1.13 void disassemble_x86_64(void)
419     {
420     disassemble(CPU_x86_64);
421     }
422    
423 cebix 1.1
424     /*
425     * Modify memory
426     * : addr bytestring
427     */
428    
429     void modify(void)
430     {
431 gbeauche 1.11 uintptr adr, len, src_adr = 0;
432 cebix 1.16 uint8 *str;
433 cebix 1.1
434     if (!mon_expression(&adr))
435     return;
436     if (!byte_string(str, len))
437     return;
438    
439     while (src_adr < len)
440     mon_write_byte(adr++, str[src_adr++]);
441 cebix 1.16 mon_dot_address = adr;
442 cebix 1.1
443 cebix 1.16 free(str);
444 cebix 1.1 }
445    
446    
447     /*
448     * Fill
449     * f start end bytestring
450     */
451    
452     void fill(void)
453     {
454 gbeauche 1.11 uintptr adr, end_adr, len, src_adr = 0;
455 cebix 1.16 uint8 *str;
456 cebix 1.1
457     if (!mon_expression(&adr))
458     return;
459     if (!mon_expression(&end_adr))
460     return;
461     if (!byte_string(str, len))
462     return;
463    
464     while (adr <= end_adr)
465     mon_write_byte(adr++, str[src_adr++ % len]);
466 cebix 1.16
467     free(str);
468 cebix 1.1 }
469    
470    
471     /*
472     * Transfer memory
473     * t start end dest
474     */
475    
476     void transfer(void)
477     {
478 gbeauche 1.11 uintptr adr, end_adr, dest;
479 cebix 1.1 int num;
480    
481     if (!mon_expression(&adr))
482     return;
483     if (!mon_expression(&end_adr))
484     return;
485     if (!mon_expression(&dest))
486     return;
487     if (mon_token != T_END) {
488     mon_error("Too many arguments");
489     return;
490     }
491    
492     num = end_adr - adr + 1;
493    
494     if (dest < adr)
495     for (int i=0; i<num; i++)
496     mon_write_byte(dest++, mon_read_byte(adr++));
497     else {
498     dest += end_adr - adr;
499     for (int i=0; i<num; i++)
500     mon_write_byte(dest--, mon_read_byte(end_adr--));
501     }
502     }
503    
504    
505     /*
506     * Compare
507     * c start end dest
508     */
509    
510     void compare(void)
511     {
512 gbeauche 1.11 uintptr adr, end_adr, dest;
513 cebix 1.1 int num = 0;
514    
515     if (!mon_expression(&adr))
516     return;
517     if (!mon_expression(&end_adr))
518     return;
519     if (!mon_expression(&dest))
520     return;
521     if (mon_token != T_END) {
522     mon_error("Too many arguments");
523     return;
524     }
525    
526     while (adr <= end_adr && !mon_aborted()) {
527     if (mon_read_byte(adr) != mon_read_byte(dest)) {
528 gbeauche 1.13 fprintf(monout, "%0*lx ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
529 cebix 1.1 num++;
530     if (!(num & 7))
531     fputc('\n', monout);
532     }
533     adr++; dest++;
534     }
535    
536     if (num & 7)
537     fputc('\n', monout);
538     fprintf(monout, "%d byte(s) different\n", num);
539     }
540    
541    
542     /*
543     * Search for byte string
544     * h start end bytestring
545     */
546    
547     void hunt(void)
548     {
549 gbeauche 1.11 uintptr adr, end_adr, len;
550 cebix 1.16 uint8 *str;
551 cebix 1.1 int num = 0;
552    
553     if (!mon_expression(&adr))
554     return;
555     if (!mon_expression(&end_adr))
556     return;
557     if (!byte_string(str, len))
558     return;
559    
560     while ((adr+len-1) <= end_adr && !mon_aborted()) {
561     uint32 i;
562    
563     for (i=0; i<len; i++)
564     if (mon_read_byte(adr + i) != str[i])
565     break;
566    
567     if (i == len) {
568 gbeauche 1.13 fprintf(monout, "%0*lx ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
569 cebix 1.1 num++;
570     if (num == 1)
571     mon_dot_address = adr;
572     if (!(num & 7))
573     fputc('\n', monout);
574     }
575     adr++;
576     }
577 cebix 1.16
578     free(str);
579 cebix 1.1
580     if (num & 7)
581     fputc('\n', monout);
582     fprintf(monout, "Found %d occurrences\n", num);
583     }
584    
585    
586     /*
587     * Load data
588     * [ start "file"
589     */
590    
591     void load_data(void)
592     {
593 gbeauche 1.11 uintptr start_adr;
594 cebix 1.1 FILE *file;
595     int fc;
596    
597     if (!mon_expression(&start_adr))
598     return;
599     if (mon_token == T_END) {
600     mon_error("Missing file name");
601     return;
602     }
603     if (mon_token != T_STRING) {
604     mon_error("'\"' around file name expected");
605     return;
606     }
607     mon_get_token();
608     if (mon_token != T_END) {
609     mon_error("Too many arguments");
610     return;
611     }
612    
613     if (!(file = fopen(mon_string, "rb")))
614     mon_error("Unable to open file");
615     else {
616 gbeauche 1.11 uintptr adr = start_adr;
617 cebix 1.1
618     while ((fc = fgetc(file)) != EOF)
619     mon_write_byte(adr++, fc);
620     fclose(file);
621    
622 gbeauche 1.13 fprintf(monerr, "%08x bytes read from %0*lx to %0*lx\n", adr - start_adr, 2 * sizeof(adr), mon_use_real_mem ? start_adr : start_adr % mon_mem_size, 2 * sizeof(adr), mon_use_real_mem ? adr-1 : (adr-1) % mon_mem_size);
623 cebix 1.1 mon_dot_address = adr;
624     }
625     }
626    
627    
628     /*
629     * Save data
630     * ] start size "file"
631     */
632    
633     void save_data(void)
634     {
635 gbeauche 1.11 uintptr start_adr, size;
636 cebix 1.1 FILE *file;
637    
638     if (!mon_expression(&start_adr))
639     return;
640     if (!mon_expression(&size))
641     return;
642     if (mon_token == T_END) {
643     mon_error("Missing file name");
644     return;
645     }
646     if (mon_token != T_STRING) {
647     mon_error("'\"' around file name expected");
648     return;
649     }
650     mon_get_token();
651     if (mon_token != T_END) {
652     mon_error("Too many arguments");
653     return;
654     }
655    
656     if (!(file = fopen(mon_string, "wb")))
657     mon_error("Unable to create file");
658     else {
659 gbeauche 1.11 uintptr adr = start_adr, end_adr = start_adr + size - 1;
660 cebix 1.1
661     while (adr <= end_adr)
662     fputc(mon_read_byte(adr++), file);
663     fclose(file);
664    
665 cebix 1.14 fprintf(monerr, "%08x bytes written from %0*lx to %0*lx\n", size, 2 * sizeof(adr), mon_use_real_mem ? start_adr : start_adr % mon_mem_size, 2 * sizeof(adr), mon_use_real_mem ? end_adr : end_adr % mon_mem_size);
666 cebix 1.1 }
667     }