25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: debugger.c,v 1.106 2005/06/26 11:36:27 debug Exp $ |
* $Id: debugger.c,v 1.125 2005/11/13 00:14:06 debug Exp $ |
29 |
* |
* |
30 |
* Single-step debugger. |
* Single-step debugger. |
31 |
* |
* |
82 |
int force_debugger_at_exit = 0; |
int force_debugger_at_exit = 0; |
83 |
int show_opcode_statistics = 0; |
int show_opcode_statistics = 0; |
84 |
|
|
85 |
|
volatile int single_step_breakpoint = 0; |
86 |
|
int debugger_n_steps_left_before_interaction = 0; |
87 |
|
|
88 |
int old_instruction_trace = 0; |
int old_instruction_trace = 0; |
89 |
int old_quiet_mode = 0; |
int old_quiet_mode = 0; |
90 |
int old_show_trace_tree = 0; |
int old_show_trace_tree = 0; |
102 |
static struct machine *debugger_machine; |
static struct machine *debugger_machine; |
103 |
|
|
104 |
static int exit_debugger; |
static int exit_debugger; |
|
static int n_steps_left_before_interaction = 0; |
|
105 |
|
|
106 |
#define MAX_CMD_BUFLEN 72 |
#define MAX_CMD_BUFLEN 72 |
107 |
#define N_PREVIOUS_CMDS 150 |
#define N_PREVIOUS_CMDS 150 |
117 |
|
|
118 |
|
|
119 |
/* |
/* |
120 |
|
* debugger_readchar(): |
121 |
|
* |
122 |
|
* TODO: This uses up 100% CPU, maybe that isn't too good. The usleep() call |
123 |
|
* might make it a tiny bit nicer on other running processes, but it |
124 |
|
* is still very ugly. |
125 |
|
*/ |
126 |
|
char debugger_readchar(void) |
127 |
|
{ |
128 |
|
int ch; |
129 |
|
while ((ch = console_readchar(MAIN_CONSOLE)) < 0) { |
130 |
|
x11_check_event(debugger_emuls, debugger_n_emuls); |
131 |
|
usleep(1); |
132 |
|
} |
133 |
|
return ch; |
134 |
|
} |
135 |
|
|
136 |
|
|
137 |
|
/* |
138 |
* debugger_activate(): |
* debugger_activate(): |
139 |
* |
* |
140 |
* This is a signal handler for CTRL-C. It shouldn't be called directly, |
* This is a signal handler for CTRL-C. It shouldn't be called directly, |
180 |
* Some examples: |
* Some examples: |
181 |
* |
* |
182 |
* "0x7fff1234" ==> numeric value (hex, in this case) |
* "0x7fff1234" ==> numeric value (hex, in this case) |
183 |
* "pc", "r5", "hi", "t4" ==> register (CPU dependant) |
* "pc", "r5", "hi", "t4" ==> register (CPU dependent) |
184 |
* "memcpy+64" ==> symbol (plus offset) |
* "memcpy+64" ==> symbol (plus offset) |
185 |
* |
* |
186 |
* Register names can be preceeded by "x:" where x is the CPU number. (CPU |
* Register names can be preceeded by "x:" where x is the CPU number. (CPU |
218 |
} |
} |
219 |
|
|
220 |
/* Warn about non-signextended values: */ |
/* Warn about non-signextended values: */ |
221 |
if (writeflag && |
if (writeflag) { |
222 |
((*valuep) >> 32) == 0 && (*valuep) & 0x80000000ULL) |
if (m->cpus[0]->is_32bit) { |
223 |
printf("WARNING: The value is not sign-extended. " |
/* Automagically sign-extend. TODO: Is this good? */ |
224 |
"Is this what you intended?\n"); |
if (((*valuep) >> 32) == 0 && (*valuep) & 0x80000000ULL) |
225 |
|
(*valuep) |= 0xffffffff00000000ULL; |
226 |
|
} else { |
227 |
|
if (((*valuep) >> 32) == 0 && (*valuep) & 0x80000000ULL) |
228 |
|
printf("WARNING: The value is not sign-extende" |
229 |
|
"d. Is this what you intended?\n"); |
230 |
|
} |
231 |
|
} |
232 |
|
|
233 |
skip_register = name[0] == '$' || name[0] == '@'; |
skip_register = name[0] == '$' || name[0] == '@'; |
234 |
skip_numeric = name[0] == '%' || name[0] == '@'; |
skip_numeric = name[0] == '%' || name[0] == '@'; |
301 |
*/ |
*/ |
302 |
static void show_breakpoint(struct machine *m, int i) |
static void show_breakpoint(struct machine *m, int i) |
303 |
{ |
{ |
304 |
printf("%3i: 0x%016llx", i, |
printf("%3i: 0x", i); |
305 |
(long long)m->breakpoint_addr[i]); |
if (m->cpus[0]->is_32bit) |
306 |
|
printf("%08x", (int)m->breakpoint_addr[i]); |
307 |
|
else |
308 |
|
printf("%016llx", (long long)m->breakpoint_addr[i]); |
309 |
if (m->breakpoint_string[i] != NULL) |
if (m->breakpoint_string[i] != NULL) |
310 |
printf(" (%s)", m->breakpoint_string[i]); |
printf(" (%s)", m->breakpoint_string[i]); |
311 |
if (m->breakpoint_flags[i]) |
if (m->breakpoint_flags[i]) |
367 |
m->breakpoint_flags[i] = m->breakpoint_flags[i+1]; |
m->breakpoint_flags[i] = m->breakpoint_flags[i+1]; |
368 |
} |
} |
369 |
m->n_breakpoints --; |
m->n_breakpoints --; |
370 |
|
|
371 |
|
/* Clear translations: */ |
372 |
|
for (i=0; i<m->ncpus; i++) |
373 |
|
if (m->cpus[i]->translation_cache != NULL) |
374 |
|
cpu_create_or_reset_tc(m->cpus[i]); |
375 |
return; |
return; |
376 |
} |
} |
377 |
|
|
407 |
|
|
408 |
m->n_breakpoints ++; |
m->n_breakpoints ++; |
409 |
show_breakpoint(m, i); |
show_breakpoint(m, i); |
410 |
|
|
411 |
|
/* Clear translations: */ |
412 |
|
for (i=0; i<m->ncpus; i++) |
413 |
|
if (m->cpus[i]->translation_cache != NULL) |
414 |
|
cpu_create_or_reset_tc(m->cpus[i]); |
415 |
return; |
return; |
416 |
} |
} |
417 |
|
|
556 |
(long long)mem->dev_length[i]); |
(long long)mem->dev_length[i]); |
557 |
if (mem->dev_flags[i]) { |
if (mem->dev_flags[i]) { |
558 |
printf(" ("); |
printf(" ("); |
559 |
if (mem->dev_flags[i] & MEM_BINTRANS_OK) |
if (mem->dev_flags[i] & DM_DYNTRANS_OK) |
560 |
printf("BINTRANS R"); |
printf("DYNTRANS R"); |
561 |
if (mem->dev_flags[i] & MEM_BINTRANS_WRITE_OK) |
if (mem->dev_flags[i] & DM_DYNTRANS_WRITE_OK) |
562 |
printf("+W"); |
printf("+W"); |
563 |
printf(")"); |
printf(")"); |
564 |
} |
} |
668 |
r = c->memory_rw(c, mem, addr, &buf[0], sizeof(buf), |
r = c->memory_rw(c, mem, addr, &buf[0], sizeof(buf), |
669 |
MEM_READ, CACHE_NONE | NO_EXCEPTIONS); |
MEM_READ, CACHE_NONE | NO_EXCEPTIONS); |
670 |
|
|
671 |
printf("0x%016llx ", (long long)addr); |
if (c->is_32bit) |
672 |
|
printf("0x%08x ", (int)addr); |
673 |
|
else |
674 |
|
printf("0x%016llx ", (long long)addr); |
675 |
|
|
676 |
if (r == MEMORY_ACCESS_FAILED) |
if (r == MEMORY_ACCESS_FAILED) |
677 |
printf("(memory access failed)\n"); |
printf("(memory access failed)\n"); |
846 |
printf("lookup for '%s' failed\n", cmd_line); |
printf("lookup for '%s' failed\n", cmd_line); |
847 |
return; |
return; |
848 |
} |
} |
849 |
printf("%s = 0x%016llx\n", cmd_line, (long long)newaddr); |
printf("%s = 0x", cmd_line); |
850 |
|
if (m->cpus[0]->is_32bit) |
851 |
|
printf("%08x\n", (int)newaddr); |
852 |
|
else |
853 |
|
printf("%016llx\n", (long long)newaddr); |
854 |
return; |
return; |
855 |
} |
} |
856 |
|
|
857 |
symbol = get_symbol_name(&m->symbol_context, addr, &offset); |
symbol = get_symbol_name(&m->symbol_context, addr, &offset); |
858 |
|
|
859 |
if (symbol != NULL) |
if (symbol != NULL) { |
860 |
printf("0x%016llx = %s\n", (long long)addr, symbol); |
if (m->cpus[0]->is_32bit) |
861 |
else |
printf("0x%08x", (int)addr); |
862 |
|
else |
863 |
|
printf("0x%016llx", (long long)addr); |
864 |
|
printf(" = %s\n", symbol); |
865 |
|
} else |
866 |
printf("lookup for '%s' failed\n", cmd_line); |
printf("lookup for '%s' failed\n", cmd_line); |
867 |
} |
} |
868 |
|
|
889 |
|
|
890 |
|
|
891 |
/* |
/* |
892 |
|
* debugger_cmd_ninstrs(): |
893 |
|
*/ |
894 |
|
static void debugger_cmd_ninstrs(struct machine *m, char *cmd_line) |
895 |
|
{ |
896 |
|
int toggle = 1; |
897 |
|
int previous_mode = m->show_nr_of_instructions; |
898 |
|
|
899 |
|
if (cmd_line[0] != '\0') { |
900 |
|
while (cmd_line[0] != '\0' && cmd_line[0] == ' ') |
901 |
|
cmd_line ++; |
902 |
|
switch (cmd_line[0]) { |
903 |
|
case '0': |
904 |
|
toggle = 0; |
905 |
|
m->show_nr_of_instructions = 0; |
906 |
|
break; |
907 |
|
case '1': |
908 |
|
toggle = 0; |
909 |
|
m->show_nr_of_instructions = 1; |
910 |
|
break; |
911 |
|
case 'o': |
912 |
|
case 'O': |
913 |
|
toggle = 0; |
914 |
|
switch (cmd_line[1]) { |
915 |
|
case 'n': |
916 |
|
case 'N': |
917 |
|
m->show_nr_of_instructions = 1; |
918 |
|
break; |
919 |
|
default: |
920 |
|
m->show_nr_of_instructions = 0; |
921 |
|
} |
922 |
|
break; |
923 |
|
default: |
924 |
|
printf("syntax: trace [on|off]\n"); |
925 |
|
return; |
926 |
|
} |
927 |
|
} |
928 |
|
|
929 |
|
if (toggle) |
930 |
|
m->show_nr_of_instructions = !m->show_nr_of_instructions; |
931 |
|
|
932 |
|
printf("show_nr_of_instructions = %s", |
933 |
|
m->show_nr_of_instructions? "ON" : "OFF"); |
934 |
|
if (m->show_nr_of_instructions != previous_mode) |
935 |
|
printf(" (was: %s)", previous_mode? "ON" : "OFF"); |
936 |
|
printf("\n"); |
937 |
|
} |
938 |
|
|
939 |
|
|
940 |
|
/* |
941 |
* debugger_cmd_opcodestats(): |
* debugger_cmd_opcodestats(): |
942 |
*/ |
*/ |
943 |
static void debugger_cmd_opcodestats(struct machine *m, char *cmd_line) |
static void debugger_cmd_opcodestats(struct machine *m, char *cmd_line) |
1010 |
printf("%s = 0x%llx\n", cmd_line, (long long)tmp); |
printf("%s = 0x%llx\n", cmd_line, (long long)tmp); |
1011 |
break; |
break; |
1012 |
case NAME_PARSE_SYMBOL: |
case NAME_PARSE_SYMBOL: |
1013 |
printf("%s = 0x%016llx\n", cmd_line, (long long)tmp); |
if (m->cpus[0]->is_32bit) |
1014 |
|
printf("%s = 0x%08x\n", cmd_line, (int)tmp); |
1015 |
|
else |
1016 |
|
printf("%s = 0x%016llx\n", cmd_line, (long long)tmp); |
1017 |
break; |
break; |
1018 |
case NAME_PARSE_NUMBER: |
case NAME_PARSE_NUMBER: |
1019 |
printf("0x%llx\n", (long long)tmp); |
printf("0x%llx\n", (long long)tmp); |
1125 |
switch (put_type) { |
switch (put_type) { |
1126 |
case 'b': |
case 'b': |
1127 |
a_byte = data; |
a_byte = data; |
1128 |
printf("0x%016llx: %02x", (long long)addr, a_byte); |
if (m->cpus[0]->is_32bit) |
1129 |
|
printf("0x%08x", (int)addr); |
1130 |
|
else |
1131 |
|
printf("0x%016llx", (long long)addr); |
1132 |
|
printf(": %02x", a_byte); |
1133 |
if (data > 255) |
if (data > 255) |
1134 |
printf(" (NOTE: truncating %0llx)", (long long)data); |
printf(" (NOTE: truncating %0llx)", (long long)data); |
1135 |
res = m->cpus[0]->memory_rw(m->cpus[0], m->cpus[0]->mem, addr, |
res = m->cpus[0]->memory_rw(m->cpus[0], m->cpus[0]->mem, addr, |
1141 |
case 'h': |
case 'h': |
1142 |
if ((data & 1) != 0) |
if ((data & 1) != 0) |
1143 |
printf("WARNING: address isn't aligned\n"); |
printf("WARNING: address isn't aligned\n"); |
1144 |
printf("0x%016llx: %04x", (long long)addr, (int)data); |
if (m->cpus[0]->is_32bit) |
1145 |
|
printf("0x%08x", (int)addr); |
1146 |
|
else |
1147 |
|
printf("0x%016llx", (long long)addr); |
1148 |
|
printf(": %04x", (int)data); |
1149 |
if (data > 0xffff) |
if (data > 0xffff) |
1150 |
printf(" (NOTE: truncating %0llx)", (long long)data); |
printf(" (NOTE: truncating %0llx)", (long long)data); |
1151 |
res = store_16bit_word(m->cpus[0], addr, data); |
res = store_16bit_word(m->cpus[0], addr, data); |
1156 |
case 'w': |
case 'w': |
1157 |
if ((data & 3) != 0) |
if ((data & 3) != 0) |
1158 |
printf("WARNING: address isn't aligned\n"); |
printf("WARNING: address isn't aligned\n"); |
1159 |
printf("0x%016llx: %08x", (long long)addr, (int)data); |
if (m->cpus[0]->is_32bit) |
1160 |
|
printf("0x%08x", (int)addr); |
1161 |
|
else |
1162 |
|
printf("0x%016llx", (long long)addr); |
1163 |
|
printf(": %08x", (int)data); |
1164 |
if (data > 0xffffffff && (data >> 32) != 0 |
if (data > 0xffffffff && (data >> 32) != 0 |
1165 |
&& (data >> 32) != 0xffffffff) |
&& (data >> 32) != 0xffffffff) |
1166 |
printf(" (NOTE: truncating %0llx)", (long long)data); |
printf(" (NOTE: truncating %0llx)", (long long)data); |
1172 |
case 'd': |
case 'd': |
1173 |
if ((data & 7) != 0) |
if ((data & 7) != 0) |
1174 |
printf("WARNING: address isn't aligned\n"); |
printf("WARNING: address isn't aligned\n"); |
1175 |
printf("0x%016llx: %016llx", (long long)addr, (long long)data); |
if (m->cpus[0]->is_32bit) |
1176 |
|
printf("0x%08x", (int)addr); |
1177 |
|
else |
1178 |
|
printf("0x%016llx", (long long)addr); |
1179 |
|
printf(": %016llx", (long long)data); |
1180 |
res = store_64bit_word(m->cpus[0], addr, data); |
res = store_64bit_word(m->cpus[0], addr, data); |
1181 |
if (!res) |
if (!res) |
1182 |
printf(" FAILED!\n"); |
printf(" FAILED!\n"); |
1326 |
} |
} |
1327 |
} |
} |
1328 |
|
|
1329 |
n_steps_left_before_interaction = n - 1; |
debugger_n_steps_left_before_interaction = n - 1; |
1330 |
|
|
1331 |
/* Special hack, see debugger() for more info. */ |
/* Special hack, see debugger() for more info. */ |
1332 |
exit_debugger = -1; |
exit_debugger = -1; |
1378 |
*/ |
*/ |
1379 |
static void debugger_cmd_trace(struct machine *m, char *cmd_line) |
static void debugger_cmd_trace(struct machine *m, char *cmd_line) |
1380 |
{ |
{ |
1381 |
if (*cmd_line) { |
int toggle = 1; |
1382 |
printf("syntax: trace\n"); |
int previous_mode = old_show_trace_tree; |
1383 |
return; |
|
1384 |
|
if (cmd_line[0] != '\0') { |
1385 |
|
while (cmd_line[0] != '\0' && cmd_line[0] == ' ') |
1386 |
|
cmd_line ++; |
1387 |
|
switch (cmd_line[0]) { |
1388 |
|
case '0': |
1389 |
|
toggle = 0; |
1390 |
|
old_show_trace_tree = 0; |
1391 |
|
break; |
1392 |
|
case '1': |
1393 |
|
toggle = 0; |
1394 |
|
old_show_trace_tree = 1; |
1395 |
|
break; |
1396 |
|
case 'o': |
1397 |
|
case 'O': |
1398 |
|
toggle = 0; |
1399 |
|
switch (cmd_line[1]) { |
1400 |
|
case 'n': |
1401 |
|
case 'N': |
1402 |
|
old_show_trace_tree = 1; |
1403 |
|
break; |
1404 |
|
default: |
1405 |
|
old_show_trace_tree = 0; |
1406 |
|
} |
1407 |
|
break; |
1408 |
|
default: |
1409 |
|
printf("syntax: trace [on|off]\n"); |
1410 |
|
return; |
1411 |
|
} |
1412 |
} |
} |
1413 |
|
|
1414 |
old_show_trace_tree = 1 - old_show_trace_tree; |
if (toggle) |
1415 |
printf("show_trace_tree = %s\n", old_show_trace_tree? "ON" : "OFF"); |
old_show_trace_tree = 1 - old_show_trace_tree; |
1416 |
|
|
1417 |
|
printf("show_trace_tree = %s", old_show_trace_tree? "ON" : "OFF"); |
1418 |
|
if (old_show_trace_tree != previous_mode) |
1419 |
|
printf(" (was: %s)", previous_mode? "ON" : "OFF"); |
1420 |
|
printf("\n"); |
1421 |
|
|
1422 |
if (m->bintrans_enable && old_show_trace_tree) |
if (m->bintrans_enable && old_show_trace_tree) |
1423 |
printf("NOTE: the trace tree functionality doesn't " |
printf("NOTE: the trace tree functionality doesn't " |
1424 |
"work very well with bintrans!\n"); |
"work very well with bintrans!\n"); |
|
|
|
|
/* TODO: how to preserve quiet_mode? */ |
|
|
old_quiet_mode = 0; |
|
|
printf("quiet_mode = %s\n", old_quiet_mode? "ON" : "OFF"); |
|
1425 |
} |
} |
1426 |
|
|
1427 |
|
|
1505 |
ctrl_c = 0; |
ctrl_c = 0; |
1506 |
|
|
1507 |
while (addr < addr_end) { |
while (addr < addr_end) { |
1508 |
int i, len; |
unsigned int i, len; |
1509 |
unsigned char buf[32]; /* TODO: How long can an |
unsigned char buf[17]; /* TODO: How long can an |
1510 |
instruction be, on weird archs? */ |
instruction be, on weird archs? */ |
1511 |
memset(buf, 0, sizeof(buf)); |
memset(buf, 0, sizeof(buf)); |
1512 |
|
|
1599 |
{ "machine", "", 0, debugger_cmd_machine, |
{ "machine", "", 0, debugger_cmd_machine, |
1600 |
"print a summary of the current machine" }, |
"print a summary of the current machine" }, |
1601 |
|
|
1602 |
|
{ "ninstrs", "[on|off]", 0, debugger_cmd_ninstrs, |
1603 |
|
"toggle (set or unset) show_nr_of_instructions" }, |
1604 |
|
|
1605 |
{ "opcodestats", "", 0, debugger_cmd_opcodestats, |
{ "opcodestats", "", 0, debugger_cmd_opcodestats, |
1606 |
"show opcode statistics" }, |
"show opcode statistics" }, |
1607 |
|
|
1632 |
{ "tlbdump", "[cpuid][,r]", 0, debugger_cmd_tlbdump, |
{ "tlbdump", "[cpuid][,r]", 0, debugger_cmd_tlbdump, |
1633 |
"dump TLB contents (add ',r' for raw data)" }, |
"dump TLB contents (add ',r' for raw data)" }, |
1634 |
|
|
1635 |
{ "trace", "", 0, debugger_cmd_trace, |
{ "trace", "[on|off]", 0, debugger_cmd_trace, |
1636 |
"toggle show_trace_tree on or off" }, |
"toggle show_trace_tree on or off" }, |
1637 |
|
|
1638 |
{ "unassemble", "[addr [endaddr]]", 0, debugger_cmd_unassemble, |
{ "unassemble", "[addr [endaddr]]", 0, debugger_cmd_unassemble, |
1641 |
{ "version", "", 0, debugger_cmd_version, |
{ "version", "", 0, debugger_cmd_version, |
1642 |
"print version information" }, |
"print version information" }, |
1643 |
|
|
1644 |
|
/* Note: NULL handler. */ |
1645 |
|
{ "x = expr", "", 0, NULL, "generic assignment" }, |
1646 |
|
|
1647 |
{ NULL, NULL, 0, NULL, NULL } |
{ NULL, NULL, 0, NULL, NULL } |
1648 |
}; |
}; |
1649 |
|
|
1660 |
*/ |
*/ |
1661 |
static void debugger_cmd_help(struct machine *m, char *cmd_line) |
static void debugger_cmd_help(struct machine *m, char *cmd_line) |
1662 |
{ |
{ |
1663 |
int i, j, max_name_len = 0, only_one = 0, only_one_match = 0; |
int i, max_name_len = 0, only_one = 0, only_one_match = 0; |
1664 |
|
char *nlines_env = getenv("LINES"); |
1665 |
|
int nlines = atoi(nlines_env != NULL? nlines_env : "999999"); |
1666 |
|
int j, curlines; |
1667 |
|
|
1668 |
if (cmd_line[0] != '\0') { |
if (cmd_line[0] != '\0') { |
1669 |
only_one = 1; |
only_one = 1; |
1679 |
i++; |
i++; |
1680 |
} |
} |
1681 |
|
|
1682 |
if (!only_one) |
curlines = 0; |
1683 |
|
if (!only_one) { |
1684 |
printf("Available commands:\n"); |
printf("Available commands:\n"); |
1685 |
|
curlines++; |
1686 |
|
} |
1687 |
|
|
1688 |
i = 0; |
i = 0; |
1689 |
while (cmds[i].name != NULL) { |
while (cmds[i].name != NULL) { |
1711 |
|
|
1712 |
printf(" %s\n", cmds[i].description); |
printf(" %s\n", cmds[i].description); |
1713 |
i++; |
i++; |
1714 |
|
|
1715 |
|
curlines ++; |
1716 |
|
if (curlines >= nlines - 1) { |
1717 |
|
char ch; |
1718 |
|
printf("-- more --"); fflush(stdout); |
1719 |
|
ch = debugger_readchar(); |
1720 |
|
printf("\n"); |
1721 |
|
if (ch == 'q' || ch == 'Q') |
1722 |
|
return; |
1723 |
|
curlines = 0; |
1724 |
|
} |
1725 |
} |
} |
1726 |
|
|
1727 |
if (only_one) { |
if (only_one) { |
1730 |
return; |
return; |
1731 |
} |
} |
1732 |
|
|
1733 |
printf("Generic assignments: x = expr\n"); |
/* TODO: generalize/refactor */ |
1734 |
printf("where x must be a register, and expr can be a register, a " |
curlines += 8; |
1735 |
"numeric value, or\na symbol name (+ an optional numeric offset)." |
if (curlines > nlines - 1) { |
1736 |
" In case there are multiple\nmatches (ie a symbol that has the " |
char ch; |
1737 |
"same name as a register), you may add a\nprefix character as a " |
printf("-- more --"); fflush(stdout); |
1738 |
"hint: '%%' for registers, '@' for symbols, and\n'$' for numeric" |
ch = debugger_readchar(); |
1739 |
" values. Use 0x for hexadecimal values.\n"); |
printf("\n"); |
1740 |
|
if (ch == 'q' || ch == 'Q') |
1741 |
|
return; |
1742 |
|
curlines = 0; |
1743 |
|
} |
1744 |
|
|
1745 |
|
printf("\nIn generic assignments, x must be a register, and expr can be" |
1746 |
|
" a register, a\nnumeric value, or a symbol name (+ an optional " |
1747 |
|
"numeric offset). In case there\nare multiple matches (i.e. a " |
1748 |
|
"symbol that has the same name as a register), you\nmay add a " |
1749 |
|
"prefix character as a hint: '%%' for registers, '@' for symbols," |
1750 |
|
" and\n'$' for numeric values. Use 0x for hexadecimal values.\n"); |
1751 |
} |
} |
1752 |
|
|
1753 |
|
|
1764 |
char *left, *right; |
char *left, *right; |
1765 |
int res_left, res_right; |
int res_left, res_right; |
1766 |
uint64_t tmp; |
uint64_t tmp; |
1767 |
|
uint64_t old_pc = m->cpus[0]->pc; /* TODO: multiple cpus? */ |
1768 |
|
|
1769 |
left = malloc(MAX_CMD_BUFLEN); |
left = malloc(MAX_CMD_BUFLEN); |
1770 |
if (left == NULL) { |
if (left == NULL) { |
1815 |
} |
} |
1816 |
} |
} |
1817 |
|
|
1818 |
|
/* |
1819 |
|
* If the PC has changed, then release any breakpoint we were |
1820 |
|
* currently stopped at. |
1821 |
|
* |
1822 |
|
* TODO: multiple cpus? |
1823 |
|
*/ |
1824 |
|
if (old_pc != m->cpus[0]->pc) |
1825 |
|
single_step_breakpoint = 0; |
1826 |
|
|
1827 |
free(left); |
free(left); |
1828 |
} |
} |
1829 |
|
|
1848 |
cursor_pos = 0; |
cursor_pos = 0; |
1849 |
|
|
1850 |
while (ch != '\n') { |
while (ch != '\n') { |
1851 |
/* |
ch = debugger_readchar(); |
|
* TODO: This uses up 100% CPU, maybe that isn't too good. |
|
|
* The usleep() call might make it a tiny bit nicer on other |
|
|
* running processes, but it is still very ugly. |
|
|
*/ |
|
|
while ((ch = console_readchar(MAIN_CONSOLE)) < 0) { |
|
|
x11_check_event(debugger_emuls, debugger_n_emuls); |
|
|
usleep(2); |
|
|
} |
|
1852 |
|
|
1853 |
if ((ch == '\b' || ch == 127) && cursor_pos > 0) { |
if ((ch == '\b' || ch == 127) && cursor_pos > 0) { |
1854 |
/* Backspace. */ |
/* Backspace. */ |
2096 |
int i, n, i_match, matchlen, cmd_len; |
int i, n, i_match, matchlen, cmd_len; |
2097 |
char *cmd; |
char *cmd; |
2098 |
|
|
2099 |
if (n_steps_left_before_interaction > 0) { |
if (debugger_n_steps_left_before_interaction > 0) { |
2100 |
n_steps_left_before_interaction --; |
debugger_n_steps_left_before_interaction --; |
2101 |
return; |
return; |
2102 |
} |
} |
2103 |
|
|
2104 |
|
/* |
2105 |
|
* Clear all dyntrans translations, because otherwise things would |
2106 |
|
* become to complex to keep in sync. |
2107 |
|
*/ |
2108 |
|
for (i=0; i<debugger_machine->ncpus; i++) |
2109 |
|
if (debugger_machine->cpus[i]->translation_cache != NULL) |
2110 |
|
cpu_create_or_reset_tc(debugger_machine->cpus[i]); |
2111 |
|
|
2112 |
exit_debugger = 0; |
exit_debugger = 0; |
2113 |
|
|
2114 |
while (!exit_debugger) { |
while (!exit_debugger) { |
2177 |
/* Check for a command name match: */ |
/* Check for a command name match: */ |
2178 |
n = i = i_match = 0; |
n = i = i_match = 0; |
2179 |
while (cmds[i].name != NULL) { |
while (cmds[i].name != NULL) { |
2180 |
if (strncasecmp(cmds[i].name, cmd, matchlen) == 0) { |
if (strncasecmp(cmds[i].name, cmd, matchlen) == 0 |
2181 |
|
&& cmds[i].f != NULL) { |
2182 |
cmds[i].tmp_flag = 1; |
cmds[i].tmp_flag = 1; |
2183 |
i_match = i; |
i_match = i; |
2184 |
n++; |
n++; |
2244 |
*/ |
*/ |
2245 |
void debugger_reset(void) |
void debugger_reset(void) |
2246 |
{ |
{ |
2247 |
n_steps_left_before_interaction = 0; |
debugger_n_steps_left_before_interaction = 0; |
2248 |
} |
} |
2249 |
|
|
2250 |
|
|