/[gxemul]/trunk/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

Annotation of /trunk/src/debugger/debugger_cmds.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (hide annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 31330 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

==============  RELEASE 0.4.0.1  ==============


1 dpavlin 24 /*
2     * Copyright (C) 2004-2006 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 dpavlin 26 * $Id: debugger_cmds.c,v 1.5 2006/06/24 19:52:28 debug Exp $
29 dpavlin 24 *
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_name(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->dev_name[i],
212     (uint64_t) mem->dev_baseaddr[i],
213     (uint64_t) mem->dev_length[i]);
214    
215     if (mem->dev_flags[i]) {
216     printf(" (");
217     if (mem->dev_flags[i] & DM_DYNTRANS_OK)
218     printf("DYNTRANS R");
219     if (mem->dev_flags[i] & 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_name(m, tmps, 0, &tmp);
268     free(tmps);
269    
270     if (r == NAME_PARSE_NOMATCH || r == NAME_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     addr_start = last_dump_addr;
281    
282     if (addr_start == MAGIC_UNTOUCHED) {
283     uint64_t tmp;
284     int match_register = 0;
285     cpu_register_match(m, "pc", 0, &tmp, &match_register);
286     if (match_register) {
287     addr_start = tmp;
288     } else {
289     printf("No starting address.\n");
290     return;
291     }
292     }
293    
294     addr_end = addr_start + 16 * 16;
295    
296     /* endaddr: */
297     if (p != NULL) {
298     while (*p == ' ' && *p)
299     p++;
300     r = debugger_parse_name(m, p, 0, &addr_end);
301     if (r == NAME_PARSE_NOMATCH || r == NAME_PARSE_MULTIPLE) {
302     printf("Unparsable address: %s\n", cmd_line);
303     return;
304     }
305     }
306    
307     if (m->cpus == NULL) {
308     printf("No cpus (?)\n");
309     return;
310     }
311     c = m->cpus[m->bootstrap_cpu];
312     if (c == NULL) {
313     printf("m->cpus[m->bootstrap_cpu] = NULL\n");
314     return;
315     }
316     mem = m->cpus[m->bootstrap_cpu]->mem;
317    
318     addr = addr_start & ~0xf;
319    
320     ctrl_c = 0;
321    
322     while (addr < addr_end) {
323     unsigned char buf[16];
324     memset(buf, 0, sizeof(buf));
325     r = c->memory_rw(c, mem, addr, &buf[0], sizeof(buf),
326     MEM_READ, CACHE_NONE | NO_EXCEPTIONS);
327    
328     if (c->is_32bit)
329     printf("0x%08"PRIx32" ", (uint32_t) addr);
330     else
331     printf("0x%016"PRIx64" ", (uint64_t) addr);
332    
333     if (r == MEMORY_ACCESS_FAILED)
334     printf("(memory access failed)\n");
335     else {
336     for (x=0; x<16; x++) {
337     if (addr + x >= addr_start &&
338     addr + x < addr_end)
339     printf("%02x%s", buf[x],
340     (x&3)==3? " " : "");
341     else
342     printf(" %s", (x&3)==3? " " : "");
343     }
344     printf(" ");
345     for (x=0; x<16; x++) {
346     if (addr + x >= addr_start &&
347     addr + x < addr_end)
348     printf("%c", (buf[x]>=' ' &&
349     buf[x]<127)? buf[x] : '.');
350     else
351     printf(" ");
352     }
353     printf("\n");
354     }
355    
356     if (ctrl_c)
357     return;
358    
359     addr += sizeof(buf);
360     }
361    
362     last_dump_addr = addr_end;
363    
364     strlcpy(repeat_cmd, "dump", MAX_CMD_BUFLEN);
365     }
366    
367    
368     /*
369     * debugger_cmd_emuls():
370     *
371     * Dump info about all current emuls.
372     */
373     static void debugger_cmd_emuls(struct machine *m, char *cmd_line)
374     {
375     int i, iadd = DEBUG_INDENTATION;
376    
377     if (*cmd_line) {
378     printf("syntax: emuls\n");
379     return;
380     }
381    
382     for (i=0; i<debugger_n_emuls; i++) {
383     struct emul *e = debugger_emuls[i];
384    
385     if (e == NULL)
386     continue;
387    
388     debug("emulation %i: \"%s\"\n", i,
389     e->name == NULL? "(no name)" : e->name);
390     debug_indentation(iadd);
391    
392     emul_dumpinfo(e);
393    
394     debug_indentation(-iadd);
395     }
396     }
397    
398    
399     /*
400     * debugger_cmd_focus():
401     *
402     * Changes focus to specific machine (in a specific emulation).
403     */
404     static void debugger_cmd_focus(struct machine *m, char *cmd_line)
405     {
406     int x = -1, y = -1;
407     char *p;
408    
409     if (!cmd_line[0]) {
410     printf("syntax: focus x[,y]\n");
411     printf("where x and y are integers as reported by the"
412     " 'emuls' command\n");
413     goto print_current_focus_and_return;
414     }
415    
416     x = atoi(cmd_line);
417     p = strchr(cmd_line, ',');
418     if (p == cmd_line) {
419     printf("No machine number specified?\n");
420     printf("syntax: focus x[,y]\n");
421     return;
422     }
423    
424     if (p != NULL)
425     y = atoi(p + 1);
426    
427     if (y != -1) {
428     /* Change emul: */
429     if (y < 0 || y >= debugger_n_emuls) {
430     printf("Invalid emul number: %i\n", y);
431     return;
432     }
433    
434     debugger_emul = debugger_emuls[y];
435    
436     /* This is just in case the machine change below fails... */
437     debugger_machine = debugger_emul->machines[0];
438     }
439    
440     /* Change machine: */
441     if (x < 0 || x >= debugger_emul->n_machines) {
442     printf("Invalid machine number: %i\n", x);
443     return;
444     }
445    
446     debugger_machine = debugger_emul->machines[x];
447    
448     print_current_focus_and_return:
449     printf("current emul: \"%s\"\n", debugger_emul->name == NULL?
450     "(no name)" : debugger_emul->name);
451     printf("current machine: \"%s\"\n", debugger_machine->name == NULL?
452     "(no name)" : debugger_machine->name);
453     }
454    
455    
456     /* This is defined below. */
457     static void debugger_cmd_help(struct machine *m, char *cmd_line);
458    
459    
460     /*
461     * debugger_cmd_itrace():
462     */
463     static void debugger_cmd_itrace(struct machine *m, char *cmd_line)
464     {
465     if (*cmd_line) {
466     printf("syntax: itrace\n");
467     return;
468     }
469    
470     old_instruction_trace = 1 - old_instruction_trace;
471     printf("instruction_trace = %s\n", old_instruction_trace? "ON":"OFF");
472     /* TODO: how to preserve quiet_mode? */
473     old_quiet_mode = 0;
474     printf("quiet_mode = %s\n", old_quiet_mode? "ON" : "OFF");
475     }
476    
477    
478     /*
479     * debugger_cmd_lookup():
480     */
481     static void debugger_cmd_lookup(struct machine *m, char *cmd_line)
482     {
483     uint64_t addr;
484     int res;
485     char *symbol;
486     uint64_t offset;
487    
488     if (cmd_line[0] == '\0') {
489     printf("syntax: lookup name|addr\n");
490     return;
491    
492     }
493    
494     /* Addresses never need to be given in decimal form anyway,
495     so assuming hex here will be ok. */
496     addr = strtoull(cmd_line, NULL, 16);
497    
498     if (addr == 0) {
499     uint64_t newaddr;
500     res = get_symbol_addr(&m->symbol_context,
501     cmd_line, &newaddr);
502     if (!res) {
503     printf("lookup for '%s' failed\n", cmd_line);
504     return;
505     }
506     printf("%s = 0x", cmd_line);
507     if (m->cpus[0]->is_32bit)
508     printf("%08"PRIx32"\n", (uint32_t) newaddr);
509     else
510     printf("%016"PRIx64"\n", (uint64_t) newaddr);
511     return;
512     }
513    
514     symbol = get_symbol_name(&m->symbol_context, addr, &offset);
515    
516     if (symbol != NULL) {
517     if (m->cpus[0]->is_32bit)
518     printf("0x%08"PRIx32, (uint32_t) addr);
519     else
520     printf("0x%016"PRIx64, (uint64_t) addr);
521     printf(" = %s\n", symbol);
522     } else
523     printf("lookup for '%s' failed\n", cmd_line);
524     }
525    
526    
527     /*
528     * debugger_cmd_machine():
529     *
530     * Dump info about the currently focused machine.
531     */
532     static void debugger_cmd_machine(struct machine *m, char *cmd_line)
533     {
534     int iadd = DEBUG_INDENTATION;
535    
536     if (*cmd_line) {
537     printf("syntax: machine\n");
538     return;
539     }
540    
541     debug("machine \"%s\":\n", m->name);
542     debug_indentation(iadd);
543     machine_dumpinfo(m);
544     debug_indentation(-iadd);
545     }
546    
547    
548     /*
549     * debugger_cmd_ninstrs():
550     */
551     static void debugger_cmd_ninstrs(struct machine *m, char *cmd_line)
552     {
553     int toggle = 1;
554     int previous_mode = m->show_nr_of_instructions;
555    
556     if (cmd_line[0] != '\0') {
557     while (cmd_line[0] != '\0' && cmd_line[0] == ' ')
558     cmd_line ++;
559     switch (cmd_line[0]) {
560     case '0':
561     toggle = 0;
562     m->show_nr_of_instructions = 0;
563     break;
564     case '1':
565     toggle = 0;
566     m->show_nr_of_instructions = 1;
567     break;
568     case 'o':
569     case 'O':
570     toggle = 0;
571     switch (cmd_line[1]) {
572     case 'n':
573     case 'N':
574     m->show_nr_of_instructions = 1;
575     break;
576     default:
577     m->show_nr_of_instructions = 0;
578     }
579     break;
580     default:
581     printf("syntax: trace [on|off]\n");
582     return;
583     }
584     }
585    
586     if (toggle)
587     m->show_nr_of_instructions = !m->show_nr_of_instructions;
588    
589     printf("show_nr_of_instructions = %s",
590     m->show_nr_of_instructions? "ON" : "OFF");
591     if (m->show_nr_of_instructions != previous_mode)
592     printf(" (was: %s)", previous_mode? "ON" : "OFF");
593     printf("\n");
594     }
595    
596    
597     /*
598     * debugger_cmd_pause():
599     */
600     static void debugger_cmd_pause(struct machine *m, char *cmd_line)
601     {
602     int cpuid = -1;
603    
604     if (cmd_line[0] != '\0')
605     cpuid = atoi(cmd_line);
606     else {
607     printf("syntax: pause cpuid\n");
608     return;
609     }
610    
611     if (cpuid < 0 || cpuid >= m->ncpus) {
612     printf("cpu%i doesn't exist.\n", cpuid);
613     return;
614     }
615    
616     m->cpus[cpuid]->running ^= 1;
617    
618     printf("cpu%i (%s) in machine \"%s\" is now %s\n", cpuid,
619     m->cpus[cpuid]->name, m->name,
620     m->cpus[cpuid]->running? "RUNNING" : "STOPPED");
621     }
622    
623    
624     /*
625     * debugger_cmd_print():
626     */
627     static void debugger_cmd_print(struct machine *m, char *cmd_line)
628     {
629     int res;
630     uint64_t tmp;
631    
632     while (cmd_line[0] != '\0' && cmd_line[0] == ' ')
633     cmd_line ++;
634    
635     if (cmd_line[0] == '\0') {
636     printf("syntax: print expr\n");
637     return;
638     }
639    
640     res = debugger_parse_name(m, cmd_line, 0, &tmp);
641     switch (res) {
642     case NAME_PARSE_NOMATCH:
643     printf("No match.\n");
644     break;
645     case NAME_PARSE_MULTIPLE:
646     printf("Multiple matches. Try prefixing with %%, $, or @.\n");
647     break;
648     case NAME_PARSE_REGISTER:
649     printf("%s = 0x%"PRIx64"\n", cmd_line, (uint64_t)tmp);
650     break;
651     case NAME_PARSE_SYMBOL:
652     if (m->cpus[0]->is_32bit)
653     printf("%s = 0x%08"PRIx32"\n", cmd_line, (uint32_t)tmp);
654     else
655     printf("%s = 0x%016"PRIx64"\n", cmd_line,(uint64_t)tmp);
656     break;
657     case NAME_PARSE_NUMBER:
658     printf("0x%"PRIx64"\n", (uint64_t) tmp);
659     break;
660     }
661     }
662    
663    
664     /*
665     * debugger_cmd_put():
666     */
667     static void debugger_cmd_put(struct machine *m, char *cmd_line)
668     {
669     static char put_type = ' '; /* Remembered across multiple calls. */
670     char copy[200];
671     int res, syntax_ok = 0;
672     char *p, *p2, *q = NULL;
673     uint64_t addr, data;
674     unsigned char a_byte;
675    
676     strncpy(copy, cmd_line, sizeof(copy));
677     copy[sizeof(copy)-1] = '\0';
678    
679     /* syntax: put [b|h|w|d|q] addr, data */
680    
681     p = strchr(copy, ',');
682     if (p != NULL) {
683     *p++ = '\0';
684     while (*p == ' ' && *p)
685     p++;
686     while (strlen(copy) >= 1 &&
687     copy[strlen(copy) - 1] == ' ')
688     copy[strlen(copy) - 1] = '\0';
689    
690     /* printf("L = '%s', R = '%s'\n", copy, p); */
691    
692     q = copy;
693     p2 = strchr(q, ' ');
694    
695     if (p2 != NULL) {
696     *p2 = '\0';
697     if (strlen(q) != 1) {
698     printf("Invalid type '%s'\n", q);
699     return;
700     }
701     put_type = *q;
702     q = p2 + 1;
703     }
704    
705     /* printf("type '%c', L '%s', R '%s'\n", put_type, q, p); */
706     syntax_ok = 1;
707     }
708    
709     if (!syntax_ok) {
710     printf("syntax: put [b|h|w|d|q] addr, data\n");
711     printf(" b byte (8 bits)\n");
712     printf(" h half-word (16 bits)\n");
713     printf(" w word (32 bits)\n");
714     printf(" d doubleword (64 bits)\n");
715     printf(" q quad-word (128 bits)\n");
716     return;
717     }
718    
719     if (put_type == ' ') {
720     printf("No type specified.\n");
721     return;
722     }
723    
724     /* here: q is the address, p is the data. */
725     res = debugger_parse_name(m, q, 0, &addr);
726     switch (res) {
727     case NAME_PARSE_NOMATCH:
728     printf("Couldn't parse the address.\n");
729     return;
730     case NAME_PARSE_MULTIPLE:
731     printf("Multiple matches for the address."
732     " Try prefixing with %%, $, or @.\n");
733     return;
734     case NAME_PARSE_REGISTER:
735     case NAME_PARSE_SYMBOL:
736     case NAME_PARSE_NUMBER:
737     break;
738     default:
739     printf("INTERNAL ERROR in debugger.c.\n");
740     return;
741     }
742    
743     res = debugger_parse_name(m, p, 0, &data);
744     switch (res) {
745     case NAME_PARSE_NOMATCH:
746     printf("Couldn't parse the data.\n");
747     return;
748     case NAME_PARSE_MULTIPLE:
749     printf("Multiple matches for the data value."
750     " Try prefixing with %%, $, or @.\n");
751     return;
752     case NAME_PARSE_REGISTER:
753     case NAME_PARSE_SYMBOL:
754     case NAME_PARSE_NUMBER:
755     break;
756     default:
757     printf("INTERNAL ERROR in debugger.c.\n");
758     return;
759     }
760    
761     /* TODO: haha, maybe this should be refactored */
762    
763     switch (put_type) {
764     case 'b':
765     a_byte = data;
766     if (m->cpus[0]->is_32bit)
767     printf("0x%08"PRIx32, (uint32_t) addr);
768     else
769     printf("0x%016"PRIx64, (uint64_t) addr);
770     printf(": %02x", a_byte);
771     if (data > 255)
772     printf(" (NOTE: truncating %0"PRIx64")",
773     (uint64_t) data);
774     res = m->cpus[0]->memory_rw(m->cpus[0], m->cpus[0]->mem, addr,
775     &a_byte, 1, MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS);
776     if (!res)
777     printf(" FAILED!\n");
778     printf("\n");
779     return;
780     case 'h':
781     if ((addr & 1) != 0)
782     printf("WARNING: address isn't aligned\n");
783     if (m->cpus[0]->is_32bit)
784     printf("0x%08"PRIx32, (uint32_t) addr);
785     else
786     printf("0x%016"PRIx64, (uint64_t) addr);
787     printf(": %04x", (int)data);
788     if (data > 0xffff)
789     printf(" (NOTE: truncating %0"PRIx64")",
790     (uint64_t) data);
791     res = store_16bit_word(m->cpus[0], addr, data);
792     if (!res)
793     printf(" FAILED!\n");
794     printf("\n");
795     return;
796     case 'w':
797     if ((addr & 3) != 0)
798     printf("WARNING: address isn't aligned\n");
799     if (m->cpus[0]->is_32bit)
800     printf("0x%08"PRIx32, (uint32_t) addr);
801     else
802     printf("0x%016"PRIx64, (uint64_t) addr);
803    
804     printf(": %08x", (int)data);
805    
806     if (data > 0xffffffff && (data >> 32) != 0
807     && (data >> 32) != 0xffffffff)
808     printf(" (NOTE: truncating %0"PRIx64")",
809     (uint64_t) data);
810    
811     res = store_32bit_word(m->cpus[0], addr, data);
812     if (!res)
813     printf(" FAILED!\n");
814     printf("\n");
815     return;
816     case 'd':
817     if ((addr & 7) != 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(": %016"PRIx64, (uint64_t) data);
825    
826     res = store_64bit_word(m->cpus[0], addr, data);
827     if (!res)
828     printf(" FAILED!\n");
829     printf("\n");
830     return;
831     case 'q':
832     printf("quad-words: TODO\n");
833     /* TODO */
834     return;
835     default:
836     printf("Unimplemented type '%c'\n", put_type);
837     return;
838     }
839     }
840    
841    
842     /*
843     * debugger_cmd_quiet():
844     */
845     static void debugger_cmd_quiet(struct machine *m, char *cmd_line)
846     {
847     int toggle = 1;
848     int previous_mode = old_quiet_mode;
849    
850     if (cmd_line[0] != '\0') {
851     while (cmd_line[0] != '\0' && cmd_line[0] == ' ')
852     cmd_line ++;
853     switch (cmd_line[0]) {
854     case '0':
855     toggle = 0;
856     old_quiet_mode = 0;
857     break;
858     case '1':
859     toggle = 0;
860     old_quiet_mode = 1;
861     break;
862     case 'o':
863     case 'O':
864     toggle = 0;
865     switch (cmd_line[1]) {
866     case 'n':
867     case 'N':
868     old_quiet_mode = 1;
869     break;
870     default:
871     old_quiet_mode = 0;
872     }
873     break;
874     default:
875     printf("syntax: quiet [on|off]\n");
876     return;
877     }
878     }
879    
880     if (toggle)
881     old_quiet_mode = 1 - old_quiet_mode;
882    
883     printf("quiet_mode = %s", old_quiet_mode? "ON" : "OFF");
884     if (old_quiet_mode != previous_mode)
885     printf(" (was: %s)", previous_mode? "ON" : "OFF");
886     printf("\n");
887     }
888    
889    
890     /*
891     * debugger_cmd_quit():
892     */
893     static void debugger_cmd_quit(struct machine *m, char *cmd_line)
894     {
895     int i, j, k;
896     struct emul *e;
897    
898     if (*cmd_line) {
899     printf("syntax: quit\n");
900     return;
901     }
902    
903     for (i=0; i<debugger_n_emuls; i++) {
904 dpavlin 26 single_step = NOT_SINGLE_STEPPING;
905 dpavlin 24
906     e = debugger_emuls[i];
907     force_debugger_at_exit = 0;
908    
909     for (j=0; j<e->n_machines; j++) {
910     struct machine *m = e->machines[j];
911    
912     for (k=0; k<m->ncpus; k++)
913     m->cpus[k]->running = 0;
914    
915     m->exit_without_entering_debugger = 1;
916     }
917     }
918    
919     exit_debugger = 1;
920     }
921    
922    
923     /*
924     * debugger_cmd_reg():
925     */
926     static void debugger_cmd_reg(struct machine *m, char *cmd_line)
927     {
928     int i, cpuid = -1, coprocnr = -1;
929     int gprs, coprocs;
930     char *p;
931    
932     /* [cpuid][,c] */
933     if (cmd_line[0] != '\0') {
934     if (cmd_line[0] != ',') {
935     cpuid = strtoull(cmd_line, NULL, 0);
936     if (cpuid < 0 || cpuid >= m->ncpus) {
937     printf("cpu%i doesn't exist.\n", cpuid);
938     return;
939     }
940     }
941     p = strchr(cmd_line, ',');
942     if (p != NULL) {
943     coprocnr = atoi(p + 1);
944     if (coprocnr < 0 || coprocnr >= 4) {
945     printf("Invalid coprocessor number.\n");
946     return;
947     }
948     }
949     }
950    
951     gprs = (coprocnr == -1)? 1 : 0;
952     coprocs = (coprocnr == -1)? 0x0 : (1 << coprocnr);
953    
954     for (i=0; i<m->ncpus; i++)
955     if (cpuid == -1 || i == cpuid)
956     cpu_register_dump(m, m->cpus[i], gprs, coprocs);
957     }
958    
959    
960     /*
961     * debugger_cmd_step():
962     */
963     static void debugger_cmd_step(struct machine *m, char *cmd_line)
964     {
965     int n = 1;
966    
967     if (cmd_line[0] != '\0') {
968     n = strtoull(cmd_line, NULL, 0);
969     if (n < 1) {
970     printf("invalid nr of steps\n");
971     return;
972     }
973     }
974    
975     debugger_n_steps_left_before_interaction = n - 1;
976    
977     /* Special hack, see debugger() for more info. */
978     exit_debugger = -1;
979    
980     strlcpy(repeat_cmd, "step", MAX_CMD_BUFLEN);
981     }
982    
983    
984     /*
985     * debugger_cmd_tlbdump():
986     *
987     * Dump each CPU's TLB contents.
988     */
989     static void debugger_cmd_tlbdump(struct machine *m, char *cmd_line)
990     {
991     int x = -1;
992     int rawflag = 0;
993    
994     if (cmd_line[0] != '\0') {
995     char *p;
996     if (cmd_line[0] != ',') {
997     x = strtoull(cmd_line, NULL, 0);
998     if (x < 0 || x >= m->ncpus) {
999     printf("cpu%i doesn't exist.\n", x);
1000     return;
1001     }
1002     }
1003     p = strchr(cmd_line, ',');
1004     if (p != NULL) {
1005     switch (p[1]) {
1006     case 'r':
1007     case 'R':
1008     rawflag = 1;
1009     break;
1010     default:
1011     printf("Unknown tlbdump flag.\n");
1012     printf("syntax: tlbdump [cpuid][,r]\n");
1013     return;
1014     }
1015     }
1016     }
1017    
1018     cpu_tlbdump(m, x, rawflag);
1019     }
1020    
1021    
1022     /*
1023     * debugger_cmd_trace():
1024     */
1025     static void debugger_cmd_trace(struct machine *m, char *cmd_line)
1026     {
1027     int toggle = 1;
1028     int previous_mode = old_show_trace_tree;
1029    
1030     if (cmd_line[0] != '\0') {
1031     while (cmd_line[0] != '\0' && cmd_line[0] == ' ')
1032     cmd_line ++;
1033     switch (cmd_line[0]) {
1034     case '0':
1035     toggle = 0;
1036     old_show_trace_tree = 0;
1037     break;
1038     case '1':
1039     toggle = 0;
1040     old_show_trace_tree = 1;
1041     break;
1042     case 'o':
1043     case 'O':
1044     toggle = 0;
1045     switch (cmd_line[1]) {
1046     case 'n':
1047     case 'N':
1048     old_show_trace_tree = 1;
1049     break;
1050     default:
1051     old_show_trace_tree = 0;
1052     }
1053     break;
1054     default:
1055     printf("syntax: trace [on|off]\n");
1056     return;
1057     }
1058     }
1059    
1060     if (toggle)
1061     old_show_trace_tree = 1 - old_show_trace_tree;
1062    
1063     printf("show_trace_tree = %s", old_show_trace_tree? "ON" : "OFF");
1064     if (old_show_trace_tree != previous_mode)
1065     printf(" (was: %s)", previous_mode? "ON" : "OFF");
1066     printf("\n");
1067     }
1068    
1069    
1070     /*
1071     * debugger_cmd_unassemble():
1072     *
1073     * Dump emulated memory as instructions.
1074     *
1075     * syntax: unassemble [addr [endaddr]]
1076     */
1077     static void debugger_cmd_unassemble(struct machine *m, char *cmd_line)
1078     {
1079     uint64_t addr, addr_start, addr_end;
1080     struct cpu *c;
1081     struct memory *mem;
1082     char *p = NULL;
1083     int r, lines_left = -1;
1084    
1085     if (cmd_line[0] != '\0') {
1086     uint64_t tmp;
1087     char *tmps = strdup(cmd_line);
1088    
1089     /* addr: */
1090     p = strchr(tmps, ' ');
1091     if (p != NULL)
1092     *p = '\0';
1093     r = debugger_parse_name(m, tmps, 0, &tmp);
1094     free(tmps);
1095    
1096     if (r == NAME_PARSE_NOMATCH || r == NAME_PARSE_MULTIPLE) {
1097     printf("Unparsable address: %s\n", cmd_line);
1098     return;
1099     } else {
1100     last_unasm_addr = tmp;
1101     }
1102    
1103     p = strchr(cmd_line, ' ');
1104     }
1105    
1106     addr_start = last_unasm_addr;
1107    
1108     if (addr_start == MAGIC_UNTOUCHED) {
1109     uint64_t tmp;
1110     int match_register = 0;
1111     cpu_register_match(m, "pc", 0, &tmp, &match_register);
1112     if (match_register) {
1113     addr_start = tmp;
1114     } else {
1115     printf("No starting address.\n");
1116     return;
1117     }
1118     }
1119    
1120     addr_end = addr_start + 1000;
1121    
1122     /* endaddr: */
1123     if (p != NULL) {
1124     while (*p == ' ' && *p)
1125     p++;
1126     r = debugger_parse_name(m, p, 0, &addr_end);
1127     if (r == NAME_PARSE_NOMATCH || r == NAME_PARSE_MULTIPLE) {
1128     printf("Unparsable address: %s\n", cmd_line);
1129     return;
1130     }
1131     } else
1132     lines_left = 20;
1133    
1134     if (m->cpus == NULL) {
1135     printf("No cpus (?)\n");
1136     return;
1137     }
1138     c = m->cpus[m->bootstrap_cpu];
1139     if (c == NULL) {
1140     printf("m->cpus[m->bootstrap_cpu] = NULL\n");
1141     return;
1142     }
1143     mem = m->cpus[m->bootstrap_cpu]->mem;
1144    
1145     addr = addr_start;
1146    
1147     ctrl_c = 0;
1148    
1149     while (addr < addr_end) {
1150     unsigned int i, len;
1151     int failed = 0;
1152     unsigned char buf[17]; /* TODO: How long can an
1153     instruction be, on weird archs? */
1154     memset(buf, 0, sizeof(buf));
1155    
1156     for (i=0; i<sizeof(buf); i++) {
1157     if (c->memory_rw(c, mem, addr+i, buf+i, 1, MEM_READ,
1158     CACHE_NONE | NO_EXCEPTIONS) == MEMORY_ACCESS_FAILED)
1159     failed ++;
1160     }
1161    
1162     if (failed == sizeof(buf)) {
1163     printf("(memory access failed)\n");
1164     break;
1165     }
1166    
1167     len = cpu_disassemble_instr(m, c, buf, 0, addr);
1168    
1169     if (ctrl_c)
1170     return;
1171     if (len == 0)
1172     break;
1173    
1174     addr += len;
1175    
1176     if (lines_left != -1) {
1177     lines_left --;
1178     if (lines_left == 0)
1179     break;
1180     }
1181     }
1182    
1183     last_unasm_addr = addr;
1184    
1185     strlcpy(repeat_cmd, "unassemble", MAX_CMD_BUFLEN);
1186     }
1187    
1188    
1189     /*
1190     * debugger_cmd_version():
1191     */
1192     static void debugger_cmd_version(struct machine *m, char *cmd_line)
1193     {
1194     if (*cmd_line) {
1195     printf("syntax: version\n");
1196     return;
1197     }
1198    
1199     #ifdef VERSION
1200     printf("%s, %s\n", VERSION, COMPILE_DATE);
1201     #else
1202     printf("(no version), %s\n", COMPILE_DATE);
1203     #endif
1204     }
1205    
1206    
1207     /****************************************************************************/
1208    
1209    
1210     struct cmd {
1211     char *name;
1212     char *args;
1213     int tmp_flag;
1214     void (*f)(struct machine *, char *cmd_line);
1215     char *description;
1216     };
1217    
1218     static struct cmd cmds[] = {
1219     { "allsettings", "", 0, debugger_cmd_allsettings,
1220     "show all settings" },
1221    
1222     { "breakpoint", "...", 0, debugger_cmd_breakpoint,
1223     "manipulate breakpoints" },
1224    
1225     /* NOTE: Try to keep 'c' down to only one command. Having 'continue'
1226     available as a one-letter command is very convenient. */
1227    
1228     { "continue", "", 0, debugger_cmd_continue,
1229     "continue execution" },
1230    
1231     { "device", "...", 0, debugger_cmd_device,
1232     "show info about (or manipulate) devices" },
1233    
1234     { "dump", "[addr [endaddr]]", 0, debugger_cmd_dump,
1235     "dump memory contents in hex and ASCII" },
1236    
1237     { "emuls", "", 0, debugger_cmd_emuls,
1238     "print a summary of all current emuls" },
1239    
1240     { "focus", "x[,y]", 0, debugger_cmd_focus,
1241     "changes focus to machine x (in emul y)" },
1242    
1243     { "help", "", 0, debugger_cmd_help,
1244     "print this help message" },
1245    
1246     { "itrace", "", 0, debugger_cmd_itrace,
1247     "toggle instruction_trace on or off" },
1248    
1249     { "lookup", "name|addr", 0, debugger_cmd_lookup,
1250     "lookup a symbol by name or address" },
1251    
1252     { "machine", "", 0, debugger_cmd_machine,
1253     "print a summary of the current machine" },
1254    
1255     { "ninstrs", "[on|off]", 0, debugger_cmd_ninstrs,
1256     "toggle (set or unset) show_nr_of_instructions" },
1257    
1258     { "pause", "cpuid", 0, debugger_cmd_pause,
1259     "pause (or unpause) a CPU" },
1260    
1261     { "print", "expr", 0, debugger_cmd_print,
1262     "evaluate an expression without side-effects" },
1263    
1264     { "put", "[b|h|w|d|q] addr, data", 0, debugger_cmd_put,
1265     "modify emulated memory contents" },
1266    
1267     { "quiet", "[on|off]", 0, debugger_cmd_quiet,
1268     "toggle quiet_mode on or off" },
1269    
1270     { "quit", "", 0, debugger_cmd_quit,
1271     "quit the emulator" },
1272    
1273     /* NOTE: Try to keep 'r' down to only one command. Having 'reg'
1274     available as a one-letter command is very convenient. */
1275    
1276     { "reg", "[cpuid][,c]", 0, debugger_cmd_reg,
1277     "show GPRs (or coprocessor c's registers)" },
1278    
1279     /* NOTE: Try to keep 's' down to only one command. Having 'step'
1280     available as a one-letter command is very convenient. */
1281    
1282     { "step", "[n]", 0, debugger_cmd_step,
1283     "single-step one (or n) instruction(s)" },
1284    
1285     { "tlbdump", "[cpuid][,r]", 0, debugger_cmd_tlbdump,
1286     "dump TLB contents (add ',r' for raw data)" },
1287    
1288     { "trace", "[on|off]", 0, debugger_cmd_trace,
1289     "toggle show_trace_tree on or off" },
1290    
1291     { "unassemble", "[addr [endaddr]]", 0, debugger_cmd_unassemble,
1292     "dump memory contents as instructions" },
1293    
1294     { "version", "", 0, debugger_cmd_version,
1295     "print version information" },
1296    
1297     /* Note: NULL handler. */
1298     { "x = expr", "", 0, NULL, "generic assignment" },
1299    
1300     { NULL, NULL, 0, NULL, NULL }
1301     };
1302    
1303    
1304     /*
1305     * debugger_cmd_help():
1306     *
1307     * Print a list of available commands.
1308     *
1309     * NOTE: This is placed after the cmds[] array, because it needs to
1310     * access it.
1311     *
1312     * TODO: Command completion (ie just type "help s" for "help step").
1313     */
1314     static void debugger_cmd_help(struct machine *m, char *cmd_line)
1315     {
1316     int only_one = 0, only_one_match = 0;
1317     char *nlines_env = getenv("LINES");
1318     int nlines = atoi(nlines_env != NULL? nlines_env : "999999"), curlines;
1319     size_t i, j, max_name_len = 0;
1320    
1321     if (cmd_line[0] != '\0') {
1322     only_one = 1;
1323     }
1324    
1325     i = 0;
1326     while (cmds[i].name != NULL) {
1327     size_t a = strlen(cmds[i].name);
1328     if (cmds[i].args != NULL)
1329     a += 1 + strlen(cmds[i].args);
1330     if (a > max_name_len)
1331     max_name_len = a;
1332     i++;
1333     }
1334    
1335     curlines = 0;
1336     if (!only_one) {
1337     printf("Available commands:\n");
1338     curlines++;
1339     }
1340    
1341     i = 0;
1342     while (cmds[i].name != NULL) {
1343     char buf[100];
1344     snprintf(buf, sizeof(buf), "%s", cmds[i].name);
1345    
1346     if (only_one) {
1347     if (strcmp(cmds[i].name, cmd_line) != 0) {
1348     i++;
1349     continue;
1350     }
1351     only_one_match = 1;
1352     }
1353    
1354     if (cmds[i].args != NULL)
1355     snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
1356     " %s", cmds[i].args);
1357    
1358     printf(" ");
1359     for (j=0; j<max_name_len; j++)
1360     if (j < strlen(buf))
1361     printf("%c", buf[j]);
1362     else
1363     printf(" ");
1364    
1365     printf(" %s\n", cmds[i].description);
1366     i++;
1367    
1368     curlines ++;
1369     if (curlines >= nlines - 1) {
1370     char ch;
1371     printf("-- more --"); fflush(stdout);
1372     ch = debugger_readchar();
1373     printf("\n");
1374     if (ch == 'q' || ch == 'Q')
1375     return;
1376     curlines = 0;
1377     }
1378     }
1379    
1380     if (only_one) {
1381     if (!only_one_match)
1382     printf("%s: no such command\n", cmd_line);
1383     return;
1384     }
1385    
1386     /* TODO: generalize/refactor */
1387     curlines += 8;
1388     if (curlines > nlines - 1) {
1389     char ch;
1390     printf("-- more --"); fflush(stdout);
1391     ch = debugger_readchar();
1392     printf("\n");
1393     if (ch == 'q' || ch == 'Q')
1394     return;
1395     curlines = 0;
1396     }
1397    
1398     printf("\nIn generic assignments, x must be a register, and expr can be"
1399     " a register, a\nnumeric value, or a symbol name (+ an optional "
1400     "numeric offset). In case there\nare multiple matches (i.e. a "
1401     "symbol that has the same name as a register), you\nmay add a "
1402     "prefix character as a hint: '%%' for registers, '@' for symbols,"
1403     " and\n'$' for numeric values. Use 0x for hexadecimal values.\n");
1404     }
1405    

  ViewVC Help
Powered by ViewVC 1.1.26