Thursday, 6 December 2018

Python scripts for GDB

Gdb is a very powerful tool, pairing it with python (version>7.0) allows to automate GDB session.

Traditional GDB scripts

Earlier to Python support in GDB, one could write simple GDB scripts (just listing gdb commands):

$ cat simple_gdb_script
b func1
command 1
print <some-var-in-func1>
end

b func2
command 3
print <some-var-in-func2>
end

// load gdb sesson
(gdb) source simple_gdb_script


and so forth. This option is useful but doesn't give us the ability to process collected data. Python on the other hand is best suited for this job.

Python GDB scripts

Following is a simple python-GDB script:

$ cat python_gdb_script.py
import os
import sys

LOG_FILE='/tmp/gdb.log'

# attach GDB to list of files
this_file = [
              'file1.c',
              'file2.c',
            ]

this_fn = [
              'fn1',
              'fn2',
          ]

def setup():
    print('Running GDB from: %s\n'%(gdb.PYTHONDIR))
    gdb.execute("set pagination off")
    gdb.execute("set print pretty")
    # if connecting to remote target
    # gdb.execute('target remote 172.20.69.21:9999') # cherry
    gdb.execute('set logging file %s'%(LOG_FILE))
    gdb.execute('set logging on')
    print('\nReading gdb env..\n')
    gdb.execute('show script-extension')
    gdb.execute('show sysroot')
    gdb.execute('show solib-search-path')
    print('\nSetup complete !!\n')

# what to do when a breakpoint is hit
def stop_handler(event):
    print('EVENT: %s' % (event))
    gdb.execute("info local")
    gdb.execute("info threads")
    gdb.execute("info args")
    gdb.execute("bt")
    if event.breakpoint.location == "func3":
        gdb.write("Special bp hit\n")
        gdb.execute("p func3_var")
        gdb.execute("p *func3_ptr")
        # don't stop, continue
        gdb.execute("c")

# set bp on all the functions specified in all the files specified in 'this_file'
def set_bp_from_files():
    for f in this_files:
    try:
        gdb.execute("rbreak %s:."%(f))
        print('rbreak %s:.'%(f))
    except:
        print('Error inserting breakpoint %s'%(fn))
    print('\nDone setting breakpoints from list of files\n')

# set breakpoint on all the functions specified in 'this_fn'
def set_bp_from_funs():
    for fn in this_fn:
        if fn:
        try:
            gdb.Breakpoint(fn)
            print('break ' + fn)
        except:
            print('Error inserting breakpoint %s'%(fn))
        print('\nDone setting breakpoints from list of funs\n')


def register_stop_handler():
    gdb.events.stop.connect(stop_handler)
    #unregister
    #gdb.events.stop.disconnect(stop_handler)
    print('\nDone setting stop-handler\n')

def main():
    setup()
    set_bp_from_funs()
    set_bp_from_files()
    register_stop_handler()
    #gdb.execute("c")

main()

// load gdb
(gdb) source python_gdb_script.py


What the code is doing:
1. setup() sets up GDB environment - printty-print, pagination off, logging on
2. set_bp_from_funs() and set_bp_from_files() loop over the lists and sets breakpoint
3. register_stop_handler() - called when GDB hits a bp, in the cb(), perform any action like getting backtrace, printing a variable in that function etc.


When the script is done executing, you can get the GDB console logs in $LOG_FILE.
And then use this data for further analysis.

Complete list of GDB-python APIs:
https://sourceware.org/gdb/onlinedocs/gdb/Python-API.html#Python-API


Function call graphs


I wrote a tool to generate function call graph using this methodology. You can find the source code at: 
https://github.com/tarun27sh/Python_gdb_networkx_graphs


I used GDB/python to get data from running process. Then using matplotlib/networkx, generated PNG/SVG call graphs. SVGs are better since they can scale and can be opened in web-brwoser and allows ctr-F search for functions in call-graph.

Call-graph for Qemu (high resolution):





Harry

Author & Editor

A technology enthusiast and addictive blogger who likes to hacking tricks and wish to be the best White Hacket Hacker of the World.

0 comments:

Post a Comment

Note: only a member of this blog may post a comment.