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 executable chmod +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 of gdb
?!
So, in order to run a Python script in gdb
, there are actually two ways:
- Name your script file with extension
.py
; say test.py
here:
def Something():
print("hello from python")
Something()
gdb.execute("quit");
Note, in this case, you just write plain Python code; and you do not need to import gdb
in order to access the gdb
object. This you can run with either of:
gdb -x test.py
gdb -x=test.py
gdb --command test.py
gdb --command=test.py
gdb -command test.py
gdb -command=test.py
... 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:
$ gdb -x=test.py
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
...
For help, type "help".
Type "apropos word" to search for commands related to "word".
hello from python
NOTE that for this case, also names like test.gdb.py
will be interpreted as pure Python scripts, since then end in .py
.
- Name your script anything else - as long as it does not end with
.py
extension; say test.pygdb
here:
python
def Something():
print("hello from python")
Something()
gdb.execute("quit");
end
In this case, gdb
interprets the script as being a gdb
script, i.e. with gdb
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:
gdb -x test.pygdb
gdb -x=test.pygdb
gdb --command test.pygdb
gdb --command=test.pygdb
gdb -command test.pygdb
gdb -command=test.pygdb
... and then the output is the same as in the previous case (since it is the same Python script running):
$ gdb -x test.pygdb
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
...
hello from python
And in response to OP: if the C code in OP is in /tmp/myprog.c
- with an added int start_test() { return rand() % 50; }
on top, otherwise it won't compile - , and is compiled with with gcc -g myprog.c -o myprog.exe
into /tmp/myprog.exe
; then you can use a myprog.gdb.py
script like this:
# need to specify the executable file which we debug (in this case, not from command line)
# here `gdb` command `file` is used - it does not have a Python equivalent (https://sourceware.org/gdb/onlinedocs/gdb/Objfiles-In-Python.html#index-Objfile_002eframe_005ffilters)
# so we must use gdb.execute:
myexefile="/tmp/myprog.exe"
print("""
### myprog.gdb.py is running: """ + myexefile + """ - and adding breakpoints:
""")
gdb.execute("file " + myexefile)
gdb.execute("set pagination off")
ax = gdb.Breakpoint("test_success")
bx = gdb.Breakpoint("test_failed")
gdb.execute("run")
# here the program will break, so we can do:
print("""
### myprog.gdb.py after the break - current stack frame:
""")
current_frame_at_break = gdb.selected_frame()
print(current_frame_at_break) # instead of gdb.execute("frame")
print("""
### myprog.gdb.py - backtrace:
""")
gdb.execute("backtrace 2")
print("""
### myprog.gdb.py - go to frame that called current frame:
""")
parent_frame = current_frame_at_break.older()
print(parent_frame)
status_var = parent_frame.read_var("status")
print("status_var is: ", status_var)
... then run this script with:
$ gdb -x myprog.gdb.py
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
....
For help, type "help".
Type "apropos word" to search for commands related to "word".
### myprog.gdb.py is running: /tmp/myprog.exe - and adding breakpoints:
Breakpoint 1 at 0x400565: file myprog.c, line 8.
Breakpoint 2 at 0x40055f: file myprog.c, line 4.
Breakpoint 2, test_failed () at myprog.c:4
4 while(1);
### myprog.gdb.py after the break - current stack frame:
{stack=0x7fffffffdc70,code=0x40055b,!special}
### myprog.gdb.py - backtrace:
#0 test_failed () at myprog.c:4
#1 0x000000000040058c in main () at myprog.c:15
### myprog.gdb.py - go to frame that called current frame:
{stack=0x7fffffffdc90,code=0x400567,!special}
status_var is: 33
(gdb)
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 do gdb.execute("quit");
as in the above scripts to force gdb
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?