I've just got the following:
(gdb) target remote :1234
Remote debugging using :1234
main () at main.cpp:5
5 {
(gdb) p add(1, 2)
$1 = 3
As you see, using the gdb debugger I've evaluated expression
add(1,2)
, where function
add
presumably adds two numbers, and got the right result. What's interesting in this?
There are two interesting things:
- It's gdb port to a new target.
- The remote side is not a hardware board -- it's our simulator, which was taught to talk using gdb's remote protocol
However simple the example seems, it involves several steps:
- First of all, gdb must load the symbol tables. Othewise, it won't know that
add
is a function. That did not work out of box, for example gdb assumed that program can't start at address 0.
- After connecting to the target, gdb asks about the value of program counter. This requires support for appropriate protocol command. Also, our simulator took shortcuts and did not even maintain the program counter!
- To call a function, the arguments are pushed to a temporary memory area. This requires
code that knows calling convention for the target, and memory writing support.
- After that, a fake return address is placed to a stack (typically, entry point of the program), and a breakpoint is set to that return address. So this requires working breakpoints in the simulator.
- Then, debugger changes program counter to the address of
add
and resumes program execution.
- After hitting breakpoint, the return value of the function is extracted, which again requires knowing calling convention.
So, it's not just a poor man's calculator, it's also a test for a good deal of debugger functionality. There's also stack frame handling (up/down/where/finish), and printing of complex data types (structures/arrays), but believe me, that works as well.
It looks like my 3-month gdb and simulator hacking comes to an end, and I'll spend more time on more interesting things like improving KDevelop's debugger frontend.
No comments:
Post a Comment