ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_cmd.cpp
Revision: 1.20
Committed: 2007-06-07T09:51:56Z (17 years, 5 months ago) by gbeauche
Branch: MAIN
Changes since 1.19: +21 -1 lines
Log Message:
Add MIPS disassembler invoked as "dm" and "dmel" (little-endian) for now.

File Contents

# Content
1 /*
2 * mon_cmd.cpp - cxmon standard commands
3 *
4 * cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig
5 *
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 */
20
21 #include "sysdeps.h"
22
23 #include <stdlib.h>
24
25 #include "mon.h"
26 #include "mon_cmd.h"
27 #include "mon_disass.h"
28
29 #ifndef VERSION
30 #define VERSION "3"
31 #endif
32
33
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 static bool range_args(uintptr *adr, uintptr *end_adr, uint32 def_range)
44 {
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 static bool byte_string(uint8 *&str, uintptr &len)
71 {
72 uintptr value;
73
74 static const int GRANULARITY = 16; // must be a power of 2
75 str = NULL;
76 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 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 mon_get_token();
90 } else if (mon_expression(&value)) {
91 str = (uint8 *)realloc(str, (len + GRANULARITY) & ~(GRANULARITY - 1));
92 str[len] = value;
93 len++;
94 } else {
95 if (str)
96 free(str);
97 return false;
98 }
99
100 } else if (mon_token == T_END) {
101 return true;
102 } else {
103 mon_error("',' expected");
104 if (str)
105 free(str);
106 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 fprintf(monout, "cxmon V" VERSION "\n");
130 }
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 uintptr val;
173
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 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 fprintf(monout, "Char : '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val));
187 } else {
188 fprintf(monout, "Hex : $%08x\n"
189 "Dec : %d\n", val, val);
190 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 uintptr adr, end_adr;
225 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 fprintf(monout, "%0*lx:", int(2 * sizeof(adr)), mon_use_real_mem ? adr: adr % mon_mem_size);
234 for (int i=0; i<MEMDUMP_BPL; i++, adr++) {
235 if (i % 4 == 0)
236 fprintf(monout, " %08x", mon_read_word(adr));
237 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 uintptr adr, end_adr;
256 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 fprintf(monout, "%0*lx:", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
265 for (int i=0; i<ASCIIDUMP_BPL; i++, adr++)
266 str[i] = char2print(mon_read_byte(adr));
267 fprintf(monout, " '%s'\n", str);
268 }
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 uintptr adr, end_adr;
282 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 fprintf(monout, "%0*lx:", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
291 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 }
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 * d8086 [start [end]]
310 */
311
312 enum CPUType {
313 CPU_PPC,
314 CPU_6502,
315 CPU_680x0,
316 CPU_Z80,
317 CPU_80x86_32,
318 CPU_80x86_16,
319 CPU_x86_64,
320 CPU_MIPS,
321 CPU_MIPS_LITTLE,
322 };
323
324 static void disassemble(CPUType type)
325 {
326 uintptr adr, end_adr;
327
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 fprintf(monout, "%0*lx: %08x\t", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size, w);
336 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 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
347 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 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
354 adr += disass_68k(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
355 }
356 break;
357
358 case CPU_Z80:
359 while (adr <= end_adr && !mon_aborted()) {
360 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
361 adr += disass_z80(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
362 }
363 break;
364
365 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 case CPU_x86_64:
374 while (adr <= end_adr && !mon_aborted()) {
375 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
376 adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 64);
377 }
378 break;
379
380 case CPU_80x86_32:
381 while (adr <= end_adr && !mon_aborted()) {
382 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
383 adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 32);
384 }
385 break;
386
387 case CPU_80x86_16:
388 while (adr <= end_adr && !mon_aborted()) {
389 fprintf(monout, "%0*lx: ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
390 adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 16);
391 }
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 void disassemble_z80(void)
413 {
414 disassemble(CPU_Z80);
415 }
416
417 void disassemble_80x86_32(void)
418 {
419 disassemble(CPU_80x86_32);
420 }
421
422 void disassemble_80x86_16(void)
423 {
424 disassemble(CPU_80x86_16);
425 }
426
427 void disassemble_x86_64(void)
428 {
429 disassemble(CPU_x86_64);
430 }
431
432 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
443 /*
444 * Modify memory
445 * : addr bytestring
446 */
447
448 void modify(void)
449 {
450 uintptr adr, len, src_adr = 0;
451 uint8 *str;
452
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 mon_dot_address = adr;
461
462 free(str);
463 }
464
465
466 /*
467 * Fill
468 * f start end bytestring
469 */
470
471 void fill(void)
472 {
473 uintptr adr, end_adr, len, src_adr = 0;
474 uint8 *str;
475
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 while (adr <= end_adr)
484 mon_write_byte(adr++, str[src_adr++ % len]);
485
486 free(str);
487 }
488
489
490 /*
491 * Transfer memory
492 * t start end dest
493 */
494
495 void transfer(void)
496 {
497 uintptr adr, end_adr, dest;
498 int num;
499
500 if (!mon_expression(&adr))
501 return;
502 if (!mon_expression(&end_adr))
503 return;
504 if (!mon_expression(&dest))
505 return;
506 if (mon_token != T_END) {
507 mon_error("Too many arguments");
508 return;
509 }
510
511 num = end_adr - adr + 1;
512
513 if (dest < adr)
514 for (int i=0; i<num; i++)
515 mon_write_byte(dest++, mon_read_byte(adr++));
516 else {
517 dest += end_adr - adr;
518 for (int i=0; i<num; i++)
519 mon_write_byte(dest--, mon_read_byte(end_adr--));
520 }
521 }
522
523
524 /*
525 * Compare
526 * c start end dest
527 */
528
529 void compare(void)
530 {
531 uintptr adr, end_adr, dest;
532 int num = 0;
533
534 if (!mon_expression(&adr))
535 return;
536 if (!mon_expression(&end_adr))
537 return;
538 if (!mon_expression(&dest))
539 return;
540 if (mon_token != T_END) {
541 mon_error("Too many arguments");
542 return;
543 }
544
545 while (adr <= end_adr && !mon_aborted()) {
546 if (mon_read_byte(adr) != mon_read_byte(dest)) {
547 fprintf(monout, "%0*lx ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
548 num++;
549 if (!(num & 7))
550 fputc('\n', monout);
551 }
552 adr++; dest++;
553 }
554
555 if (num & 7)
556 fputc('\n', monout);
557 fprintf(monout, "%d byte(s) different\n", num);
558 }
559
560
561 /*
562 * Search for byte string
563 * h start end bytestring
564 */
565
566 void hunt(void)
567 {
568 uintptr adr, end_adr, len;
569 uint8 *str;
570 int num = 0;
571
572 if (!mon_expression(&adr))
573 return;
574 if (!mon_expression(&end_adr))
575 return;
576 if (!byte_string(str, len))
577 return;
578
579 while ((adr+len-1) <= end_adr && !mon_aborted()) {
580 uint32 i;
581
582 for (i=0; i<len; i++)
583 if (mon_read_byte(adr + i) != str[i])
584 break;
585
586 if (i == len) {
587 fprintf(monout, "%0*lx ", int(2 * sizeof(adr)), mon_use_real_mem ? adr : adr % mon_mem_size);
588 num++;
589 if (num == 1)
590 mon_dot_address = adr;
591 if (!(num & 7))
592 fputc('\n', monout);
593 }
594 adr++;
595 }
596
597 free(str);
598
599 if (num & 7)
600 fputc('\n', monout);
601 fprintf(monout, "Found %d occurrences\n", num);
602 }
603
604
605 /*
606 * Load data
607 * [ start "file"
608 */
609
610 void load_data(void)
611 {
612 uintptr start_adr;
613 FILE *file;
614 int fc;
615
616 if (!mon_expression(&start_adr))
617 return;
618 if (mon_token == T_END) {
619 mon_error("Missing file name");
620 return;
621 }
622 if (mon_token != T_STRING) {
623 mon_error("'\"' around file name expected");
624 return;
625 }
626 mon_get_token();
627 if (mon_token != T_END) {
628 mon_error("Too many arguments");
629 return;
630 }
631
632 if (!(file = fopen(mon_string, "rb")))
633 mon_error("Unable to open file");
634 else {
635 uintptr adr = start_adr;
636
637 while ((fc = fgetc(file)) != EOF)
638 mon_write_byte(adr++, fc);
639 fclose(file);
640
641 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);
642 mon_dot_address = adr;
643 }
644 }
645
646
647 /*
648 * Save data
649 * ] start size "file"
650 */
651
652 void save_data(void)
653 {
654 uintptr start_adr, size;
655 FILE *file;
656
657 if (!mon_expression(&start_adr))
658 return;
659 if (!mon_expression(&size))
660 return;
661 if (mon_token == T_END) {
662 mon_error("Missing file name");
663 return;
664 }
665 if (mon_token != T_STRING) {
666 mon_error("'\"' around file name expected");
667 return;
668 }
669 mon_get_token();
670 if (mon_token != T_END) {
671 mon_error("Too many arguments");
672 return;
673 }
674
675 if (!(file = fopen(mon_string, "wb")))
676 mon_error("Unable to create file");
677 else {
678 uintptr adr = start_adr, end_adr = start_adr + size - 1;
679
680 while (adr <= end_adr)
681 fputc(mon_read_byte(adr++), file);
682 fclose(file);
683
684 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);
685 }
686 }