1 |
/* |
/* |
2 |
* Copyright (C) 2004-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2004-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: debugger_cmds.c,v 1.8 2006/10/14 02:30:12 debug Exp $ |
* $Id: debugger_cmds.c,v 1.14 2007/06/28 14:58:38 debug Exp $ |
29 |
* |
* |
30 |
* Debugger commands. Included from debugger.c. |
* Debugger commands. Included from debugger.c. |
31 |
*/ |
*/ |
62 |
} |
} |
63 |
|
|
64 |
if (strcmp(cmd_line, "show") == 0) { |
if (strcmp(cmd_line, "show") == 0) { |
65 |
if (m->n_breakpoints == 0) |
if (m->breakpoints.n == 0) |
66 |
printf("No breakpoints set.\n"); |
printf("No breakpoints set.\n"); |
67 |
for (i=0; i<m->n_breakpoints; i++) |
for (i=0; i<m->breakpoints.n; i++) |
68 |
show_breakpoint(m, i); |
show_breakpoint(m, i); |
69 |
return; |
return; |
70 |
} |
} |
72 |
if (strncmp(cmd_line, "delete ", 7) == 0) { |
if (strncmp(cmd_line, "delete ", 7) == 0) { |
73 |
int x = atoi(cmd_line + 7); |
int x = atoi(cmd_line + 7); |
74 |
|
|
75 |
if (m->n_breakpoints == 0) { |
if (m->breakpoints.n == 0) { |
76 |
printf("No breakpoints set.\n"); |
printf("No breakpoints set.\n"); |
77 |
return; |
return; |
78 |
} |
} |
79 |
if (x < 0 || x >= m->n_breakpoints) { |
if (x < 0 || x > m->breakpoints.n) { |
80 |
printf("Invalid breakpoint nr %i. Use 'breakpoint " |
printf("Invalid breakpoint nr %i. Use 'breakpoint " |
81 |
"show' to see the current breakpoints.\n", x); |
"show' to see the current breakpoints.\n", x); |
82 |
return; |
return; |
83 |
} |
} |
84 |
|
|
85 |
free(m->breakpoint_string[x]); |
free(m->breakpoints.string[x]); |
86 |
|
|
87 |
for (i=x; i<m->n_breakpoints-1; i++) { |
for (i=x; i<m->breakpoints.n-1; i++) { |
88 |
m->breakpoint_addr[i] = m->breakpoint_addr[i+1]; |
m->breakpoints.addr[i] = m->breakpoints.addr[i+1]; |
89 |
m->breakpoint_string[i] = m->breakpoint_string[i+1]; |
m->breakpoints.string[i] = m->breakpoints.string[i+1]; |
|
m->breakpoint_flags[i] = m->breakpoint_flags[i+1]; |
|
90 |
} |
} |
91 |
m->n_breakpoints --; |
m->breakpoints.n --; |
92 |
|
|
93 |
/* Clear translations: */ |
/* Clear translations: */ |
94 |
for (i=0; i<m->ncpus; i++) |
for (i=0; i<m->ncpus; i++) |
101 |
uint64_t tmp; |
uint64_t tmp; |
102 |
size_t breakpoint_buf_len; |
size_t breakpoint_buf_len; |
103 |
|
|
104 |
if (m->n_breakpoints >= MAX_BREAKPOINTS) { |
i = m->breakpoints.n; |
|
printf("Too many breakpoints. (You need to recompile" |
|
|
" gxemul to increase this. Max = %i.)\n", |
|
|
MAX_BREAKPOINTS); |
|
|
return; |
|
|
} |
|
|
|
|
|
i = m->n_breakpoints; |
|
105 |
|
|
106 |
res = debugger_parse_expression(m, cmd_line + 4, 0, &tmp); |
res = debugger_parse_expression(m, cmd_line + 4, 0, &tmp); |
107 |
if (!res) { |
if (!res) { |
109 |
return; |
return; |
110 |
} |
} |
111 |
|
|
112 |
|
CHECK_ALLOCATION(m->breakpoints.string = realloc( |
113 |
|
m->breakpoints.string, sizeof(char *) * |
114 |
|
(m->breakpoints.n + 1))); |
115 |
|
CHECK_ALLOCATION(m->breakpoints.addr = realloc( |
116 |
|
m->breakpoints.addr, sizeof(uint64_t) * |
117 |
|
(m->breakpoints.n + 1))); |
118 |
|
|
119 |
breakpoint_buf_len = strlen(cmd_line+4) + 1; |
breakpoint_buf_len = strlen(cmd_line+4) + 1; |
120 |
m->breakpoint_string[i] = malloc(breakpoint_buf_len); |
|
121 |
if (m->breakpoint_string[i] == NULL) { |
CHECK_ALLOCATION(m->breakpoints.string[i] = |
122 |
printf("out of memory in debugger_cmd_breakpoint()\n"); |
malloc(breakpoint_buf_len)); |
123 |
exit(1); |
strlcpy(m->breakpoints.string[i], cmd_line+4, |
|
} |
|
|
strlcpy(m->breakpoint_string[i], cmd_line+4, |
|
124 |
breakpoint_buf_len); |
breakpoint_buf_len); |
125 |
m->breakpoint_addr[i] = tmp; |
m->breakpoints.addr[i] = tmp; |
|
m->breakpoint_flags[i] = 0; |
|
126 |
|
|
127 |
m->n_breakpoints ++; |
m->breakpoints.n ++; |
128 |
show_breakpoint(m, i); |
show_breakpoint(m, i); |
129 |
|
|
130 |
/* Clear translations: */ |
/* Clear translations: */ |
254 |
|
|
255 |
if (cmd_line[0] != '\0') { |
if (cmd_line[0] != '\0') { |
256 |
uint64_t tmp; |
uint64_t tmp; |
257 |
char *tmps = strdup(cmd_line); |
char *tmps; |
258 |
|
|
259 |
|
CHECK_ALLOCATION(tmps = strdup(cmd_line)); |
260 |
|
|
261 |
/* addr: */ |
/* addr: */ |
262 |
p = strchr(tmps, ' '); |
p = strchr(tmps, ' '); |
355 |
|
|
356 |
|
|
357 |
/* |
/* |
358 |
* debugger_cmd_emuls(): |
* debugger_cmd_emul(): |
359 |
* |
* |
360 |
* Dump info about all current emuls. |
* Dump info about the current emulation. |
361 |
*/ |
*/ |
362 |
static void debugger_cmd_emuls(struct machine *m, char *cmd_line) |
static void debugger_cmd_emul(struct machine *m, char *cmd_line) |
363 |
{ |
{ |
364 |
int i, iadd = DEBUG_INDENTATION; |
int iadd = DEBUG_INDENTATION; |
365 |
|
|
366 |
if (*cmd_line) { |
if (*cmd_line) { |
367 |
printf("syntax: emuls\n"); |
printf("syntax: emul\n"); |
368 |
return; |
return; |
369 |
} |
} |
370 |
|
|
371 |
for (i=0; i<debugger_n_emuls; i++) { |
debug("emulation \"%s\":\n", debugger_emul->name == NULL? |
372 |
struct emul *e = debugger_emuls[i]; |
"(simple setup)" : debugger_emul->name); |
|
|
|
|
if (e == NULL) |
|
|
continue; |
|
|
|
|
|
debug("emulation %i: \"%s\"\n", i, |
|
|
e->name == NULL? "(no name)" : e->name); |
|
|
debug_indentation(iadd); |
|
|
|
|
|
emul_dumpinfo(e); |
|
373 |
|
|
374 |
debug_indentation(-iadd); |
debug_indentation(iadd); |
375 |
} |
emul_dumpinfo(debugger_emul); |
376 |
|
debug_indentation(-iadd); |
377 |
} |
} |
378 |
|
|
379 |
|
|
385 |
*/ |
*/ |
386 |
static void debugger_cmd_focus(struct machine *m, char *cmd_line) |
static void debugger_cmd_focus(struct machine *m, char *cmd_line) |
387 |
{ |
{ |
388 |
int x = -1, y = -1, z = -1; |
int x = -1, y = -1; |
389 |
char *p, *p2; |
char *p, *p2; |
390 |
|
|
391 |
if (!cmd_line[0]) { |
if (!cmd_line[0]) { |
392 |
printf("syntax: focus x[,y,[,z]]\n"); |
printf("syntax: focus x[,y]\n"); |
393 |
printf("where x (cpu id), y (machine number), and z (emul " |
printf("where x (cpu id) and y (machine number) " |
394 |
"number) are integers as\nreported by the 'emuls'" |
"are integers as\nreported by the 'emul'" |
395 |
" command.\n"); |
" command.\n"); |
396 |
goto print_current_focus_and_return; |
goto print_current_focus_and_return; |
397 |
} |
} |
410 |
printf("No machine number specified?\n"); |
printf("No machine number specified?\n"); |
411 |
return; |
return; |
412 |
} |
} |
|
|
|
|
if (p2 != NULL) |
|
|
z = atoi(p2 + 1); |
|
|
} |
|
|
|
|
|
if (z != -1) { |
|
|
/* Change emul: */ |
|
|
if (z < 0 || z >= debugger_n_emuls) { |
|
|
printf("Invalid emul number: %i\n", z); |
|
|
return; |
|
|
} |
|
|
|
|
|
debugger_cur_emul = z; |
|
|
debugger_emul = debugger_emuls[z]; |
|
|
|
|
|
/* This is just in case the machine change below fails... */ |
|
|
debugger_machine = debugger_emul->machines[0]; |
|
413 |
} |
} |
414 |
|
|
415 |
if (y != -1) { |
if (y != -1) { |
432 |
debugger_cur_cpu = x; |
debugger_cur_cpu = x; |
433 |
|
|
434 |
print_current_focus_and_return: |
print_current_focus_and_return: |
|
if (debugger_n_emuls > 1) |
|
|
printf("current emul (%i): \"%s\"\n", |
|
|
debugger_cur_emul, debugger_emul->name == NULL? |
|
|
"(no name)" : debugger_emul->name); |
|
|
|
|
435 |
if (debugger_emul->n_machines > 1) |
if (debugger_emul->n_machines > 1) |
436 |
printf("current machine (%i): \"%s\"\n", |
printf("current machine (%i): \"%s\"\n", |
437 |
debugger_cur_machine, debugger_machine->name == NULL? |
debugger_cur_machine, debugger_machine->name == NULL? |
519 |
*/ |
*/ |
520 |
static void debugger_cmd_machine(struct machine *m, char *cmd_line) |
static void debugger_cmd_machine(struct machine *m, char *cmd_line) |
521 |
{ |
{ |
522 |
int iadd = DEBUG_INDENTATION; |
int iadd = 0; |
523 |
|
|
524 |
if (*cmd_line) { |
if (*cmd_line) { |
525 |
printf("syntax: machine\n"); |
printf("syntax: machine\n"); |
526 |
return; |
return; |
527 |
} |
} |
528 |
|
|
529 |
debug("machine \"%s\":\n", m->name); |
if (m->name != NULL) { |
530 |
|
debug("machine \"%s\":\n", m->name); |
531 |
|
iadd = DEBUG_INDENTATION; |
532 |
|
} |
533 |
|
|
534 |
debug_indentation(iadd); |
debug_indentation(iadd); |
535 |
machine_dumpinfo(m); |
machine_dumpinfo(m); |
536 |
debug_indentation(-iadd); |
debug_indentation(-iadd); |
884 |
*/ |
*/ |
885 |
static void debugger_cmd_quit(struct machine *m, char *cmd_line) |
static void debugger_cmd_quit(struct machine *m, char *cmd_line) |
886 |
{ |
{ |
887 |
int i, j, k; |
int j, k; |
|
struct emul *e; |
|
888 |
|
|
889 |
if (*cmd_line) { |
if (*cmd_line) { |
890 |
printf("syntax: quit\n"); |
printf("syntax: quit\n"); |
891 |
return; |
return; |
892 |
} |
} |
893 |
|
|
894 |
for (i=0; i<debugger_n_emuls; i++) { |
single_step = NOT_SINGLE_STEPPING; |
|
single_step = NOT_SINGLE_STEPPING; |
|
895 |
|
|
896 |
e = debugger_emuls[i]; |
force_debugger_at_exit = 0; |
|
force_debugger_at_exit = 0; |
|
897 |
|
|
898 |
for (j=0; j<e->n_machines; j++) { |
for (j=0; j<debugger_emul->n_machines; j++) { |
899 |
struct machine *m = e->machines[j]; |
struct machine *m = debugger_emul->machines[j]; |
900 |
|
|
901 |
for (k=0; k<m->ncpus; k++) |
for (k=0; k<m->ncpus; k++) |
902 |
m->cpus[k]->running = 0; |
m->cpus[k]->running = 0; |
903 |
|
|
904 |
m->exit_without_entering_debugger = 1; |
m->exit_without_entering_debugger = 1; |
|
} |
|
905 |
} |
} |
906 |
|
|
907 |
exit_debugger = 1; |
exit_debugger = 1; |
1070 |
|
|
1071 |
if (cmd_line[0] != '\0') { |
if (cmd_line[0] != '\0') { |
1072 |
uint64_t tmp; |
uint64_t tmp; |
1073 |
char *tmps = strdup(cmd_line); |
char *tmps; |
1074 |
|
|
1075 |
|
CHECK_ALLOCATION(tmps = strdup(cmd_line)); |
1076 |
|
|
1077 |
/* addr: */ |
/* addr: */ |
1078 |
p = strchr(tmps, ' '); |
p = strchr(tmps, ' '); |
1175 |
return; |
return; |
1176 |
} |
} |
1177 |
|
|
|
#ifdef VERSION |
|
1178 |
printf("%s, %s\n", VERSION, COMPILE_DATE); |
printf("%s, %s\n", VERSION, COMPILE_DATE); |
|
#else |
|
|
printf("(no version), %s\n", COMPILE_DATE); |
|
|
#endif |
|
1179 |
} |
} |
1180 |
|
|
1181 |
|
|
1209 |
{ "dump", "[addr [endaddr]]", 0, debugger_cmd_dump, |
{ "dump", "[addr [endaddr]]", 0, debugger_cmd_dump, |
1210 |
"dump memory contents in hex and ASCII" }, |
"dump memory contents in hex and ASCII" }, |
1211 |
|
|
1212 |
{ "emuls", "", 0, debugger_cmd_emuls, |
{ "emul", "", 0, debugger_cmd_emul, |
1213 |
"print a summary of all current emuls" }, |
"print a summary of the current emulation" }, |
1214 |
|
|
1215 |
{ "focus", "x[,y[,z]]", 0, debugger_cmd_focus, |
{ "focus", "x[,y[,z]]", 0, debugger_cmd_focus, |
1216 |
"changes focus to cpu x, machine x, emul z" }, |
"changes focus to cpu x, machine x, emul z" }, |
1373 |
printf("\nIn generic assignments, x must be a register or other " |
printf("\nIn generic assignments, x must be a register or other " |
1374 |
"writable settings\nvariable, and expr can contain registers/" |
"writable settings\nvariable, and expr can contain registers/" |
1375 |
"settings, numeric values, or symbol\nnames, in combination with" |
"settings, numeric values, or symbol\nnames, in combination with" |
1376 |
" parenthesis and + - * / %% ^ | operators.\nIn case there are" |
" parenthesis and + - * / & %% ^ | operators.\nIn case there are" |
1377 |
" multiple matches (i.e. a symbol that has the same name as a\n" |
" multiple matches (i.e. a symbol that has the same name as a\n" |
1378 |
"register), you may add a prefix character as a hint: '#' for" |
"register), you may add a prefix character as a hint: '#' for" |
1379 |
" registers, '@'\nfor symbols, and '$' for numeric values. Use" |
" registers, '@'\nfor symbols, and '$' for numeric values. Use" |