/[gxemul]/upstream/0.4.4.1/src/debugger/debugger_cmds.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.4.1/src/debugger/debugger_cmds.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 37 - (show annotations)
Mon Oct 8 16:21:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 31571 byte(s)
0.4.4.1
1 /*
2 * Copyright (C) 2004-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: debugger_cmds.c,v 1.10 2006/12/30 13:30:56 debug Exp $
29 *
30 * Debugger commands. Included from debugger.c.
31 */
32
33
34 /*
35 * debugger_cmd_allsettings():
36 */
37 static void debugger_cmd_allsettings(struct machine *m, char *cmd_line)
38 {
39 settings_debugdump(global_settings, GLOBAL_SETTINGS_NAME, 1);
40 }
41
42
43 /*
44 * debugger_cmd_breakpoint():
45 *
46 * TODO: automagic "expansion" for the subcommand names (s => show).
47 */
48 static void debugger_cmd_breakpoint(struct machine *m, char *cmd_line)
49 {
50 int i, res;
51
52 while (cmd_line[0] != '\0' && cmd_line[0] == ' ')
53 cmd_line ++;
54
55 if (cmd_line[0] == '\0') {
56 printf("syntax: breakpoint subcmd [args...]\n");
57 printf("Available subcmds (and args) are:\n");
58 printf(" add addr add a breakpoint for address addr\n");
59 printf(" delete x delete breakpoint nr x\n");
60 printf(" show show current breakpoints\n");
61 return;
62 }
63
64 if (strcmp(cmd_line, "show") == 0) {
65 if (m->n_breakpoints == 0)
66 printf("No breakpoints set.\n");
67 for (i=0; i<m->n_breakpoints; i++)
68 show_breakpoint(m, i);
69 return;
70 }
71
72 if (strncmp(cmd_line, "delete ", 7) == 0) {
73 int x = atoi(cmd_line + 7);
74
75 if (m->n_breakpoints == 0) {
76 printf("No breakpoints set.\n");
77 return;
78 }
79 if (x < 0 || x >= m->n_breakpoints) {
80 printf("Invalid breakpoint nr %i. Use 'breakpoint "
81 "show' to see the current breakpoints.\n", x);
82 return;
83 }
84
85 free(m->breakpoint_string[x]);
86
87 for (i=x; i<m->n_breakpoints-1; i++) {
88 m->breakpoint_addr[i] = m->breakpoint_addr[i+1];
89 m->breakpoint_string[i] = m->breakpoint_string[i+1];
90 m->breakpoint_flags[i] = m->breakpoint_flags[i+1];
91 }
92 m->n_breakpoints --;
93
94 /* Clear translations: */
95 for (i=0; i<m->ncpus; i++)
96 if (m->cpus[i]->translation_cache != NULL)
97 cpu_create_or_reset_tc(m->cpus[i]);
98 return;
99 }
100
101 if (strncmp(cmd_line, "add ", 4) == 0) {
102 uint64_t tmp;
103 size_t breakpoint_buf_len;
104
105 if (m->n_breakpoints >= MAX_BREAKPOINTS) {
106 printf("Too many breakpoints. (You need to recompile"
107 " gxemul to increase this. Max = %i.)\n",
108 MAX_BREAKPOINTS);
109 return;
110 }
111
112 i = m->n_breakpoints;
113
114 res = debugger_parse_expression(m, cmd_line + 4, 0, &tmp);
115 if (!res) {
116 printf("Couldn't parse '%s'\n", cmd_line + 4);
117 return;
118 }
119
120 breakpoint_buf_len = strlen(cmd_line+4) + 1;
121 m->breakpoint_string[i] = malloc(breakpoint_buf_len);
122 if (m->breakpoint_string[i] == NULL) {
123 printf("out of memory in debugger_cmd_breakpoint()\n");
124 exit(1);
125 }
126 strlcpy(m->breakpoint_string[i], cmd_line+4,
127 breakpoint_buf_len);
128 m->breakpoint_addr[i] = tmp;
129 m->breakpoint_flags[i] = 0;
130
131 m->n_breakpoints ++;
132 show_breakpoint(m, i);
133
134 /* Clear translations: */
135 for (i=0; i<m->ncpus; i++)
136 if (m->cpus[i]->translation_cache != NULL)
137 cpu_create_or_reset_tc(m->cpus[i]);
138 return;
139 }
140
141 printf("Unknown breakpoint subcommand.\n");
142 }
143
144
145 /*
146 * debugger_cmd_continue():
147 */
148 static void debugger_cmd_continue(struct machine *m, char *cmd_line)
149 {
150 if (*cmd_line) {
151 printf("syntax: continue\n");
152 return;
153 }
154
155 exit_debugger = 1;
156 }
157
158
159 /*
160 * debugger_cmd_device():
161 */
162 static void debugger_cmd_device(struct machine *m, char *cmd_line)
163 {
164 int i;
165 struct memory *mem;
166 struct cpu *c;
167
168 if (cmd_line[0] == '\0')
169 goto return_help;
170
171 if (m->cpus == NULL) {
172 printf("No cpus (?)\n");
173 return;
174 }
175 c = m->cpus[m->bootstrap_cpu];
176 if (c == NULL) {
177 printf("m->cpus[m->bootstrap_cpu] = NULL\n");
178 return;
179 }
180 mem = m->cpus[m->bootstrap_cpu]->mem;
181
182 if (m->cpus == NULL) {
183 printf("No cpus (?)\n");
184 return;
185 }
186 c = m->cpus[m->bootstrap_cpu];
187 if (c == NULL) {
188 printf("m->cpus[m->bootstrap_cpu] = NULL\n");
189 return;
190 }
191 mem = m->cpus[m->bootstrap_cpu]->mem;
192
193 if (strcmp(cmd_line, "all") == 0) {
194 device_dumplist();
195 } else if (strncmp(cmd_line, "add ", 4) == 0) {
196 device_add(m, cmd_line+4);
197 } else if (strcmp(cmd_line, "consoles") == 0) {
198 console_debug_dump(m);
199 } else if (strncmp(cmd_line, "remove ", 7) == 0) {
200 i = atoi(cmd_line + 7);
201 if (i==0 && cmd_line[7]!='0') {
202 printf("Weird device number. Use 'device list'.\n");
203 } else
204 memory_device_remove(m->memory, i);
205 } else if (strcmp(cmd_line, "list") == 0) {
206 if (mem->n_mmapped_devices == 0)
207 printf("No memory-mapped devices in this machine.\n");
208
209 for (i=0; i<mem->n_mmapped_devices; i++) {
210 printf("%2i: %25s @ 0x%011"PRIx64", len = 0x%"PRIx64,
211 i, mem->devices[i].name,
212 (uint64_t) mem->devices[i].baseaddr,
213 (uint64_t) mem->devices[i].length);
214
215 if (mem->devices[i].flags) {
216 printf(" (");
217 if (mem->devices[i].flags & DM_DYNTRANS_OK)
218 printf("DYNTRANS R");
219 if (mem->devices[i].flags &DM_DYNTRANS_WRITE_OK)
220 printf("+W");
221 printf(")");
222 }
223 printf("\n");
224 }
225 } else
226 goto return_help;
227
228 return;
229
230 return_help:
231 printf("syntax: devices cmd [...]\n");
232 printf("Available cmds are:\n");
233 printf(" add name_and_params add a device to the current "
234 "machine\n");
235 printf(" all list all registered devices\n");
236 printf(" consoles list all slave consoles\n");
237 printf(" list list memory-mapped devices in the"
238 " current machine\n");
239 printf(" remove x remove device nr x from the "
240 "current machine\n");
241 }
242
243
244 /*
245 * debugger_cmd_dump():
246 *
247 * Dump emulated memory in hex and ASCII.
248 *
249 * syntax: dump [addr [endaddr]]
250 */
251 static void debugger_cmd_dump(struct machine *m, char *cmd_line)
252 {
253 uint64_t addr, addr_start, addr_end;
254 struct cpu *c;
255 struct memory *mem;
256 char *p = NULL;
257 int x, r;
258
259 if (cmd_line[0] != '\0') {
260 uint64_t tmp;
261 char *tmps = strdup(cmd_line);
262
263 /* addr: */
264 p = strchr(tmps, ' ');
265 if (p != NULL)
266 *p = '\0';
267 r = debugger_parse_expression(m, tmps, 0, &tmp);
268 free(tmps);
269
270 if (r == PARSE_NOMATCH || r == PARSE_MULTIPLE) {
271 printf("Unparsable address: %s\n", cmd_line);
272 return;
273 } else {
274 last_dump_addr = tmp;
275 }
276
277 p = strchr(cmd_line, ' ');
278 }
279
280 if (m->cpus == NULL) {
281 printf("No cpus (?)\n");
282 return;
283 }
284 c = m->cpus[m->bootstrap_cpu];
285 if (c == NULL) {
286 printf("m->cpus[m->bootstrap_cpu] = NULL\n");
287 return;
288 }
289 mem = m->cpus[m->bootstrap_cpu]->mem;
290
291 addr_start = last_dump_addr;
292
293 if (addr_start == MAGIC_UNTOUCHED)
294 addr_start = c->pc;
295
296 addr_end = addr_start + 16 * 16;
297
298 /* endaddr: */
299 if (p != NULL) {
300 while (*p == ' ' && *p)
301 p++;
302 r = debugger_parse_expression(m, p, 0, &addr_end);
303 if (r == PARSE_NOMATCH || r == PARSE_MULTIPLE) {
304 printf("Unparsable address: %s\n", cmd_line);
305 return;
306 }
307 }
308
309 addr = addr_start & ~0xf;
310
311 ctrl_c = 0;
312
313 while (addr < addr_end) {
314 unsigned char buf[16];
315 memset(buf, 0, sizeof(buf));
316 r = c->memory_rw(c, mem, addr, &buf[0], sizeof(buf),
317 MEM_READ, CACHE_NONE | NO_EXCEPTIONS);
318
319 if (c->is_32bit)
320 printf("0x%08"PRIx32" ", (uint32_t) addr);
321 else
322 printf("0x%016"PRIx64" ", (uint64_t) addr);
323
324 if (r == MEMORY_ACCESS_FAILED)
325 printf("(memory access failed)\n");
326 else {
327 for (x=0; x<16; x++) {
328 if (addr + x >= addr_start &&
329 addr + x < addr_end)
330 printf("%02x%s", buf[x],
331 (x&3)==3? " " : "");
332 else
333 printf(" %s", (x&3)==3? " " : "");
334 }
335 printf(" ");
336 for (x=0; x<16; x++) {
337 if (addr + x >= addr_start &&
338 addr + x < addr_end)
339 printf("%c", (buf[x]>=' ' &&
340 buf[x]<127)? buf[x] : '.');
341 else
342 printf(" ");
343 }
344 printf("\n");
345 }
346
347 if (ctrl_c)
348 return;
349
350 addr += sizeof(buf);
351 }
352
353 last_dump_addr = addr_end;
354
355 strlcpy(repeat_cmd, "dump", MAX_CMD_BUFLEN);
356 }
357
358
359 /*
360 * debugger_cmd_emuls():
361 *
362 * Dump info about all current emuls.
363 */
364 static void debugger_cmd_emuls(struct machine *m, char *cmd_line)
365 {
366 int i, iadd = DEBUG_INDENTATION;
367
368 if (*cmd_line) {
369 printf("syntax: emuls\n");
370 return;
371 }
372
373 for (i=0; i<debugger_n_emuls; i++) {
374 struct emul *e = debugger_emuls[i];
375
376 if (e == NULL)
377 continue;
378
379 debug("emulation %i: \"%s\"\n", i,
380 e->name == NULL? "(no name)" : e->name);
381 debug_indentation(iadd);
382
383 emul_dumpinfo(e);
384
385 debug_indentation(-iadd);
386 }
387 }
388
389
390 /*
391 * debugger_cmd_focus():
392 *
393 * Changes focus to specific cpu, in a specific machine (in a specific
394 * emulation).
395 */
396 static void debugger_cmd_focus(struct machine *m, char *cmd_line)
397 {
398 int x = -1, y = -1, z = -1;
399 char *p, *p2;
400
401 if (!cmd_line[0]) {
402 printf("syntax: focus x[,y,[,z]]\n");
403 printf("where x (cpu id), y (machine number), and z (emul "
404 "number) are integers as\nreported by the 'emuls'"
405 " command.\n");
406 goto print_current_focus_and_return;
407 }
408
409 x = atoi(cmd_line);
410 p = strchr(cmd_line, ',');
411 if (p == cmd_line) {
412 printf("No cpu number specified?\n");
413 return;
414 }
415
416 if (p != NULL) {
417 y = atoi(p+1);
418 p2 = strchr(p+1, ',');
419 if (p2 == p+1) {
420 printf("No machine number specified?\n");
421 return;
422 }
423
424 if (p2 != NULL)
425 z = atoi(p2 + 1);
426 }
427
428 if (z != -1) {
429 /* Change emul: */
430 if (z < 0 || z >= debugger_n_emuls) {
431 printf("Invalid emul number: %i\n", z);
432 return;
433 }
434
435 debugger_cur_emul = z;
436 debugger_emul = debugger_emuls[z];
437
438 /* This is just in case the machine change below fails... */
439 debugger_machine = debugger_emul->machines[0];
440 }
441
442 if (y != -1) {
443 /* Change machine: */
444 if (y < 0 || y >= debugger_emul->n_machines) {
445 printf("Invalid machine number: %i\n", y);
446 return;
447 }
448
449 debugger_cur_machine = y;
450 debugger_machine = debugger_emul->machines[y];
451 }
452
453 /* Change cpu: */
454 if (x < 0 || x >= debugger_machine->ncpus) {
455 printf("Invalid cpu number: %i\n", x);
456 return;
457 }
458
459 debugger_cur_cpu = x;
460
461 print_current_focus_and_return:
462 if (debugger_n_emuls > 1)
463 printf("current emul (%i): \"%s\"\n",
464 debugger_cur_emul, debugger_emul->name == NULL?
465 "(no name)" : debugger_emul->name);
466
467 if (debugger_emul->n_machines > 1)
468 printf("current machine (%i): \"%s\"\n",
469 debugger_cur_machine, debugger_machine->name == NULL?
470 "(no name)" : debugger_machine->name);
471
472 printf("current cpu (%i)\n", debugger_cur_cpu);
473 }
474
475
476 /* This is defined below. */
477 static void debugger_cmd_help(struct machine *m, char *cmd_line);
478
479
480 /*
481 * debugger_cmd_itrace():
482 */
483 static void debugger_cmd_itrace(struct machine *m, char *cmd_line)
484 {
485 if (*cmd_line) {
486 printf("syntax: itrace\n");
487 return;
488 }
489
490 old_instruction_trace = 1 - old_instruction_trace;
491 printf("instruction_trace = %s\n", old_instruction_trace? "ON":"OFF");
492 /* TODO: how to preserve quiet_mode? */
493 old_quiet_mode = 0;
494 printf("quiet_mode = %s\n", old_quiet_mode? "ON" : "OFF");
495 }
496
497
498 /*
499 * debugger_cmd_lookup():
500 */
501 static void debugger_cmd_lookup(struct machine *m, char *cmd_line)
502 {
503 uint64_t addr;
504 int res;
505 char *symbol;
506 uint64_t offset;
507
508 if (cmd_line[0] == '\0') {
509 printf("syntax: lookup name|addr\n");
510 return;
511
512 }
513
514 /* Addresses never need to be given in decimal form anyway,
515 so assuming hex here will be ok. */
516 addr = strtoull(cmd_line, NULL, 16);
517
518 if (addr == 0) {
519 uint64_t newaddr;
520 res = get_symbol_addr(&m->symbol_context,
521 cmd_line, &newaddr);
522 if (!res) {
523 printf("lookup for '%s' failed\n", cmd_line);
524 return;
525 }
526 printf("%s = 0x", cmd_line);
527 if (m->cpus[0]->is_32bit)
528 printf("%08"PRIx32"\n", (uint32_t) newaddr);
529 else
530 printf("%016"PRIx64"\n", (uint64_t) newaddr);
531 return;
532 }
533
534 symbol = get_symbol_name(&m->symbol_context, addr, &offset);
535
536 if (symbol != NULL) {
537 if (m->cpus[0]->is_32bit)
538 printf("0x%08"PRIx32, (uint32_t) addr);
539 else
540 printf("0x%016"PRIx64, (uint64_t) addr);
541 printf(" = %s\n", symbol);
542 } else
543 printf("lookup for '%s' failed\n", cmd_line);
544 }
545
546
547 /*
548 * debugger_cmd_machine():
549 *
550 * Dump info about the currently focused machine.
551 */
552 static void debugger_cmd_machine(struct machine *m, char *cmd_line)
553 {
554 int iadd = DEBUG_INDENTATION;
555
556 if (*cmd_line) {
557 printf("syntax: machine\n");
558 return;
559 }
560
561 debug("machine \"%s\":\n", m->name);
562 debug_indentation(iadd);
563 machine_dumpinfo(m);
564 debug_indentation(-iadd);
565 }
566
567
568 /*
569 * debugger_cmd_ninstrs():
570 */
571 static void debugger_cmd_ninstrs(struct machine *m, char *cmd_line)
572 {
573 int toggle = 1;
574 int previous_mode = m->show_nr_of_instructions;
575
576 if (cmd_line[0] != '\0') {
577 while (cmd_line[0] != '\0' && cmd_line[0] == ' ')
578 cmd_line ++;
579 switch (cmd_line[0]) {
580 case '0':
581 toggle = 0;
582 m->show_nr_of_instructions = 0;
583 break;
584 case '1':
585 toggle = 0;
586 m->show_nr_of_instructions = 1;
587 break;
588 case 'o':
589 case 'O':
590 toggle = 0;
591 switch (cmd_line[1]) {
592 case 'n':
593 case 'N':
594 m->show_nr_of_instructions = 1;
595 break;
596 default:
597 m->show_nr_of_instructions = 0;
598 }
599 break;
600 default:
601 printf("syntax: trace [on|off]\n");
602 return;
603 }
604 }
605
606 if (toggle)
607 m->show_nr_of_instructions = !m->show_nr_of_instructions;
608
609 printf("show_nr_of_instructions = %s",
610 m->show_nr_of_instructions? "ON" : "OFF");
611 if (m->show_nr_of_instructions != previous_mode)
612 printf(" (was: %s)", previous_mode? "ON" : "OFF");
613 printf("\n");
614 }
615
616
617 /*
618 * debugger_cmd_pause():
619 */
620 static void debugger_cmd_pause(struct machine *m, char *cmd_line)
621 {
622 int cpuid = -1;
623
624 if (cmd_line[0] != '\0')
625 cpuid = atoi(cmd_line);
626 else {
627 printf("syntax: pause cpuid\n");
628 return;
629 }
630
631 if (cpuid < 0 || cpuid >= m->ncpus) {
632 printf("cpu%i doesn't exist.\n", cpuid);
633 return;
634 }
635
636 m->cpus[cpuid]->running ^= 1;
637
638 printf("cpu%i (%s) in machine \"%s\" is now %s\n", cpuid,
639 m->cpus[cpuid]->name, m->name,
640 m->cpus[cpuid]->running? "RUNNING" : "STOPPED");
641 }
642
643
644 /*
645 * debugger_cmd_print():
646 */
647 static void debugger_cmd_print(struct machine *m, char *cmd_line)
648 {
649 int res;
650 uint64_t tmp;
651
652 while (cmd_line[0] != '\0' && cmd_line[0] == ' ')
653 cmd_line ++;
654
655 if (cmd_line[0] == '\0') {
656 printf("syntax: print expr\n");
657 return;
658 }
659
660 res = debugger_parse_expression(m, cmd_line, 0, &tmp);
661 switch (res) {
662 case PARSE_NOMATCH:
663 printf("No match.\n");
664 break;
665 case PARSE_MULTIPLE:
666 printf("Multiple matches. Try prefixing with %%, $, or @.\n");
667 break;
668 case PARSE_SETTINGS:
669 printf("%s = 0x%"PRIx64"\n", cmd_line, (uint64_t)tmp);
670 break;
671 case PARSE_SYMBOL:
672 if (m->cpus[0]->is_32bit)
673 printf("%s = 0x%08"PRIx32"\n", cmd_line, (uint32_t)tmp);
674 else
675 printf("%s = 0x%016"PRIx64"\n", cmd_line,(uint64_t)tmp);
676 break;
677 case PARSE_NUMBER:
678 printf("0x%"PRIx64"\n", (uint64_t) tmp);
679 break;
680 }
681 }
682
683
684 /*
685 * debugger_cmd_put():
686 */
687 static void debugger_cmd_put(struct machine *m, char *cmd_line)
688 {
689 static char put_type = ' '; /* Remembered across multiple calls. */
690 char copy[200];
691 int res, syntax_ok = 0;
692 char *p, *p2, *q = NULL;
693 uint64_t addr, data;
694 unsigned char a_byte;
695
696 strncpy(copy, cmd_line, sizeof(copy));
697 copy[sizeof(copy)-1] = '\0';
698
699 /* syntax: put [b|h|w|d|q] addr, data */
700
701 p = strchr(copy, ',');
702 if (p != NULL) {
703 *p++ = '\0';
704 while (*p == ' ' && *p)
705 p++;
706 while (strlen(copy) >= 1 &&
707 copy[strlen(copy) - 1] == ' ')
708 copy[strlen(copy) - 1] = '\0';
709
710 /* printf("L = '%s', R = '%s'\n", copy, p); */
711
712 q = copy;
713 p2 = strchr(q, ' ');
714
715 if (p2 != NULL) {
716 *p2 = '\0';
717 if (strlen(q) != 1) {
718 printf("Invalid type '%s'\n", q);
719 return;
720 }
721 put_type = *q;
722 q = p2 + 1;
723 }
724
725 /* printf("type '%c', L '%s', R '%s'\n", put_type, q, p); */
726 syntax_ok = 1;
727 }
728
729 if (!syntax_ok) {
730 printf("syntax: put [b|h|w|d|q] addr, data\n");
731 printf(" b byte (8 bits)\n");
732 printf(" h half-word (16 bits)\n");
733 printf(" w word (32 bits)\n");
734 printf(" d doubleword (64 bits)\n");
735 printf(" q quad-word (128 bits)\n");
736 return;
737 }
738
739 if (put_type == ' ') {
740 printf("No type specified.\n");
741 return;
742 }
743
744 /* here: q is the address, p is the data. */
745 res = debugger_parse_expression(m, q, 0, &addr);
746 switch (res) {
747 case PARSE_NOMATCH:
748 printf("Couldn't parse the address.\n");
749 return;
750 case PARSE_MULTIPLE:
751 printf("Multiple matches for the address."
752 " Try prefixing with %%, $, or @.\n");
753 return;
754 case PARSE_SETTINGS:
755 case PARSE_SYMBOL:
756 case PARSE_NUMBER:
757 break;
758 default:
759 printf("INTERNAL ERROR in debugger.c.\n");
760 return;
761 }
762
763 res = debugger_parse_expression(m, p, 0, &data);
764 switch (res) {
765 case PARSE_NOMATCH:
766 printf("Couldn't parse the data.\n");
767 return;
768 case PARSE_MULTIPLE:
769 printf("Multiple matches for the data value."
770 " Try prefixing with %%, $, or @.\n");
771 return;
772 case PARSE_SETTINGS:
773 case PARSE_SYMBOL:
774 case PARSE_NUMBER:
775 break;
776 default:
777 printf("INTERNAL ERROR in debugger.c.\n");
778 return;
779 }
780
781 /* TODO: haha, maybe this should be refactored */
782
783 switch (put_type) {
784 case 'b':
785 a_byte = data;
786 if (m->cpus[0]->is_32bit)
787 printf("0x%08"PRIx32, (uint32_t) addr);
788 else
789 printf("0x%016"PRIx64, (uint64_t) addr);
790 printf(": %02x", a_byte);
791 if (data > 255)
792 printf(" (NOTE: truncating %0"PRIx64")",
793 (uint64_t) data);
794 res = m->cpus[0]->memory_rw(m->cpus[0], m->cpus[0]->mem, addr,
795 &a_byte, 1, MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS);
796 if (!res)
797 printf(" FAILED!\n");
798 printf("\n");
799 return;
800 case 'h':
801 if ((addr & 1) != 0)
802 printf("WARNING: address isn't aligned\n");
803 if (m->cpus[0]->is_32bit)
804 printf("0x%08"PRIx32, (uint32_t) addr);
805 else
806 printf("0x%016"PRIx64, (uint64_t) addr);
807 printf(": %04x", (int)data);
808 if (data > 0xffff)
809 printf(" (NOTE: truncating %0"PRIx64")",
810 (uint64_t) data);
811 res = store_16bit_word(m->cpus[0], addr, data);
812 if (!res)
813 printf(" FAILED!\n");
814 printf("\n");
815 return;
816 case 'w':
817 if ((addr & 3) != 0)
818 printf("WARNING: address isn't aligned\n");
819 if (m->cpus[0]->is_32bit)
820 printf("0x%08"PRIx32, (uint32_t) addr);
821 else
822 printf("0x%016"PRIx64, (uint64_t) addr);
823
824 printf(": %08x", (int)data);
825
826 if (data > 0xffffffff && (data >> 32) != 0
827 && (data >> 32) != 0xffffffff)
828 printf(" (NOTE: truncating %0"PRIx64")",
829 (uint64_t) data);
830
831 res = store_32bit_word(m->cpus[0], addr, data);
832 if (!res)
833 printf(" FAILED!\n");
834 printf("\n");
835 return;
836 case 'd':
837 if ((addr & 7) != 0)
838 printf("WARNING: address isn't aligned\n");
839 if (m->cpus[0]->is_32bit)
840 printf("0x%08"PRIx32, (uint32_t) addr);
841 else
842 printf("0x%016"PRIx64, (uint64_t) addr);
843
844 printf(": %016"PRIx64, (uint64_t) data);
845
846 res = store_64bit_word(m->cpus[0], addr, data);
847 if (!res)
848 printf(" FAILED!\n");
849 printf("\n");
850 return;
851 case 'q':
852 printf("quad-words: TODO\n");
853 /* TODO */
854 return;
855 default:
856 printf("Unimplemented type '%c'\n", put_type);
857 return;
858 }
859 }
860
861
862 /*
863 * debugger_cmd_quiet():
864 */
865 static void debugger_cmd_quiet(struct machine *m, char *cmd_line)
866 {
867 int toggle = 1;
868 int previous_mode = old_quiet_mode;
869
870 if (cmd_line[0] != '\0') {
871 while (cmd_line[0] != '\0' && cmd_line[0] == ' ')
872 cmd_line ++;
873 switch (cmd_line[0]) {
874 case '0':
875 toggle = 0;
876 old_quiet_mode = 0;
877 break;
878 case '1':
879 toggle = 0;
880 old_quiet_mode = 1;
881 break;
882 case 'o':
883 case 'O':
884 toggle = 0;
885 switch (cmd_line[1]) {
886 case 'n':
887 case 'N':
888 old_quiet_mode = 1;
889 break;
890 default:
891 old_quiet_mode = 0;
892 }
893 break;
894 default:
895 printf("syntax: quiet [on|off]\n");
896 return;
897 }
898 }
899
900 if (toggle)
901 old_quiet_mode = 1 - old_quiet_mode;
902
903 printf("quiet_mode = %s", old_quiet_mode? "ON" : "OFF");
904 if (old_quiet_mode != previous_mode)
905 printf(" (was: %s)", previous_mode? "ON" : "OFF");
906 printf("\n");
907 }
908
909
910 /*
911 * debugger_cmd_quit():
912 */
913 static void debugger_cmd_quit(struct machine *m, char *cmd_line)
914 {
915 int i, j, k;
916 struct emul *e;
917
918 if (*cmd_line) {
919 printf("syntax: quit\n");
920 return;
921 }
922
923 for (i=0; i<debugger_n_emuls; i++) {
924 single_step = NOT_SINGLE_STEPPING;
925
926 e = debugger_emuls[i];
927 force_debugger_at_exit = 0;
928
929 for (j=0; j<e->n_machines; j++) {
930 struct machine *m = e->machines[j];
931
932 for (k=0; k<m->ncpus; k++)
933 m->cpus[k]->running = 0;
934
935 m->exit_without_entering_debugger = 1;
936 }
937 }
938
939 exit_debugger = 1;
940 }
941
942
943 /*
944 * debugger_cmd_reg():
945 */
946 static void debugger_cmd_reg(struct machine *m, char *cmd_line)
947 {
948 int cpuid = debugger_cur_cpu, coprocnr = -1;
949 int gprs, coprocs;
950 char *p;
951
952 /* [cpuid][,c] */
953 if (cmd_line[0] != '\0') {
954 if (cmd_line[0] != ',') {
955 cpuid = strtoull(cmd_line, NULL, 0);
956 if (cpuid < 0 || cpuid >= m->ncpus) {
957 printf("cpu%i doesn't exist.\n", cpuid);
958 return;
959 }
960 }
961 p = strchr(cmd_line, ',');
962 if (p != NULL) {
963 coprocnr = atoi(p + 1);
964 if (coprocnr < 0 || coprocnr >= 4) {
965 printf("Invalid coprocessor number.\n");
966 return;
967 }
968 }
969 }
970
971 gprs = (coprocnr == -1)? 1 : 0;
972 coprocs = (coprocnr == -1)? 0x0 : (1 << coprocnr);
973
974 cpu_register_dump(m, m->cpus[cpuid], gprs, coprocs);
975 }
976
977
978 /*
979 * debugger_cmd_step():
980 */
981 static void debugger_cmd_step(struct machine *m, char *cmd_line)
982 {
983 int n = 1;
984
985 if (cmd_line[0] != '\0') {
986 n = strtoull(cmd_line, NULL, 0);
987 if (n < 1) {
988 printf("invalid nr of steps\n");
989 return;
990 }
991 }
992
993 debugger_n_steps_left_before_interaction = n - 1;
994
995 /* Special hack, see debugger() for more info. */
996 exit_debugger = -1;
997
998 strlcpy(repeat_cmd, "step", MAX_CMD_BUFLEN);
999 }
1000
1001
1002 /*
1003 * debugger_cmd_tlbdump():
1004 *
1005 * Dump each CPU's TLB contents.
1006 */
1007 static void debugger_cmd_tlbdump(struct machine *m, char *cmd_line)
1008 {
1009 int x = -1;
1010 int rawflag = 0;
1011
1012 if (cmd_line[0] != '\0') {
1013 char *p;
1014 if (cmd_line[0] != ',') {
1015 x = strtoull(cmd_line, NULL, 0);
1016 if (x < 0 || x >= m->ncpus) {
1017 printf("cpu%i doesn't exist.\n", x);
1018 return;
1019 }
1020 }
1021 p = strchr(cmd_line, ',');
1022 if (p != NULL) {
1023 switch (p[1]) {
1024 case 'r':
1025 case 'R':
1026 rawflag = 1;
1027 break;
1028 default:
1029 printf("Unknown tlbdump flag.\n");
1030 printf("syntax: tlbdump [cpuid][,r]\n");
1031 return;
1032 }
1033 }
1034 }
1035
1036 cpu_tlbdump(m, x, rawflag);
1037 }
1038
1039
1040 /*
1041 * debugger_cmd_trace():
1042 */
1043 static void debugger_cmd_trace(struct machine *m, char *cmd_line)
1044 {
1045 int toggle = 1;
1046 int previous_mode = old_show_trace_tree;
1047
1048 if (cmd_line[0] != '\0') {
1049 while (cmd_line[0] != '\0' && cmd_line[0] == ' ')
1050 cmd_line ++;
1051 switch (cmd_line[0]) {
1052 case '0':
1053 toggle = 0;
1054 old_show_trace_tree = 0;
1055 break;
1056 case '1':
1057 toggle = 0;
1058 old_show_trace_tree = 1;
1059 break;
1060 case 'o':
1061 case 'O':
1062 toggle = 0;
1063 switch (cmd_line[1]) {
1064 case 'n':
1065 case 'N':
1066 old_show_trace_tree = 1;
1067 break;
1068 default:
1069 old_show_trace_tree = 0;
1070 }
1071 break;
1072 default:
1073 printf("syntax: trace [on|off]\n");
1074 return;
1075 }
1076 }
1077
1078 if (toggle)
1079 old_show_trace_tree = 1 - old_show_trace_tree;
1080
1081 printf("show_trace_tree = %s", old_show_trace_tree? "ON" : "OFF");
1082 if (old_show_trace_tree != previous_mode)
1083 printf(" (was: %s)", previous_mode? "ON" : "OFF");
1084 printf("\n");
1085 }
1086
1087
1088 /*
1089 * debugger_cmd_unassemble():
1090 *
1091 * Dump emulated memory as instructions.
1092 *
1093 * syntax: unassemble [addr [endaddr]]
1094 */
1095 static void debugger_cmd_unassemble(struct machine *m, char *cmd_line)
1096 {
1097 uint64_t addr, addr_start, addr_end;
1098 struct cpu *c;
1099 struct memory *mem;
1100 char *p = NULL;
1101 int r, lines_left = -1;
1102
1103 if (cmd_line[0] != '\0') {
1104 uint64_t tmp;
1105 char *tmps = strdup(cmd_line);
1106
1107 /* addr: */
1108 p = strchr(tmps, ' ');
1109 if (p != NULL)
1110 *p = '\0';
1111 r = debugger_parse_expression(m, tmps, 0, &tmp);
1112 free(tmps);
1113
1114 if (r == PARSE_NOMATCH || r == PARSE_MULTIPLE) {
1115 printf("Unparsable address: %s\n", cmd_line);
1116 return;
1117 } else {
1118 last_unasm_addr = tmp;
1119 }
1120
1121 p = strchr(cmd_line, ' ');
1122 }
1123
1124 if (m->cpus == NULL) {
1125 printf("No cpus (?)\n");
1126 return;
1127 }
1128 c = m->cpus[m->bootstrap_cpu];
1129 if (c == NULL) {
1130 printf("m->cpus[m->bootstrap_cpu] = NULL\n");
1131 return;
1132 }
1133 mem = m->cpus[m->bootstrap_cpu]->mem;
1134
1135 addr_start = last_unasm_addr;
1136
1137 if (addr_start == MAGIC_UNTOUCHED)
1138 addr_start = c->pc;
1139
1140 addr_end = addr_start + 1000;
1141
1142 /* endaddr: */
1143 if (p != NULL) {
1144 while (*p == ' ' && *p)
1145 p++;
1146 r = debugger_parse_expression(m, p, 0, &addr_end);
1147 if (r == PARSE_NOMATCH || r == PARSE_MULTIPLE) {
1148 printf("Unparsable address: %s\n", cmd_line);
1149 return;
1150 }
1151 } else
1152 lines_left = 20;
1153
1154 addr = addr_start;
1155
1156 ctrl_c = 0;
1157
1158 while (addr < addr_end) {
1159 unsigned int i, len;
1160 int failed = 0;
1161 unsigned char buf[17]; /* TODO: How long can an
1162 instruction be, on weird archs? */
1163 memset(buf, 0, sizeof(buf));
1164
1165 for (i=0; i<sizeof(buf); i++) {
1166 if (c->memory_rw(c, mem, addr+i, buf+i, 1, MEM_READ,
1167 CACHE_NONE | NO_EXCEPTIONS) == MEMORY_ACCESS_FAILED)
1168 failed ++;
1169 }
1170
1171 if (failed == sizeof(buf)) {
1172 printf("(memory access failed)\n");
1173 break;
1174 }
1175
1176 len = cpu_disassemble_instr(m, c, buf, 0, addr);
1177
1178 if (ctrl_c)
1179 return;
1180 if (len == 0)
1181 break;
1182
1183 addr += len;
1184
1185 if (lines_left != -1) {
1186 lines_left --;
1187 if (lines_left == 0)
1188 break;
1189 }
1190 }
1191
1192 last_unasm_addr = addr;
1193
1194 strlcpy(repeat_cmd, "unassemble", MAX_CMD_BUFLEN);
1195 }
1196
1197
1198 /*
1199 * debugger_cmd_version():
1200 */
1201 static void debugger_cmd_version(struct machine *m, char *cmd_line)
1202 {
1203 if (*cmd_line) {
1204 printf("syntax: version\n");
1205 return;
1206 }
1207
1208 #ifdef VERSION
1209 printf("%s, %s\n", VERSION, COMPILE_DATE);
1210 #else
1211 printf("(no version), %s\n", COMPILE_DATE);
1212 #endif
1213 }
1214
1215
1216 /****************************************************************************/
1217
1218
1219 struct cmd {
1220 char *name;
1221 char *args;
1222 int tmp_flag;
1223 void (*f)(struct machine *, char *cmd_line);
1224 char *description;
1225 };
1226
1227 static struct cmd cmds[] = {
1228 { "allsettings", "", 0, debugger_cmd_allsettings,
1229 "show all settings" },
1230
1231 { "breakpoint", "...", 0, debugger_cmd_breakpoint,
1232 "manipulate breakpoints" },
1233
1234 /* NOTE: Try to keep 'c' down to only one command. Having 'continue'
1235 available as a one-letter command is very convenient. */
1236
1237 { "continue", "", 0, debugger_cmd_continue,
1238 "continue execution" },
1239
1240 { "device", "...", 0, debugger_cmd_device,
1241 "show info about (or manipulate) devices" },
1242
1243 { "dump", "[addr [endaddr]]", 0, debugger_cmd_dump,
1244 "dump memory contents in hex and ASCII" },
1245
1246 { "emuls", "", 0, debugger_cmd_emuls,
1247 "print a summary of all current emuls" },
1248
1249 { "focus", "x[,y[,z]]", 0, debugger_cmd_focus,
1250 "changes focus to cpu x, machine x, emul z" },
1251
1252 { "help", "", 0, debugger_cmd_help,
1253 "print this help message" },
1254
1255 { "itrace", "", 0, debugger_cmd_itrace,
1256 "toggle instruction_trace on or off" },
1257
1258 { "lookup", "name|addr", 0, debugger_cmd_lookup,
1259 "lookup a symbol by name or address" },
1260
1261 { "machine", "", 0, debugger_cmd_machine,
1262 "print a summary of the current machine" },
1263
1264 { "ninstrs", "[on|off]", 0, debugger_cmd_ninstrs,
1265 "toggle (set or unset) show_nr_of_instructions" },
1266
1267 { "pause", "cpuid", 0, debugger_cmd_pause,
1268 "pause (or unpause) a CPU" },
1269
1270 { "print", "expr", 0, debugger_cmd_print,
1271 "evaluate an expression without side-effects" },
1272
1273 { "put", "[b|h|w|d|q] addr, data", 0, debugger_cmd_put,
1274 "modify emulated memory contents" },
1275
1276 { "quiet", "[on|off]", 0, debugger_cmd_quiet,
1277 "toggle quiet_mode on or off" },
1278
1279 { "quit", "", 0, debugger_cmd_quit,
1280 "quit the emulator" },
1281
1282 /* NOTE: Try to keep 'r' down to only one command. Having 'reg'
1283 available as a one-letter command is very convenient. */
1284
1285 { "reg", "[cpuid][,c]", 0, debugger_cmd_reg,
1286 "show GPRs (or coprocessor c's registers)" },
1287
1288 /* NOTE: Try to keep 's' down to only one command. Having 'step'
1289 available as a one-letter command is very convenient. */
1290
1291 { "step", "[n]", 0, debugger_cmd_step,
1292 "single-step one (or n) instruction(s)" },
1293
1294 { "tlbdump", "[cpuid][,r]", 0, debugger_cmd_tlbdump,
1295 "dump TLB contents (add ',r' for raw data)" },
1296
1297 { "trace", "[on|off]", 0, debugger_cmd_trace,
1298 "toggle show_trace_tree on or off" },
1299
1300 { "unassemble", "[addr [endaddr]]", 0, debugger_cmd_unassemble,
1301 "dump memory contents as instructions" },
1302
1303 { "version", "", 0, debugger_cmd_version,
1304 "print version information" },
1305
1306 /* Note: NULL handler. */
1307 { "x = expr", "", 0, NULL, "generic assignment" },
1308
1309 { NULL, NULL, 0, NULL, NULL }
1310 };
1311
1312
1313 /*
1314 * debugger_cmd_help():
1315 *
1316 * Print a list of available commands.
1317 *
1318 * NOTE: This is placed after the cmds[] array, because it needs to
1319 * access it.
1320 *
1321 * TODO: Command completion (ie just type "help s" for "help step").
1322 */
1323 static void debugger_cmd_help(struct machine *m, char *cmd_line)
1324 {
1325 int only_one = 0, only_one_match = 0;
1326 char *nlines_env = getenv("LINES");
1327 int nlines = atoi(nlines_env != NULL? nlines_env : "999999"), curlines;
1328 size_t i, j, max_name_len = 0;
1329
1330 if (cmd_line[0] != '\0') {
1331 only_one = 1;
1332 }
1333
1334 i = 0;
1335 while (cmds[i].name != NULL) {
1336 size_t a = strlen(cmds[i].name);
1337 if (cmds[i].args != NULL)
1338 a += 1 + strlen(cmds[i].args);
1339 if (a > max_name_len)
1340 max_name_len = a;
1341 i++;
1342 }
1343
1344 curlines = 0;
1345 if (!only_one) {
1346 printf("Available commands:\n");
1347 curlines++;
1348 }
1349
1350 i = 0;
1351 while (cmds[i].name != NULL) {
1352 char buf[100];
1353 snprintf(buf, sizeof(buf), "%s", cmds[i].name);
1354
1355 if (only_one) {
1356 if (strcmp(cmds[i].name, cmd_line) != 0) {
1357 i++;
1358 continue;
1359 }
1360 only_one_match = 1;
1361 }
1362
1363 if (cmds[i].args != NULL)
1364 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1365 " %s", cmds[i].args);
1366
1367 printf(" ");
1368 for (j=0; j<max_name_len; j++)
1369 if (j < strlen(buf))
1370 printf("%c", buf[j]);
1371 else
1372 printf(" ");
1373
1374 printf(" %s\n", cmds[i].description);
1375 i++;
1376
1377 curlines ++;
1378 if (curlines >= nlines - 1) {
1379 char ch;
1380 printf("-- more --"); fflush(stdout);
1381 ch = debugger_readchar();
1382 printf("\n");
1383 if (ch == 'q' || ch == 'Q')
1384 return;
1385 curlines = 0;
1386 }
1387 }
1388
1389 if (only_one) {
1390 if (!only_one_match)
1391 printf("%s: no such command\n", cmd_line);
1392 return;
1393 }
1394
1395 /* TODO: generalize/refactor */
1396 curlines += 8;
1397 if (curlines > nlines - 1) {
1398 char ch;
1399 printf("-- more --"); fflush(stdout);
1400 ch = debugger_readchar();
1401 printf("\n");
1402 if (ch == 'q' || ch == 'Q')
1403 return;
1404 curlines = 0;
1405 }
1406
1407 printf("\nIn generic assignments, x must be a register or other "
1408 "writable settings\nvariable, and expr can contain registers/"
1409 "settings, numeric values, or symbol\nnames, in combination with"
1410 " parenthesis and + - * / & %% ^ | operators.\nIn case there are"
1411 " multiple matches (i.e. a symbol that has the same name as a\n"
1412 "register), you may add a prefix character as a hint: '#' for"
1413 " registers, '@'\nfor symbols, and '$' for numeric values. Use"
1414 " 0x for hexadecimal values.\n");
1415 }
1416

  ViewVC Help
Powered by ViewVC 1.1.26