25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: debugger.c,v 1.103 2005/05/13 14:26:29 debug Exp $ |
* $Id: debugger.c,v 1.106 2005/06/26 11:36:27 debug Exp $ |
29 |
* |
* |
30 |
* Single-step debugger. |
* Single-step debugger. |
31 |
* |
* |
101 |
static int exit_debugger; |
static int exit_debugger; |
102 |
static int n_steps_left_before_interaction = 0; |
static int n_steps_left_before_interaction = 0; |
103 |
|
|
104 |
#define MAX_CMD_LEN 70 |
#define MAX_CMD_BUFLEN 72 |
105 |
#define N_PREVIOUS_CMDS 150 |
#define N_PREVIOUS_CMDS 150 |
106 |
static char *last_cmd[N_PREVIOUS_CMDS]; |
static char *last_cmd[N_PREVIOUS_CMDS]; |
107 |
static int last_cmd_index; |
static int last_cmd_index; |
108 |
|
|
109 |
static char repeat_cmd[MAX_CMD_LEN + 1]; |
static char repeat_cmd[MAX_CMD_BUFLEN]; |
110 |
|
|
111 |
#define MAGIC_UNTOUCHED 0x98ca76c2ffcc0011ULL |
#define MAGIC_UNTOUCHED 0x98ca76c2ffcc0011ULL |
112 |
|
|
128 |
if (single_step) { |
if (single_step) { |
129 |
/* Already in the debugger. Do nothing. */ |
/* Already in the debugger. Do nothing. */ |
130 |
int i; |
int i; |
131 |
for (i=0; i<MAX_CMD_LEN+1; i++) |
for (i=0; i<MAX_CMD_BUFLEN; i++) |
132 |
console_makeavail(MAIN_CONSOLE, '\b'); |
console_makeavail(MAIN_CONSOLE, '\b'); |
133 |
console_makeavail(MAIN_CONSOLE, ' '); |
console_makeavail(MAIN_CONSOLE, ' '); |
134 |
console_makeavail(MAIN_CONSOLE, '\n'); |
console_makeavail(MAIN_CONSOLE, '\n'); |
234 |
fprintf(stderr, "out of memory in debugger\n"); |
fprintf(stderr, "out of memory in debugger\n"); |
235 |
exit(1); |
exit(1); |
236 |
} |
} |
237 |
strcpy(sn, name); |
strlcpy(sn, name, strlen(name)+1); |
238 |
|
|
239 |
/* Is there a '+' in there? Then treat that as an offset: */ |
/* Is there a '+' in there? Then treat that as an offset: */ |
240 |
p = strchr(sn, '+'); |
p = strchr(sn, '+'); |
342 |
|
|
343 |
if (strncmp(cmd_line, "add ", 4) == 0) { |
if (strncmp(cmd_line, "add ", 4) == 0) { |
344 |
uint64_t tmp; |
uint64_t tmp; |
345 |
|
size_t breakpoint_buf_len; |
346 |
|
|
347 |
if (m->n_breakpoints >= MAX_BREAKPOINTS) { |
if (m->n_breakpoints >= MAX_BREAKPOINTS) { |
348 |
printf("Too many breakpoints. (You need to recompile" |
printf("Too many breakpoints. (You need to recompile" |
359 |
return; |
return; |
360 |
} |
} |
361 |
|
|
362 |
m->breakpoint_string[i] = malloc(strlen(cmd_line+4) + 1); |
breakpoint_buf_len = strlen(cmd_line+4) + 1; |
363 |
|
m->breakpoint_string[i] = malloc(breakpoint_buf_len); |
364 |
if (m->breakpoint_string[i] == NULL) { |
if (m->breakpoint_string[i] == NULL) { |
365 |
printf("out of memory in debugger_cmd_breakpoint()\n"); |
printf("out of memory in debugger_cmd_breakpoint()\n"); |
366 |
exit(1); |
exit(1); |
367 |
} |
} |
368 |
strcpy(m->breakpoint_string[i], cmd_line+4); |
strlcpy(m->breakpoint_string[i], cmd_line+4, |
369 |
|
breakpoint_buf_len); |
370 |
m->breakpoint_addr[i] = tmp; |
m->breakpoint_addr[i] = tmp; |
371 |
m->breakpoint_flags[i] = 0; |
m->breakpoint_flags[i] = 0; |
372 |
|
|
661 |
|
|
662 |
last_dump_addr = addr_end; |
last_dump_addr = addr_end; |
663 |
|
|
664 |
strcpy(repeat_cmd, "dump"); |
strlcpy(repeat_cmd, "dump", MAX_CMD_BUFLEN); |
665 |
} |
} |
666 |
|
|
667 |
|
|
1212 |
/* Special hack, see debugger() for more info. */ |
/* Special hack, see debugger() for more info. */ |
1213 |
exit_debugger = -1; |
exit_debugger = -1; |
1214 |
|
|
1215 |
strcpy(repeat_cmd, "step"); |
strlcpy(repeat_cmd, "step", MAX_CMD_BUFLEN); |
1216 |
} |
} |
1217 |
|
|
1218 |
|
|
1384 |
|
|
1385 |
last_unasm_addr = addr; |
last_unasm_addr = addr; |
1386 |
|
|
1387 |
strcpy(repeat_cmd, "unassemble"); |
strlcpy(repeat_cmd, "unassemble", MAX_CMD_BUFLEN); |
1388 |
} |
} |
1389 |
|
|
1390 |
|
|
1501 |
* |
* |
1502 |
* NOTE: This is placed after the cmds[] array, because it needs to |
* NOTE: This is placed after the cmds[] array, because it needs to |
1503 |
* access it. |
* access it. |
1504 |
|
* |
1505 |
|
* TODO: Command completion (ie just type "help s" for "help step"). |
1506 |
*/ |
*/ |
1507 |
static void debugger_cmd_help(struct machine *m, char *cmd_line) |
static void debugger_cmd_help(struct machine *m, char *cmd_line) |
1508 |
{ |
{ |
1509 |
int i, j, max_name_len = 0; |
int i, j, max_name_len = 0, only_one = 0, only_one_match = 0; |
1510 |
|
|
1511 |
|
if (cmd_line[0] != '\0') { |
1512 |
|
only_one = 1; |
1513 |
|
} |
1514 |
|
|
1515 |
i = 0; |
i = 0; |
1516 |
while (cmds[i].name != NULL) { |
while (cmds[i].name != NULL) { |
1522 |
i++; |
i++; |
1523 |
} |
} |
1524 |
|
|
1525 |
printf("Available commands:\n"); |
if (!only_one) |
1526 |
|
printf("Available commands:\n"); |
1527 |
|
|
1528 |
i = 0; |
i = 0; |
1529 |
while (cmds[i].name != NULL) { |
while (cmds[i].name != NULL) { |
1530 |
char buf[100]; |
char buf[100]; |
1531 |
snprintf(buf, sizeof(buf), "%s", cmds[i].name); |
snprintf(buf, sizeof(buf), "%s", cmds[i].name); |
1532 |
|
|
1533 |
|
if (only_one) { |
1534 |
|
if (strcmp(cmds[i].name, cmd_line) != 0) { |
1535 |
|
i++; |
1536 |
|
continue; |
1537 |
|
} |
1538 |
|
only_one_match = 1; |
1539 |
|
} |
1540 |
|
|
1541 |
if (cmds[i].args != NULL) |
if (cmds[i].args != NULL) |
1542 |
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
1543 |
" %s", cmds[i].args); |
" %s", cmds[i].args); |
1553 |
i++; |
i++; |
1554 |
} |
} |
1555 |
|
|
1556 |
|
if (only_one) { |
1557 |
|
if (!only_one_match) |
1558 |
|
printf("%s: no such command\n", cmd_line); |
1559 |
|
return; |
1560 |
|
} |
1561 |
|
|
1562 |
printf("Generic assignments: x = expr\n"); |
printf("Generic assignments: x = expr\n"); |
1563 |
printf("where x must be a register, and expr can be a register, a " |
printf("where x must be a register, and expr can be a register, a " |
1564 |
"numeric value, or\na symbol name (+ an optional numeric offset)." |
"numeric value, or\na symbol name (+ an optional numeric offset)." |
1583 |
int res_left, res_right; |
int res_left, res_right; |
1584 |
uint64_t tmp; |
uint64_t tmp; |
1585 |
|
|
1586 |
left = malloc(strlen(cmd) + 1); |
left = malloc(MAX_CMD_BUFLEN); |
1587 |
if (left == NULL) { |
if (left == NULL) { |
1588 |
fprintf(stderr, "out of memory in debugger_assignment()\n"); |
fprintf(stderr, "out of memory in debugger_assignment()\n"); |
1589 |
exit(1); |
exit(1); |
1590 |
} |
} |
1591 |
strcpy(left, cmd); |
strlcpy(left, cmd, MAX_CMD_BUFLEN); |
1592 |
right = strchr(left, '='); |
right = strchr(left, '='); |
1593 |
if (right == NULL) { |
if (right == NULL) { |
1594 |
fprintf(stderr, "internal error in the debugger\n"); |
fprintf(stderr, "internal error in the debugger\n"); |
1717 |
} |
} |
1718 |
} else if (ch == 11) { |
} else if (ch == 11) { |
1719 |
/* CTRL-K: Kill to end of line. */ |
/* CTRL-K: Kill to end of line. */ |
1720 |
for (i=0; i<MAX_CMD_LEN; i++) |
for (i=0; i<MAX_CMD_BUFLEN; i++) |
1721 |
console_makeavail(MAIN_CONSOLE, 4); /* :-) */ |
console_makeavail(MAIN_CONSOLE, 4); /* :-) */ |
1722 |
} else if (ch == 14 || ch == 16) { |
} else if (ch == 14 || ch == 16) { |
1723 |
/* CTRL-P: Previous line in the command history, |
/* CTRL-P: Previous line in the command history, |
1755 |
printf(" "); |
printf(" "); |
1756 |
for (i=cmd_len-1; i>=0; i--) |
for (i=cmd_len-1; i>=0; i--) |
1757 |
printf("\b \b"); |
printf("\b \b"); |
1758 |
strcpy(cmd, |
strlcpy(cmd, |
1759 |
last_cmd[read_from_index]); |
last_cmd[read_from_index], |
1760 |
|
MAX_CMD_BUFLEN); |
1761 |
cmd_len = strlen(cmd); |
cmd_len = strlen(cmd); |
1762 |
printf("%s", cmd); |
printf("%s", cmd); |
1763 |
cursor_pos = cmd_len; |
cursor_pos = cmd_len; |
1764 |
} |
} |
1765 |
} while (0); |
} while (0); |
1766 |
} else if (ch >= ' ' && cmd_len < MAX_CMD_LEN) { |
} else if (ch >= ' ' && cmd_len < MAX_CMD_BUFLEN-1) { |
1767 |
/* Visible character: */ |
/* Visible character: */ |
1768 |
memmove(cmd + cursor_pos + 1, cmd + cursor_pos, |
memmove(cmd + cursor_pos + 1, cmd + cursor_pos, |
1769 |
cmd_len - cursor_pos); |
cmd_len - cursor_pos); |
1934 |
if (cmd_len == 0) { |
if (cmd_len == 0) { |
1935 |
/* Special case for repeated commands: */ |
/* Special case for repeated commands: */ |
1936 |
if (repeat_cmd[0] != '\0') |
if (repeat_cmd[0] != '\0') |
1937 |
strcpy(cmd, repeat_cmd); |
strlcpy(cmd, repeat_cmd, MAX_CMD_BUFLEN); |
1938 |
else |
else |
1939 |
continue; |
continue; |
1940 |
} else { |
} else { |
2031 |
return; |
return; |
2032 |
} |
} |
2033 |
|
|
2034 |
|
gettimeofday(&debugger_machine->starttime, NULL); |
2035 |
|
debugger_machine->ncycles_since_gettimeofday = 0; |
2036 |
|
|
2037 |
single_step = 0; |
single_step = 0; |
2038 |
debugger_machine->instruction_trace = old_instruction_trace; |
debugger_machine->instruction_trace = old_instruction_trace; |
2039 |
debugger_machine->show_trace_tree = old_show_trace_tree; |
debugger_machine->show_trace_tree = old_show_trace_tree; |
2082 |
debugger_machine = emuls[0]->machines[0]; |
debugger_machine = emuls[0]->machines[0]; |
2083 |
|
|
2084 |
for (i=0; i<N_PREVIOUS_CMDS; i++) { |
for (i=0; i<N_PREVIOUS_CMDS; i++) { |
2085 |
last_cmd[i] = malloc(MAX_CMD_LEN + 1); |
last_cmd[i] = malloc(MAX_CMD_BUFLEN); |
2086 |
if (last_cmd[i] == NULL) { |
if (last_cmd[i] == NULL) { |
2087 |
fprintf(stderr, "debugger_init(): out of memory\n"); |
fprintf(stderr, "debugger_init(): out of memory\n"); |
2088 |
exit(1); |
exit(1); |