I'm trying to create a little unit test with gdb, for a embedded mcu that is controlled by OpenOCD (that gives me control over my target via a gdb server).
So I would like to automate this with some scripting of gdb.
I would like to write some kind of script for gdb that more or less does this:
- Add a couple of breakpoints
- Start the program
- When we stop, where did it stop (get the frame info)
- Quit.
Any ideas?
A example on how to do this in python gdb scripting would be nice.
Thanks Johan
Note:
Let's say that we have this basic structure, that more or less goes into test_failed() or test_success() depending on what the function start_test() returns.
void test_failed() {
while(1);
}
void test_success() {
while(1);
}
int main(void) {
int status = start_test();
if( status > 0 ) {
test_failed();
}
test_success();
while(1);
}
To do this manually in gdb is very strait forward,
(gdb) break test_success
Breakpoint 1 at 0x20: file src/main.c, line 9.
(gdb) break test_failed
Breakpoint 2 at 0x18: file src/main.c, line 5.
(gdb) cont
Continuing.
Breakpoint 1, test_success () at src/main.c:9
9 while(1);
(gdb) frame
#0 test_success () at src/main.c:9
9 while(1);
(gdb)
So the next step I tried was to add those gdb commands into a gdb startup script that more or less just looked like this.
break test_success
break test_failed
target remote localhost:3333
cont
frame
and start it with
arm-none-eabi-gdb --batch --command=commands.gdb main.elf
And this kind of works, but it is not very nice. How do I do this with the "new and cool" python scripts, that gdb seem to support.
Just wanted to note something that I find confusing whenever I come back to this topic (Note, I'm currently on Ubuntu 14.04, GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1):
First, there are references about it being "possible to invoke
gdb
as an interpreter":... meaning, one would write a script text file with the shebang line
#!/usr/bin/gbd -P
or#!/usr/bin/gbd --python
, then write Python code in it, then make it executablechmod +x pygdbscript
, then run./pygdbscript
; ... but as in this post:..., I get
gdb: unrecognized option '--python'
if I try anything like that. Apparently this option is/was a feature in some "archer" branch ofgdb
?!So, in order to run a Python script in
gdb
, there are actually two ways:.py
; saytest.py
here:Note, in this case, you just write plain Python code; and you do not need to
import gdb
in order to access thegdb
object. This you can run with either of:... which seem to be equivalent, as the result for any of these is the same printout, before
gdb
is instructed to exit by the script:NOTE that for this case, also names like
test.gdb.py
will be interpreted as pure Python scripts, since then end in.py
..py
extension; saytest.pygdb
here:In this case,
gdb
interprets the script as being agdb
script, i.e. withgdb
commands - and that means, that whatever Python code you may want to write in here, must be wrapped in "python
" as a starting line and "end
" at end of the Python code. Again, it would be called with any of these equivalent calls:... and then the output is the same as in the previous case (since it is the same Python script running):
And in response to OP: if the C code in OP is in
/tmp/myprog.c
- with an addedint start_test() { return rand() % 50; }
on top, otherwise it won't compile - , and is compiled with withgcc -g myprog.c -o myprog.exe
into/tmp/myprog.exe
; then you can use amyprog.gdb.py
script like this:... then run this script with:
Note that at the end of this script, the
(gdb)
interactive prompt remains, and you can use it normally here; if you don't need the interactive prompt, you can dogdb.execute("quit");
as in the above scripts to forcegdb
to exit instead at end of script execution.Also, for an example of subclassing breakpoint class in gdb Python, see How to print the current line of source at breakpoint in GDB and nothing else?
A reduced example that I'm currently using:
You can execute this script from gdb's prompt like this:
Or from the command-line:
See the complete GDB Python API docs for further info.
OK, I found the answer while asking the question... and it and it was a really simple thing.
You should not use both the "--command" and the "--eval" at the same time if you expect them to be executed in a specific order!
A more predicable way is to put everything in the commands.gdb file and ignore --eval.
So it becomes something like this:
Where commands.gdb looks like this:
But it would probably be so much nicer to do this with something like python instead.
FYI recent gdb versions are scriptable in Python. You can call python code from the gdb command line. This opens a whole new world, check the relevant documentation. From the command line run:
If you do not like the text-based info browser, here is one (among many?) alternative, graphical browser:
Here is a sample gdb-python script. It attaches gdb to the first "your_program" found running.