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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 17862 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26