26. Console command line¶
The console interpreter provides an interactive command line with powerful features, including command completion, history, and editing.
Your command-line history is also saved between sessions in
~/.db68k/db68k.history.
26.1. Command structure¶
Commands consist of one or more space-separated words. If a word is a unique match, it does not need to be fully spelled out.
An argument specific to the command (e.g., a string, file path, or boolean value) may follow the command.
Command completion¶
Command completion is available via the TAB key. Pressing TAB
directly at the prompt lists all words that can start a command:
(db68k) <TAB>
b enable n s
break exec-file next set
c file nexti show
cd frame ni si
clear ignore p source
complete info platform step
condition interpreter-exec plug-in stepi
continue interrupt print thread
delete kill pwd tty
directory lua quit
disable maintenance r
disassemble module run
(db68k)
Pressing TAB completes the command to the left of the cursor as
far as possible. If the word can be partially completed, the first TAB
fills in as much as possible:
(db68k) int<TAB>
Results in:
(db68k) inter
Pressing TAB a second time results in:
(db68k) inter<TAB>
interpreter-exec interrupt
(db68k) inter
26.2. A simple debugging session¶
To get a feeling for how to run a very simple debugging session here is how it can look.
$ db68k program.elf
Calypsi debugger for 68000
(db68k) b main
breakpoint 1
(db68k) info breakpoints
Num Type Disp Enb Lua/plug-in Address What
1 breakpoint keep y no 0x80f1 main
(db68k)
Note
A command requires enough characters to be unique. For info breakpoints,
i b suffices, as the interpreter considers all words for multi-word
commands. The completer operates left of the cursor: i<TAB> shows all
commands starting with ‘i’. To complete to info, type inf<TAB>
followed by b<TAB>. However, i b<TAB> expands directly to
i breakpoints because no other command matches this two-word prefix.
To start debugging, use the run command (abbreviated to r), which
begins execution from the start. The program will stop almost
immediately upon hitting the breakpoint at the beginning of the
main() function.
(db68k) r
running
12 int const cglob_int = 12;
13
14 size_t fossasas;
15
-> 16 int main () {
17 basic_expr(glob_int + 21, 2, 3);
18 int xx = fact(4);
19 int b = vla1(4);
20 int c = struct1(2);
0x80f1 in main() at main.c:16
(db68k)
The breakpoint is hit at address 0x80f1 in main.c:16.
Source lines are shown as context, with the current line indicated.
You can now perform a couple of single steps:
(db68k) s
13
14 size_t fossasas;
15
16 int main () {
-> 17 basic_expr(glob_int + 21, 2, 3);
18 int xx = fact(4);
19 int b = vla1(4);
20 int c = struct1(2);
21 int d = struct11(2);
0x80f8 in main() at main.c:17
(db68k)
10 int bar (long* p) {
11 return *p + 2;
12 }
13
-> 14 long basic_expr (long a, long a2, int a3) {
15 char cglob_int = 0; // block a variable in global scope
16 if (a) {
17 int b = 10;
18 a = foo(b + cglob_int);
0x8000 in basic_expr() at basic_expr.c:14
(db68k)
The step command (abbreviated as s) steps one source line.
Subsequent steps can be performed by simply pressing RETURN,
which repeats the most recent command.
Each step advances us one line, updating the source context shown.
The step command steps into functions, as demonstrated by entering
basic_expr().
You can inspect variables with info locals.
(db68k) info locals
(int) a3 = 3
(long) a2 = 2
(long) a = 21
(db68k)
To trace your current position, use the backtrace (or bt) command.
(db68k) backtrace
#0 0x8000 in basic_expr() at basic_expr.c:14
#1 0x8137 in main() at main.c:17
(db68k)
To stop at a specific line further down the source code, use:
(db68k) b basic_expr.c:18
breakpoint 2
(db68k) c
running
program hit breakpoint 2
14 long basic_expr (long a, long a2, int a3) {
15 char cglob_int = 0; // block a variable in global scope
16 if (a) {
17 int b = 10;
-> 18 a = foo(b + cglob_int);
19 a += bar(&a2); // take address of a2, forcing it to stack.
20 }
21 if (a > 2) {
22 // Make the variable in global scope visible
0x8030 in basic_expr() at basic_expr.c:18
(db68k)
The continue command (or c) resumes execution (unlike run,
which starts from the beginning).
Lets take a look at the local variables again.
(db68k) info locals
(int) b = 10
(char) cglob_int = 0
(int) a3 = 3
(long) a2 = 2
(long) a - value not available, reason: "a" has no valid value here
(db68k)
The local context now includes two additional variables: b and
cglob_int. At this point, a has no value because its last use
was on line 16, and it will receive a new value on the current line.
Thus, the debugger knows about a but it currently holds no examinable
value.
Step over two function calls and inspect the value of a using the
print command, which can be entered as p:
(db68k) n
15 char cglob_int = 0; // block a variable in global scope
16 if (a) {
17 int b = 10;
18 a = foo(b + cglob_int);
-> 19 a += bar(&a2); // take address of a2, forcing it to stack.
20 }
21 if (a > 2) {
22 // Make the variable in global scope visible
23 extern int const cglob_int;
0x8050 in basic_expr() at basic_expr.c:19
(db68k)
17 int b = 10;
18 a = foo(b + cglob_int);
19 a += bar(&a2); // take address of a2, forcing it to stack.
20 }
-> 21 if (a > 2) {
22 // Make the variable in global scope visible
23 extern int const cglob_int;
24 a = foo(cglob_int);
25 }
0x8082 in basic_expr() at basic_expr.c:21
(db68k) p a
(long) $8 = 8
(db68k)
The variable a now holds a value from the function calls.
The local char cglob_int shadows a global variable of the same name.
Stepping to line 24 makes the global cglob_int visible:
(db68k) n
20 }
21 if (a > 2) {
22 // Make the variable in global scope visible
23 extern int const cglob_int;
-> 24 a = foo(cglob_int);
25 }
26 return a + a3; // a3 alive and on the stack
27 }
28
0x8098 in basic_expr() at basic_expr.c:24
(db68k) p cglob_int
(int const) $9 = 12
(db68k)
The global variable is now visible again, with a different value and type.
If you no longer need the first breakpoint, you can disable it using
the disable command, rather than deleting it:
(db68k) disable 1
(db68k) info breakpoints
Num Type Disp Enb Lua/plug-in Address What
1 breakpoint keep n no 0x80f1 main
breakpoint already hit 1 time
2 breakpoint keep y no 0x8030 basic_expr.c:18
breakpoint already hit 1 time
(db68k)
The first breakpoint still exists but is not enabled (n in the
Enb column). The debugger also tracks breakpoint statistics.