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 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

# 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 uint8 *p = (uint8 *)mon_string;
86 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 mon_get_token();
91 } else if (mon_expression(&value)) {
92 str = (uint8 *)realloc(str, (len + GRANULARITY) & ~(GRANULARITY - 1));
93 str[len] = value;
94 len++;
95 } else {
96 if (str)
97 free(str);
98 return false;
99 }
100
101 } else if (mon_token == T_END) {
102 return true;
103 } else {
104 mon_error("',' expected");
105 if (str)
106 free(str);
107 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 fprintf(monout, "cxmon V" VERSION "\n");
131 }
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 uintptr val;
174
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 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 fprintf(monout, "Char : '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val));
188 } else {
189 fprintf(monout, "Hex : $%08x\n"
190 "Dec : %d\n", val, val);
191 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 uintptr adr, end_adr;
226 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 fprintf(monout, "%0*lx:", 2 * sizeof(adr), mon_use_real_mem ? adr: adr % mon_mem_size);
235 for (int i=0; i<MEMDUMP_BPL; i++, adr++) {
236 if (i % 4 == 0)
237 fprintf(monout, " %08x", mon_read_word(adr));
238 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 uintptr adr, end_adr;
257 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 fprintf(monout, "%0*lx:", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
266 for (int i=0; i<ASCIIDUMP_BPL; i++, adr++)
267 str[i] = char2print(mon_read_byte(adr));
268 fprintf(monout, " '%s'\n", str);
269 }
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 uintptr adr, end_adr;
283 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 fprintf(monout, "%0*lx:", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
292 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 }
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 * d8086 [start [end]]
311 */
312
313 enum CPUType {
314 CPU_PPC,
315 CPU_6502,
316 CPU_680x0,
317 CPU_Z80,
318 CPU_80x86_32,
319 CPU_80x86_16,
320 CPU_x86_64
321 };
322
323 static void disassemble(CPUType type)
324 {
325 uintptr adr, end_adr;
326
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 fprintf(monout, "%0*lx: %08x\t", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size, w);
335 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 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
346 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 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
353 adr += disass_68k(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
354 }
355 break;
356
357 case CPU_Z80:
358 while (adr <= end_adr && !mon_aborted()) {
359 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
360 adr += disass_z80(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
361 }
362 break;
363
364 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 case CPU_80x86_32:
372 while (adr <= end_adr && !mon_aborted()) {
373 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 }
376 break;
377
378 case CPU_80x86_16:
379 while (adr <= end_adr && !mon_aborted()) {
380 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 }
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 void disassemble_z80(void)
404 {
405 disassemble(CPU_Z80);
406 }
407
408 void disassemble_80x86_32(void)
409 {
410 disassemble(CPU_80x86_32);
411 }
412
413 void disassemble_80x86_16(void)
414 {
415 disassemble(CPU_80x86_16);
416 }
417
418 void disassemble_x86_64(void)
419 {
420 disassemble(CPU_x86_64);
421 }
422
423
424 /*
425 * Modify memory
426 * : addr bytestring
427 */
428
429 void modify(void)
430 {
431 uintptr adr, len, src_adr = 0;
432 uint8 *str;
433
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 mon_dot_address = adr;
442
443 free(str);
444 }
445
446
447 /*
448 * Fill
449 * f start end bytestring
450 */
451
452 void fill(void)
453 {
454 uintptr adr, end_adr, len, src_adr = 0;
455 uint8 *str;
456
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
467 free(str);
468 }
469
470
471 /*
472 * Transfer memory
473 * t start end dest
474 */
475
476 void transfer(void)
477 {
478 uintptr adr, end_adr, dest;
479 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 uintptr adr, end_adr, dest;
513 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 fprintf(monout, "%0*lx ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
529 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 uintptr adr, end_adr, len;
550 uint8 *str;
551 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 fprintf(monout, "%0*lx ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
569 num++;
570 if (num == 1)
571 mon_dot_address = adr;
572 if (!(num & 7))
573 fputc('\n', monout);
574 }
575 adr++;
576 }
577
578 free(str);
579
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 uintptr start_adr;
594 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 uintptr adr = start_adr;
617
618 while ((fc = fgetc(file)) != EOF)
619 mon_write_byte(adr++, fc);
620 fclose(file);
621
622 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 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 uintptr start_adr, size;
636 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 uintptr adr = start_adr, end_adr = start_adr + size - 1;
660
661 while (adr <= end_adr)
662 fputc(mon_read_byte(adr++), file);
663 fclose(file);
664
665 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 }
667 }