ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_cmd.cpp
Revision: 1.15
Committed: 2003-09-27T20:33:06Z (21 years, 1 month ago) by cebix
Branch: MAIN
Changes since 1.14: +1 -1 lines
Log Message:
2002 -> 2003

File Contents

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