ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_cmd.cpp
Revision: 1.21
Committed: 2012-06-19T22:23:25Z (12 years, 5 months ago) by cebix
Branch: MAIN
CVS Tags: HEAD
Changes since 1.20: +4 -2 lines
Log Message:
don't crash if string argument to fill command is empty

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 cebix 1.16 unsigned n = strlen(mon_string);
86     str = (uint8 *)realloc(str, (len + n - 1 + GRANULARITY) & ~(GRANULARITY - 1));
87     memcpy(str + len, mon_string, n);
88     len += n;
89 cebix 1.1 mon_get_token();
90     } else if (mon_expression(&value)) {
91 cebix 1.16 str = (uint8 *)realloc(str, (len + GRANULARITY) & ~(GRANULARITY - 1));
92     str[len] = value;
93 cebix 1.1 len++;
94 cebix 1.16 } else {
95     if (str)
96     free(str);
97 cebix 1.1 return false;
98 cebix 1.16 }
99 cebix 1.1
100 cebix 1.16 } else if (mon_token == T_END) {
101 cebix 1.1 return true;
102 cebix 1.16 } else {
103 cebix 1.1 mon_error("',' expected");
104 cebix 1.16 if (str)
105     free(str);
106 cebix 1.1 return false;
107     }
108     }
109     }
110    
111    
112     /*
113     * Convert character to printable character
114     */
115    
116     static inline uint8 char2print(uint8 c)
117     {
118     return (c >= 0x20 && c <= 0x7e) ? c : '.';
119     }
120    
121    
122     /*
123     * Show version
124     * ver
125     */
126    
127     void version(void)
128     {
129 cebix 1.18 fprintf(monout, "cxmon V" VERSION "\n");
130 cebix 1.1 }
131    
132    
133     /*
134     * Redirect output
135     * o [file]
136     */
137    
138     void redir_output(void)
139     {
140     // Close old file
141     if (monout != monerr) {
142     fclose(monout);
143     monout = monerr;
144     return;
145     }
146    
147     // No argument given?
148     if (mon_token == T_END)
149     return;
150    
151     // Otherwise open file
152     if (mon_token == T_STRING) {
153     mon_get_token();
154     if (mon_token != T_END) {
155     mon_error("Too many arguments");
156     return;
157     }
158     if (!(monout = fopen(mon_string, "w")))
159     mon_error("Unable to open file");
160     } else
161     mon_error("'\"' around file name expected");
162     }
163    
164    
165     /*
166     * Compute and display expression
167     * ? expression
168     */
169    
170     void print_expr(void)
171     {
172 gbeauche 1.11 uintptr val;
173 cebix 1.1
174     if (!mon_expression(&val))
175     return;
176     if (mon_token != T_END) {
177     mon_error("Too many arguments");
178     return;
179     }
180    
181     if (val > 0x7fffffff) {
182 cebix 1.3 fprintf(monout, "Hex unsigned: $%08x\n"
183     "Hex signed : -$%08x\n"
184     "Dec unsigned: %u\n"
185     "Dec signed : %d\n", val, -val, val, val);
186 cebix 1.1 fprintf(monout, "Char : '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val));
187     } else {
188 cebix 1.3 fprintf(monout, "Hex : $%08x\n"
189     "Dec : %d\n", val, val);
190 cebix 1.1 fprintf(monout, "Char: '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val));
191     }
192     }
193    
194    
195     /*
196     * Execute shell command
197     * \ "command"
198     */
199    
200     void shell_command(void)
201     {
202     if (mon_token != T_STRING) {
203     mon_error("'\"' around command expected");
204     return;
205     }
206     mon_get_token();
207     if (mon_token != T_END) {
208     mon_error("Too many arguments");
209     return;
210     }
211     system(mon_string);
212     }
213    
214    
215     /*
216     * Memory dump
217     * m [start [end]]
218     */
219    
220     #define MEMDUMP_BPL 16 // Bytes per line
221    
222     void memory_dump(void)
223     {
224 gbeauche 1.11 uintptr adr, end_adr;
225 cebix 1.1 uint8 mem[MEMDUMP_BPL + 1];
226    
227     mem[MEMDUMP_BPL] = 0;
228    
229     if (!range_args(&adr, &end_adr, 16 * MEMDUMP_BPL - 1)) // 16 lines unless end address specified
230     return;
231    
232     while (adr <= end_adr && !mon_aborted()) {
233 cebix 1.19 fprintf(monout, "%0*lx:", int(2 * sizeof(adr)), mon_use_real_mem ? adr: adr % mon_mem_size);
234 cebix 1.1 for (int i=0; i<MEMDUMP_BPL; i++, adr++) {
235     if (i % 4 == 0)
236 cebix 1.3 fprintf(monout, " %08x", mon_read_word(adr));
237 cebix 1.1 mem[i] = char2print(mon_read_byte(adr));
238     }
239     fprintf(monout, " '%s'\n", mem);
240     }
241    
242     mon_dot_address = adr;
243     }
244    
245    
246     /*
247     * ASCII dump
248     * i [start [end]]
249     */
250    
251     #define ASCIIDUMP_BPL 64 // Bytes per line
252    
253     void ascii_dump(void)
254     {
255 gbeauche 1.11 uintptr adr, end_adr;
256 cebix 1.1 uint8 str[ASCIIDUMP_BPL + 1];
257    
258     str[ASCIIDUMP_BPL] = 0;
259    
260     if (!range_args(&adr, &end_adr, 16 * ASCIIDUMP_BPL - 1)) // 16 lines unless end address specified
261     return;
262    
263     while (adr <= end_adr && !mon_aborted()) {
264 cebix 1.19 fprintf(monout, "%0*lx:", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
265 cebix 1.1 for (int i=0; i<ASCIIDUMP_BPL; i++, adr++)
266     str[i] = char2print(mon_read_byte(adr));
267     fprintf(monout, " '%s'\n", str);
268 cebix 1.5 }
269    
270     mon_dot_address = adr;
271     }
272    
273    
274     /*
275     * Binary dump
276     * b [start [end]]
277     */
278    
279     void binary_dump(void)
280     {
281 gbeauche 1.11 uintptr adr, end_adr;
282 cebix 1.5 uint8 str[9];
283    
284     str[8] = 0;
285    
286     if (!range_args(&adr, &end_adr, 7)) // 8 lines unless end address specified
287     return;
288    
289     while (adr <= end_adr && !mon_aborted()) {
290 cebix 1.19 fprintf(monout, "%0*lx:", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
291 cebix 1.5 uint8 b = mon_read_byte(adr);
292     for (int m=0x80, i=0; i<8; m>>=1, i++)
293     str[i] = (b & m) ? '*' : '.';
294     fprintf(monout, " '%s'\n", str);
295     adr++;
296 cebix 1.1 }
297    
298     mon_dot_address = adr;
299     }
300    
301    
302     /*
303     * Disassemble
304     * d [start [end]]
305     * d65 [start [end]]
306     * d68 [start [end]]
307     * d80 [start [end]]
308     * d86 [start [end]]
309 cebix 1.9 * d8086 [start [end]]
310 cebix 1.1 */
311    
312     enum CPUType {
313     CPU_PPC,
314     CPU_6502,
315     CPU_680x0,
316 cebix 1.9 CPU_Z80,
317 cebix 1.8 CPU_80x86_32,
318 gbeauche 1.13 CPU_80x86_16,
319 gbeauche 1.20 CPU_x86_64,
320     CPU_MIPS,
321     CPU_MIPS_LITTLE,
322 cebix 1.1 };
323    
324     static void disassemble(CPUType type)
325     {
326 gbeauche 1.11 uintptr adr, end_adr;
327 cebix 1.1
328     if (!range_args(&adr, &end_adr, 16 * 4 - 1)) // 16 lines unless end address specified
329     return;
330    
331     switch (type) {
332     case CPU_PPC:
333     while (adr <= end_adr && !mon_aborted()) {
334     uint32 w = mon_read_word(adr);
335 cebix 1.19 fprintf(monout, "%0*lx: %08x\t", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size, w);
336 cebix 1.1 disass_ppc(monout, mon_use_real_mem ? adr : adr % mon_mem_size, w);
337     adr += 4;
338     }
339     break;
340    
341     case CPU_6502:
342     while (adr <= end_adr && !mon_aborted()) {
343     uint8 op = mon_read_byte(adr);
344     uint8 lo = mon_read_byte(adr + 1);
345     uint8 hi = mon_read_byte(adr + 2);
346 cebix 1.19 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
347 cebix 1.1 adr += disass_6502(monout, mon_use_real_mem ? adr : adr % mon_mem_size, op, lo, hi);
348     }
349     break;
350    
351     case CPU_680x0:
352     while (adr <= end_adr && !mon_aborted()) {
353 cebix 1.19 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
354 cebix 1.7 adr += disass_68k(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
355 cebix 1.1 }
356     break;
357    
358 cebix 1.9 case CPU_Z80:
359 cebix 1.1 while (adr <= end_adr && !mon_aborted()) {
360 cebix 1.19 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
361 cebix 1.9 adr += disass_z80(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
362 cebix 1.1 }
363     break;
364    
365 gbeauche 1.20 case CPU_MIPS:
366     case CPU_MIPS_LITTLE:
367     while (adr <= end_adr && !mon_aborted()) {
368     fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
369     adr += disass_mips(monout, mon_use_real_mem ? adr : adr % mon_mem_size, type == CPU_MIPS_LITTLE);
370     }
371     break;
372    
373 gbeauche 1.13 case CPU_x86_64:
374     while (adr <= end_adr && !mon_aborted()) {
375 cebix 1.19 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
376 gbeauche 1.13 adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 64);
377     }
378     break;
379    
380 cebix 1.8 case CPU_80x86_32:
381 cebix 1.1 while (adr <= end_adr && !mon_aborted()) {
382 cebix 1.19 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
383 gbeauche 1.13 adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 32);
384 cebix 1.8 }
385     break;
386    
387     case CPU_80x86_16:
388     while (adr <= end_adr && !mon_aborted()) {
389 cebix 1.19 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
390 gbeauche 1.13 adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 16);
391 cebix 1.1 }
392     }
393    
394     mon_dot_address = adr;
395     }
396    
397     void disassemble_ppc(void)
398     {
399     disassemble(CPU_PPC);
400     }
401    
402     void disassemble_6502(void)
403     {
404     disassemble(CPU_6502);
405     }
406    
407     void disassemble_680x0(void)
408     {
409     disassemble(CPU_680x0);
410     }
411    
412 cebix 1.9 void disassemble_z80(void)
413 cebix 1.1 {
414 cebix 1.9 disassemble(CPU_Z80);
415 cebix 1.1 }
416    
417 cebix 1.8 void disassemble_80x86_32(void)
418     {
419     disassemble(CPU_80x86_32);
420     }
421    
422     void disassemble_80x86_16(void)
423 cebix 1.1 {
424 cebix 1.8 disassemble(CPU_80x86_16);
425 cebix 1.1 }
426    
427 gbeauche 1.13 void disassemble_x86_64(void)
428     {
429     disassemble(CPU_x86_64);
430     }
431    
432 gbeauche 1.20 void disassemble_mips(void)
433     {
434     disassemble(CPU_MIPS);
435     }
436    
437     void disassemble_mipsel(void)
438     {
439     disassemble(CPU_MIPS_LITTLE);
440     }
441    
442 cebix 1.1
443     /*
444     * Modify memory
445     * : addr bytestring
446     */
447    
448     void modify(void)
449     {
450 gbeauche 1.11 uintptr adr, len, src_adr = 0;
451 cebix 1.16 uint8 *str;
452 cebix 1.1
453     if (!mon_expression(&adr))
454     return;
455     if (!byte_string(str, len))
456     return;
457    
458     while (src_adr < len)
459     mon_write_byte(adr++, str[src_adr++]);
460 cebix 1.16 mon_dot_address = adr;
461 cebix 1.1
462 cebix 1.16 free(str);
463 cebix 1.1 }
464    
465    
466     /*
467     * Fill
468     * f start end bytestring
469     */
470    
471     void fill(void)
472     {
473 gbeauche 1.11 uintptr adr, end_adr, len, src_adr = 0;
474 cebix 1.16 uint8 *str;
475 cebix 1.1
476     if (!mon_expression(&adr))
477     return;
478     if (!mon_expression(&end_adr))
479     return;
480     if (!byte_string(str, len))
481     return;
482    
483 cebix 1.21 if (len) {
484     while (adr <= end_adr)
485     mon_write_byte(adr++, str[src_adr++ % len]);
486     }
487 cebix 1.16
488     free(str);
489 cebix 1.1 }
490    
491    
492     /*
493     * Transfer memory
494     * t start end dest
495     */
496    
497     void transfer(void)
498     {
499 gbeauche 1.11 uintptr adr, end_adr, dest;
500 cebix 1.1 int num;
501    
502     if (!mon_expression(&adr))
503     return;
504     if (!mon_expression(&end_adr))
505     return;
506     if (!mon_expression(&dest))
507     return;
508     if (mon_token != T_END) {
509     mon_error("Too many arguments");
510     return;
511     }
512    
513     num = end_adr - adr + 1;
514    
515     if (dest < adr)
516     for (int i=0; i<num; i++)
517     mon_write_byte(dest++, mon_read_byte(adr++));
518     else {
519     dest += end_adr - adr;
520     for (int i=0; i<num; i++)
521     mon_write_byte(dest--, mon_read_byte(end_adr--));
522     }
523     }
524    
525    
526     /*
527     * Compare
528     * c start end dest
529     */
530    
531     void compare(void)
532     {
533 gbeauche 1.11 uintptr adr, end_adr, dest;
534 cebix 1.1 int num = 0;
535    
536     if (!mon_expression(&adr))
537     return;
538     if (!mon_expression(&end_adr))
539     return;
540     if (!mon_expression(&dest))
541     return;
542     if (mon_token != T_END) {
543     mon_error("Too many arguments");
544     return;
545     }
546    
547     while (adr <= end_adr && !mon_aborted()) {
548     if (mon_read_byte(adr) != mon_read_byte(dest)) {
549 cebix 1.19 fprintf(monout, "%0*lx ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
550 cebix 1.1 num++;
551     if (!(num & 7))
552     fputc('\n', monout);
553     }
554     adr++; dest++;
555     }
556    
557     if (num & 7)
558     fputc('\n', monout);
559     fprintf(monout, "%d byte(s) different\n", num);
560     }
561    
562    
563     /*
564     * Search for byte string
565     * h start end bytestring
566     */
567    
568     void hunt(void)
569     {
570 gbeauche 1.11 uintptr adr, end_adr, len;
571 cebix 1.16 uint8 *str;
572 cebix 1.1 int num = 0;
573    
574     if (!mon_expression(&adr))
575     return;
576     if (!mon_expression(&end_adr))
577     return;
578     if (!byte_string(str, len))
579     return;
580    
581     while ((adr+len-1) <= end_adr && !mon_aborted()) {
582     uint32 i;
583    
584     for (i=0; i<len; i++)
585     if (mon_read_byte(adr + i) != str[i])
586     break;
587    
588     if (i == len) {
589 cebix 1.19 fprintf(monout, "%0*lx ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
590 cebix 1.1 num++;
591     if (num == 1)
592     mon_dot_address = adr;
593     if (!(num & 7))
594     fputc('\n', monout);
595     }
596     adr++;
597     }
598 cebix 1.16
599     free(str);
600 cebix 1.1
601     if (num & 7)
602     fputc('\n', monout);
603     fprintf(monout, "Found %d occurrences\n", num);
604     }
605    
606    
607     /*
608     * Load data
609     * [ start "file"
610     */
611    
612     void load_data(void)
613     {
614 gbeauche 1.11 uintptr start_adr;
615 cebix 1.1 FILE *file;
616     int fc;
617    
618     if (!mon_expression(&start_adr))
619     return;
620     if (mon_token == T_END) {
621     mon_error("Missing file name");
622     return;
623     }
624     if (mon_token != T_STRING) {
625     mon_error("'\"' around file name expected");
626     return;
627     }
628     mon_get_token();
629     if (mon_token != T_END) {
630     mon_error("Too many arguments");
631     return;
632     }
633    
634     if (!(file = fopen(mon_string, "rb")))
635     mon_error("Unable to open file");
636     else {
637 gbeauche 1.11 uintptr adr = start_adr;
638 cebix 1.1
639     while ((fc = fgetc(file)) != EOF)
640     mon_write_byte(adr++, fc);
641     fclose(file);
642    
643 cebix 1.19 fprintf(monerr, "%08x bytes read from %0*lx to %0*lx\n", adr - start_adr, int(2 * sizeof(adr)), mon_use_real_mem ? start_adr : start_adr % mon_mem_size, int(2 * sizeof(adr)), mon_use_real_mem ? adr-1 : (adr-1) % mon_mem_size);
644 cebix 1.1 mon_dot_address = adr;
645     }
646     }
647    
648    
649     /*
650     * Save data
651     * ] start size "file"
652     */
653    
654     void save_data(void)
655     {
656 gbeauche 1.11 uintptr start_adr, size;
657 cebix 1.1 FILE *file;
658    
659     if (!mon_expression(&start_adr))
660     return;
661     if (!mon_expression(&size))
662     return;
663     if (mon_token == T_END) {
664     mon_error("Missing file name");
665     return;
666     }
667     if (mon_token != T_STRING) {
668     mon_error("'\"' around file name expected");
669     return;
670     }
671     mon_get_token();
672     if (mon_token != T_END) {
673     mon_error("Too many arguments");
674     return;
675     }
676    
677     if (!(file = fopen(mon_string, "wb")))
678     mon_error("Unable to create file");
679     else {
680 gbeauche 1.11 uintptr adr = start_adr, end_adr = start_adr + size - 1;
681 cebix 1.1
682     while (adr <= end_adr)
683     fputc(mon_read_byte(adr++), file);
684     fclose(file);
685    
686 cebix 1.19 fprintf(monerr, "%08x bytes written from %0*lx to %0*lx\n", size, int(2 * sizeof(adr)), mon_use_real_mem ? start_adr : start_adr % mon_mem_size, int(2 * sizeof(adr)), mon_use_real_mem ? end_adr : end_adr % mon_mem_size);
687 cebix 1.1 }
688     }