/[gxemul]/upstream/0.4.4/src/debugger/debugger.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 /upstream/0.4.4/src/debugger/debugger.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 35 - (hide annotations)
Mon Oct 8 16:21:26 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 19650 byte(s)
0.4.4
1 dpavlin 24 /*
2 dpavlin 34 * Copyright (C) 2004-2007 Anders Gavare. All rights reserved.
3 dpavlin 24 *
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 34 * $Id: debugger.c,v 1.21 2006/12/30 13:30:56 debug Exp $
29 dpavlin 24 *
30     * Single-step debugger.
31     *
32     *
33     * TODO:
34     *
35     * This entire module is very much non-reentrant. :-/
36     *
37     * Add more functionality that already exists elsewhere in the emulator.
38     *
39     * Call stack display (back-trace)?
40     *
41     * Nicer looking output of register dumps, floating point registers,
42     * etc. Warn about weird/invalid register contents.
43     *
44     * Ctrl-C doesn't enter the debugger on some OSes (HP-UX?)...
45     *
46     * Many other TODOs.
47     */
48    
49     #include <ctype.h>
50     #include <signal.h>
51     #include <stdio.h>
52     #include <stdlib.h>
53     #include <string.h>
54     #include <unistd.h>
55    
56     #include "console.h"
57     #include "cpu.h"
58     #include "device.h"
59     #include "debugger.h"
60     #include "debugger_gdb.h"
61     #include "diskimage.h"
62     #include "emul.h"
63     #include "machine.h"
64     #include "memory.h"
65     #include "misc.h"
66     #include "net.h"
67     #include "settings.h"
68 dpavlin 32 #include "timer.h"
69 dpavlin 24 #include "x11.h"
70    
71    
72     extern int extra_argc;
73     extern char **extra_argv;
74     extern struct settings *global_settings;
75     extern int quiet_mode;
76    
77    
78     /*
79     * Global debugger variables:
80     *
81     * TODO: Some of these should be moved to some other place!
82     */
83    
84 dpavlin 26 volatile int single_step = NOT_SINGLE_STEPPING;
85 dpavlin 24 volatile int exit_debugger;
86     int force_debugger_at_exit = 0;
87    
88     volatile int single_step_breakpoint = 0;
89     int debugger_n_steps_left_before_interaction = 0;
90    
91     int old_instruction_trace = 0;
92     int old_quiet_mode = 0;
93     int old_show_trace_tree = 0;
94    
95    
96     /*
97     * Private (global) debugger variables:
98     */
99    
100     static volatile int ctrl_c;
101    
102     static int debugger_n_emuls;
103     static struct emul **debugger_emuls;
104 dpavlin 32
105     /* Currently focused CPU, machine, and emulation: */
106     int debugger_cur_cpu;
107     int debugger_cur_machine;
108     int debugger_cur_emul;
109     static struct machine *debugger_machine;
110 dpavlin 24 static struct emul *debugger_emul;
111    
112     #define MAX_CMD_BUFLEN 72
113     #define N_PREVIOUS_CMDS 150
114     static char *last_cmd[N_PREVIOUS_CMDS];
115     static int last_cmd_index;
116    
117     static char repeat_cmd[MAX_CMD_BUFLEN];
118    
119     #define MAGIC_UNTOUCHED 0x98ca76c2ffcc0011ULL
120    
121     static uint64_t last_dump_addr = MAGIC_UNTOUCHED;
122     static uint64_t last_unasm_addr = MAGIC_UNTOUCHED;
123    
124    
125     /*
126     * debugger_readchar():
127     */
128     char debugger_readchar(void)
129     {
130     int ch, i, j;
131    
132     while ((ch = console_readchar(MAIN_CONSOLE)) < 0 && !exit_debugger) {
133     /* Check for X11 events: */
134     x11_check_event(debugger_emuls, debugger_n_emuls);
135    
136     /* Check for incoming GDB packets: */
137     for (i=0; i<debugger_n_emuls; i++) {
138     struct emul *e = debugger_emuls[i];
139     if (e == NULL)
140     continue;
141    
142     for (j=0; j<e->n_machines; j++) {
143     if (e->machines[j]->gdb.port > 0)
144     debugger_gdb_check_incoming(
145     e->machines[j]);
146     }
147     }
148    
149     /* TODO: The X11 and GDB checks above should probably
150     be factored out... */
151    
152     /* Give up some CPU time: */
153 dpavlin 32 usleep(10000);
154 dpavlin 24 }
155     return ch;
156     }
157    
158    
159     /*
160     * debugger_activate():
161     *
162     * This is a signal handler for CTRL-C. It shouldn't be called directly,
163     * but setup code in emul.c sets the CTRL-C signal handler to use this
164     * function.
165     */
166     void debugger_activate(int x)
167     {
168     ctrl_c = 1;
169    
170 dpavlin 26 if (single_step != NOT_SINGLE_STEPPING) {
171 dpavlin 24 /* Already in the debugger. Do nothing. */
172     int i;
173     for (i=0; i<MAX_CMD_BUFLEN; i++)
174     console_makeavail(MAIN_CONSOLE, '\b');
175     console_makeavail(MAIN_CONSOLE, ' ');
176     console_makeavail(MAIN_CONSOLE, '\n');
177     printf("^C");
178     fflush(stdout);
179     } else {
180     /* Enter the single step debugger. */
181 dpavlin 26 single_step = ENTER_SINGLE_STEPPING;
182 dpavlin 24
183     /* Discard any chars in the input queue: */
184     while (console_charavail(MAIN_CONSOLE))
185     console_readchar(MAIN_CONSOLE);
186     }
187    
188     /* Clear the repeat-command buffer: */
189     repeat_cmd[0] = '\0';
190    
191     /* Reactivate the signal handler: */
192     signal(SIGINT, debugger_activate);
193     }
194    
195    
196     /*
197     * show_breakpoint():
198     */
199     static void show_breakpoint(struct machine *m, int i)
200     {
201     printf("%3i: 0x", i);
202     if (m->cpus[0]->is_32bit)
203     printf("%08"PRIx32, (uint32_t) m->breakpoint_addr[i]);
204     else
205     printf("%016"PRIx64, (uint64_t) m->breakpoint_addr[i]);
206     if (m->breakpoint_string[i] != NULL)
207     printf(" (%s)", m->breakpoint_string[i]);
208     if (m->breakpoint_flags[i])
209     printf(": flags=0x%x", m->breakpoint_flags[i]);
210     printf("\n");
211     }
212    
213    
214     /****************************************************************************/
215    
216    
217     #include "debugger_cmds.c"
218    
219    
220     /****************************************************************************/
221    
222    
223     /*
224     * debugger_assignment():
225     *
226     * cmd contains something like "pc=0x80001000", or "r31=memcpy+0x40".
227     */
228     void debugger_assignment(struct machine *m, char *cmd)
229     {
230     char *left, *right;
231     int res_left, res_right;
232     uint64_t tmp;
233     uint64_t old_pc = m->cpus[0]->pc; /* TODO: multiple cpus? */
234    
235     left = malloc(MAX_CMD_BUFLEN);
236     if (left == NULL) {
237     fprintf(stderr, "out of memory in debugger_assignment()\n");
238     exit(1);
239     }
240     strlcpy(left, cmd, MAX_CMD_BUFLEN);
241     right = strchr(left, '=');
242     if (right == NULL) {
243     fprintf(stderr, "internal error in the debugger\n");
244     exit(1);
245     }
246     *right = '\0';
247    
248     /* Remove trailing spaces in left: */
249     while (strlen(left) >= 1 && left[strlen(left)-1] == ' ')
250     left[strlen(left)-1] = '\0';
251    
252     /* Remove leading spaces in right: */
253     right++;
254     while (*right == ' ' && *right != '\0')
255     right++;
256    
257     /* printf("left = '%s'\nright = '%s'\n", left, right); */
258    
259 dpavlin 32 res_right = debugger_parse_expression(m, right, 0, &tmp);
260 dpavlin 24 switch (res_right) {
261 dpavlin 32 case PARSE_NOMATCH:
262 dpavlin 24 printf("No match for the right-hand side of the assignment.\n");
263     break;
264 dpavlin 32 case PARSE_MULTIPLE:
265 dpavlin 24 printf("Multiple matches for the right-hand side of the "
266     "assignment.\n");
267     break;
268     default:
269 dpavlin 32 res_left = debugger_parse_expression(m, left, 1, &tmp);
270 dpavlin 24 switch (res_left) {
271 dpavlin 32 case PARSE_NOMATCH:
272 dpavlin 24 printf("No match for the left-hand side of the "
273     "assignment.\n");
274     break;
275 dpavlin 32 case PARSE_MULTIPLE:
276 dpavlin 24 printf("Multiple matches for the left-hand side "
277     "of the assignment.\n");
278     break;
279     default:
280     debugger_cmd_print(m, left);
281     }
282     }
283    
284     /*
285     * If the PC has changed, then release any breakpoint we were
286     * currently stopped at.
287     *
288     * TODO: multiple cpus?
289     */
290     if (old_pc != m->cpus[0]->pc)
291     single_step_breakpoint = 0;
292    
293     free(left);
294     }
295    
296    
297     /*
298     * debugger_execute_cmd():
299     */
300     void debugger_execute_cmd(char *cmd, int cmd_len)
301     {
302     int i, n, i_match, matchlen;
303    
304     /*
305     * Is there a '=' on the command line? Then try to do an
306     * assignment. (Only if there is just one word, followed
307     * by the '=' sign. This makes it possible to use commands
308     * such as "device add name addr=xyz".)
309     */
310     if (strchr(cmd, '=') != NULL) {
311     /* Count the nr of words: */
312     int nw = 0, inword = 0;
313     char *p = cmd;
314     while (*p) {
315     if (*p == '=')
316     break;
317     if (*p != ' ') {
318     if (!inword)
319     nw ++;
320     inword = 1;
321     } else
322     inword = 0;
323     p++;
324     }
325    
326     if (nw == 1) {
327     debugger_assignment(debugger_machine, cmd);
328     return;
329     }
330     }
331    
332     i = 0;
333     while (cmds[i].name != NULL)
334     cmds[i++].tmp_flag = 0;
335    
336     /* How many chars in cmd to match against: */
337     matchlen = 0;
338     while (isalpha((int)cmd[matchlen]))
339     matchlen ++;
340    
341     /* Check for a command name match: */
342     n = i = i_match = 0;
343     while (cmds[i].name != NULL) {
344     if (strncasecmp(cmds[i].name, cmd, matchlen) == 0
345     && cmds[i].f != NULL) {
346     cmds[i].tmp_flag = 1;
347     i_match = i;
348     n++;
349     }
350     i++;
351     }
352    
353     /* No match? */
354     if (n == 0) {
355     printf("Unknown command '%s'. Type 'help' for help.\n", cmd);
356     return;
357     }
358    
359     /* More than one match? */
360     if (n > 1) {
361     printf("Ambiguous command '%s': ", cmd);
362     i = 0;
363     while (cmds[i].name != NULL) {
364     if (cmds[i].tmp_flag)
365     printf(" %s", cmds[i].name);
366     i++;
367     }
368     printf("\n");
369     return;
370     }
371    
372     /* Exactly one match: */
373     if (cmds[i_match].f != NULL) {
374     char *p = cmd + matchlen;
375     /* Remove leading whitespace from the args... */
376     while (*p != '\0' && *p == ' ')
377     p++;
378    
379     /* ... and run the command: */
380     cmds[i_match].f(debugger_machine, p);
381     } else
382     printf("FATAL ERROR: internal error in debugger.c:"
383     " no handler for this command?\n");
384     }
385    
386    
387     /*
388     * debugger_readline():
389     *
390     * Read a line from the terminal.
391     */
392     static char *debugger_readline(void)
393     {
394     int ch, i, j, n, i_match, reallen, cmd_len, cursor_pos;
395     int read_from_index = last_cmd_index;
396     char *cmd = last_cmd[last_cmd_index];
397    
398     cmd_len = 0; cmd[0] = '\0';
399     printf("GXemul> ");
400     fflush(stdout);
401    
402     ch = '\0';
403     cmd_len = 0;
404     cursor_pos = 0;
405    
406     while (ch != '\n' && !exit_debugger) {
407     ch = debugger_readchar();
408    
409     if ((ch == '\b' || ch == 127) && cursor_pos > 0) {
410     /* Backspace. */
411     cursor_pos --;
412     cmd_len --;
413     memmove(cmd + cursor_pos, cmd + cursor_pos + 1,
414     cmd_len);
415     cmd[cmd_len] = '\0';
416     printf("\b");
417     for (i=cursor_pos; i<cmd_len; i++)
418     printf("%c", cmd[i]);
419     printf(" \b");
420     for (i=cursor_pos; i<cmd_len; i++)
421     printf("\b");
422     } else if (ch == 4 && cmd_len > 0 && cursor_pos < cmd_len) {
423     /* CTRL-D: Delete. */
424     cmd_len --;
425     memmove(cmd + cursor_pos, cmd + cursor_pos + 1,
426     cmd_len);
427     cmd[cmd_len] = '\0';
428     for (i=cursor_pos; i<cmd_len; i++)
429     printf("%c", cmd[i]);
430     printf(" \b");
431     for (i=cursor_pos; i<cmd_len; i++)
432     printf("\b");
433     } else if (ch == 1) {
434     /* CTRL-A: Start of line. */
435     while (cursor_pos > 0) {
436     cursor_pos --;
437     printf("\b");
438     }
439     } else if (ch == 2) {
440     /* CTRL-B: Backwards one character. */
441     if (cursor_pos > 0) {
442     printf("\b");
443     cursor_pos --;
444     }
445     } else if (ch == 5) {
446     /* CTRL-E: End of line. */
447     while (cursor_pos < cmd_len) {
448     printf("%c", cmd[cursor_pos]);
449     cursor_pos ++;
450     }
451     } else if (ch == 6) {
452     /* CTRL-F: Forward one character. */
453     if (cursor_pos < cmd_len) {
454     printf("%c",
455     cmd[cursor_pos]);
456     cursor_pos ++;
457     }
458     } else if (ch == 11) {
459     /* CTRL-K: Kill to end of line. */
460     for (i=0; i<MAX_CMD_BUFLEN; i++)
461     console_makeavail(MAIN_CONSOLE, 4); /* :-) */
462     } else if (ch == 14 || ch == 16) {
463     /* CTRL-P: Previous line in the command history,
464     CTRL-N: next line */
465     do {
466     if (ch == 14 &&
467     read_from_index == last_cmd_index)
468     break;
469     if (ch == 16)
470     i = read_from_index - 1;
471     else
472     i = read_from_index + 1;
473    
474     if (i < 0)
475     i = N_PREVIOUS_CMDS - 1;
476     if (i >= N_PREVIOUS_CMDS)
477     i = 0;
478    
479     /* Special case: pressing 'down'
480     to reach last_cmd_index: */
481     if (i == last_cmd_index) {
482     read_from_index = i;
483     for (i=cursor_pos; i<cmd_len;
484     i++)
485     printf(" ");
486     for (i=cmd_len-1; i>=0; i--)
487     printf("\b \b");
488     cmd[0] = '\0';
489     cmd_len = cursor_pos = 0;
490     } else if (last_cmd[i][0] != '\0') {
491     /* Copy from old line: */
492     read_from_index = i;
493     for (i=cursor_pos; i<cmd_len;
494     i++)
495     printf(" ");
496     for (i=cmd_len-1; i>=0; i--)
497     printf("\b \b");
498     strlcpy(cmd,
499     last_cmd[read_from_index],
500     MAX_CMD_BUFLEN);
501     cmd_len = strlen(cmd);
502     printf("%s", cmd);
503     cursor_pos = cmd_len;
504     }
505     } while (0);
506     } else if (ch >= ' ' && cmd_len < MAX_CMD_BUFLEN-1) {
507     /* Visible character: */
508     memmove(cmd + cursor_pos + 1, cmd + cursor_pos,
509     cmd_len - cursor_pos);
510     cmd[cursor_pos] = ch;
511     cmd_len ++;
512     cursor_pos ++;
513     cmd[cmd_len] = '\0';
514     printf("%c", ch);
515     for (i=cursor_pos; i<cmd_len; i++)
516     printf("%c", cmd[i]);
517     for (i=cursor_pos; i<cmd_len; i++)
518     printf("\b");
519     } else if (ch == '\r' || ch == '\n') {
520     ch = '\n';
521     printf("\n");
522     } else if (ch == '\t') {
523     /* Super-simple tab-completion: */
524     i = 0;
525     while (cmds[i].name != NULL)
526     cmds[i++].tmp_flag = 0;
527    
528     /* Check for a (partial) command match: */
529     n = i = i_match = 0;
530     while (cmds[i].name != NULL) {
531     if (strncasecmp(cmds[i].name, cmd,
532     cmd_len) == 0) {
533     cmds[i].tmp_flag = 1;
534     i_match = i;
535     n++;
536     }
537     i++;
538     }
539    
540     switch (n) {
541     case 0: /* Beep. */
542     printf("\a");
543     break;
544     case 1: /* Add the rest of the command: */
545     reallen = strlen(cmds[i_match].name);
546     for (i=cmd_len; i<reallen; i++)
547     console_makeavail(MAIN_CONSOLE,
548     cmds[i_match].name[i]);
549     /* ... and a space, if the command takes
550     any arguments: */
551     if (cmds[i_match].args != NULL &&
552     cmds[i_match].args[0] != '\0')
553     console_makeavail(MAIN_CONSOLE, ' ');
554     break;
555     default:
556     /* Show all possible commands: */
557     printf("\a\n"); /* Beep. :-) */
558     i = 0; /* i = cmds index */
559     j = 0; /* j = # of cmds printed */
560     while (cmds[i].name != NULL) {
561     if (cmds[i].tmp_flag) {
562     size_t q;
563     if (j == 0)
564     printf(" ");
565     printf("%s",
566     cmds[i].name);
567     j++;
568     if (j != 6)
569     for (q=0; q<13-strlen(
570     cmds[i].name); q++)
571     printf(" ");
572     if (j == 6) {
573     printf("\n");
574     j = 0;
575     }
576     }
577     i++;
578     }
579     if (j != 0)
580     printf("\n");
581     printf("GXemul> ");
582     for (i=0; i<cmd_len; i++)
583     printf("%c", cmd[i]);
584     }
585     } else if (ch == 27) {
586     /* Escape codes: (cursor keys etc) */
587     while ((ch = console_readchar(MAIN_CONSOLE)) < 0)
588 dpavlin 32 usleep(10000);
589 dpavlin 24 if (ch == '[' || ch == 'O') {
590     while ((ch = console_readchar(MAIN_CONSOLE))
591     < 0)
592 dpavlin 32 usleep(10000);
593 dpavlin 24 switch (ch) {
594     case '2': /* 2~ = ins */
595     case '5': /* 5~ = pgup */
596     case '6': /* 6~ = pgdn */
597     /* TODO: Ugly hack, but might work. */
598     while ((ch = console_readchar(
599     MAIN_CONSOLE)) < 0)
600 dpavlin 32 usleep(10000);
601 dpavlin 24 /* Do nothing for these keys. */
602     break;
603     case '3': /* 3~ = delete */
604     /* TODO: Ugly hack, but might work. */
605     while ((ch = console_readchar(
606     MAIN_CONSOLE)) < 0)
607 dpavlin 32 usleep(10000);
608 dpavlin 24 console_makeavail(MAIN_CONSOLE, '\b');
609     break;
610     case 'A': /* Up. */
611     /* Up cursor ==> CTRL-P */
612     console_makeavail(MAIN_CONSOLE, 16);
613     break;
614     case 'B': /* Down. */
615     /* Down cursor ==> CTRL-N */
616     console_makeavail(MAIN_CONSOLE, 14);
617     break;
618     case 'C':
619     /* Right cursor ==> CTRL-F */
620     console_makeavail(MAIN_CONSOLE, 6);
621     break;
622     case 'D': /* Left */
623     /* Left cursor ==> CTRL-B */
624     console_makeavail(MAIN_CONSOLE, 2);
625     break;
626     case 'F':
627     /* End ==> CTRL-E */
628     console_makeavail(MAIN_CONSOLE, 5);
629     break;
630     case 'H':
631     /* Home ==> CTRL-A */
632     console_makeavail(MAIN_CONSOLE, 1);
633     break;
634     }
635     }
636     }
637    
638     fflush(stdout);
639     }
640    
641     if (exit_debugger)
642     cmd[0] = '\0';
643    
644     return cmd;
645     }
646    
647    
648     /*
649     * debugger():
650     *
651     * This is a loop, which reads a command from the terminal, and executes it.
652     */
653     void debugger(void)
654     {
655     int i, cmd_len;
656     char *cmd;
657    
658     if (debugger_n_steps_left_before_interaction > 0) {
659     debugger_n_steps_left_before_interaction --;
660     return;
661     }
662    
663     /*
664     * Clear all dyntrans translations, because otherwise things would
665     * become to complex to keep in sync.
666     */
667     /* TODO: In all machines */
668     for (i=0; i<debugger_machine->ncpus; i++)
669 dpavlin 26 if (debugger_machine->cpus[i]->translation_cache != NULL) {
670 dpavlin 24 cpu_create_or_reset_tc(debugger_machine->cpus[i]);
671 dpavlin 26 debugger_machine->cpus[i]->
672     invalidate_translation_caches(
673     debugger_machine->cpus[i], 0, INVALIDATE_ALL);
674     }
675 dpavlin 24
676     /*
677     * Ugly GDB hack: After single stepping, we need to send back
678     * status to GDB:
679     */
680     if (exit_debugger == -1) {
681     int i, j;
682     for (i=0; i<debugger_n_emuls; i++) {
683     struct emul *e = debugger_emuls[i];
684     if (e == NULL)
685     continue;
686    
687     for (j=0; j<e->n_machines; j++) {
688     if (e->machines[j]->gdb.port > 0)
689     debugger_gdb_after_singlestep(
690     e->machines[j]);
691     }
692     }
693     }
694    
695    
696 dpavlin 32 /* Stop timers while interacting with the user: */
697     timer_stop();
698    
699 dpavlin 24 exit_debugger = 0;
700    
701     while (!exit_debugger) {
702     /* Read a line from the terminal: */
703     cmd = debugger_readline();
704    
705     /* Special hack for the "step" _GDB_ command: */
706     if (exit_debugger == -1)
707     return;
708    
709     cmd_len = strlen(cmd);
710    
711     /* Remove spaces: */
712     while (cmd_len > 0 && cmd[0]==' ')
713     memmove(cmd, cmd+1, cmd_len --);
714     while (cmd_len > 0 && cmd[cmd_len-1] == ' ')
715     cmd[(cmd_len--)-1] = '\0';
716    
717     /* No command? Then try reading another line. */
718     if (cmd_len == 0) {
719     /* Special case for repeated commands: */
720     if (repeat_cmd[0] != '\0')
721     strlcpy(cmd, repeat_cmd, MAX_CMD_BUFLEN);
722     else
723     continue;
724     } else {
725     last_cmd_index ++;
726     if (last_cmd_index >= N_PREVIOUS_CMDS)
727     last_cmd_index = 0;
728    
729     repeat_cmd[0] = '\0';
730     }
731    
732     debugger_execute_cmd(cmd, cmd_len);
733    
734     /* Special hack for the "step" command: */
735     if (exit_debugger == -1)
736     return;
737     }
738    
739 dpavlin 32 /* Start up timers again: */
740     timer_start();
741    
742     /* ... and reset starttime, so that nr of instructions per second
743     can be calculated correctly: */
744 dpavlin 24 gettimeofday(&debugger_machine->starttime, NULL);
745 dpavlin 28 debugger_machine->ninstrs_since_gettimeofday = 0;
746 dpavlin 24
747 dpavlin 26 single_step = NOT_SINGLE_STEPPING;
748 dpavlin 24 debugger_machine->instruction_trace = old_instruction_trace;
749     debugger_machine->show_trace_tree = old_show_trace_tree;
750     quiet_mode = old_quiet_mode;
751     }
752    
753    
754     /*
755     * debugger_reset():
756     *
757     * This function should be called before calling debugger(), when it is
758     * absolutely necessary that debugger() is interactive. Otherwise, it might
759     * return without doing anything, such as when single-stepping multiple
760     * instructions at a time.
761     */
762     void debugger_reset(void)
763     {
764     debugger_n_steps_left_before_interaction = 0;
765     }
766    
767    
768     /*
769     * debugger_init():
770     *
771     * Must be called before any other debugger function is used.
772     */
773     void debugger_init(struct emul **emuls, int n_emuls)
774     {
775     int i, j;
776    
777     debugger_n_emuls = n_emuls;
778     debugger_emuls = emuls;
779    
780     if (n_emuls < 1) {
781     fprintf(stderr, "\nERROR: No emuls (?)\n");
782     exit(1);
783     }
784    
785     debugger_emul = emuls[0];
786     if (emuls[0]->n_machines < 1) {
787     fprintf(stderr, "\nERROR: No machines in emuls[0], "
788     "cannot handle this situation yet.\n\n");
789     exit(1);
790     }
791    
792     for (i=0; i<n_emuls; i++)
793     for (j=0; j<emuls[i]->n_machines; j++)
794     debugger_gdb_init(emuls[i]->machines[j]);
795    
796     debugger_machine = emuls[0]->machines[0];
797    
798 dpavlin 32 debugger_cur_cpu = 0;
799     debugger_cur_machine = 0;
800     debugger_cur_emul = 0;
801    
802 dpavlin 24 for (i=0; i<N_PREVIOUS_CMDS; i++) {
803     last_cmd[i] = malloc(MAX_CMD_BUFLEN);
804     if (last_cmd[i] == NULL) {
805     fprintf(stderr, "debugger_init(): out of memory\n");
806     exit(1);
807     }
808     last_cmd[i][0] = '\0';
809     }
810    
811     last_cmd_index = 0;
812     repeat_cmd[0] = '\0';
813     }
814    

  ViewVC Help
Powered by ViewVC 1.1.26