Running GDB - endplay/omniplay GitHub Wiki

Table of Contents

Building and Setup

There is no special build or setup instructions. When you setup omniplay, gdb support should come along with it.

Attaching GDB to a Replay

Attaching Manually

First, the replay needs to be started so that it will wait for gdb to be attached.

Run resume with the -g flag:

    ./resume -g <logdb_folder>

This will cause the replay to wait for gdb to attach before running.

Alternatively, to pause the replay at a specific syscall instead of at the beginning, run:

    ./resume -g --attach_offset=<pid>,<syscall index> <logdb_folder>

Where pid is the recorded pid that executed the system call and syscall index is the index of it in the klog.

Gdb can be attached to the replay just like any other process. Run:

    gdb <binary> <pid>

Now gdb should be attached and running. You can set breakpoints, continue the process, and do everything in gdb like normal.

Attaching Programatically

The python wrapper library can be used to run a replay with gdb.

    env = omniplay.OmniplayEnvironment()
    
    group_id = 12345
    env.run_gdb_interactive(group_id)

This causes an interactive gdb shell to open, already attached to the replay.

To run a script instead, run:

    env = omniplay.OmniplayEnvironment()
    
    group_id = 12345
    script = "io.py"
    env.run_gdb_script(group_id, script)

This will run the io tool script.

GDB Scripts

GDB scripts are python files that contain commands that gdb will automatically execute.

Basics

In order to run gdb with a script, pass the script in with the -x flag.

    gdb <binary> <pid> -x <script>

An example script would look like:

    gdb.execute("break main")
    gdb.execute("continue")
    argc = gdb.parse_and_eval("argc")
    print "argc is:", argc

gdb.execute: Acts as if you literally typed it into gdb

gdb.parse_and_eval: Gets the value of variables in the process, including special ones like '$pc' or '$eax'

Full documentation of the gdb python extensions is here: Python-API

Once a script is done running, it will drop back into using its interactive command-line.

Building a Tool

Passing in a script to gdb this way is bad for making a tool. It requires manually calling resume and manually getting the pid each time. Also, gdb will be very verbose and will ask for confirmation for certain actions. As well it is impossible to pass arguments to the script. To solve these, use the omniplay python library to run your script.

Example of calling a gdb script:

    env = omniplay.OmniplayEnvironment()
    
    group_id = 12345
    script = "myScript.py"
    args = {
        "optionA" : 1,
        "optionB" : 'a'
    }
    env.run_gdb_script(group_id, script, script_args=args)

Example of myScript.py:

    utils = omniplay.gdbscripts.ScriptUtilities()
    optA = utils.get_arg("optionA")
    optB = utils.get_arg("optionB")
    
    gdb.execute("break main")
    gdb.execute("continue")
    ...

When run_gdb_script is used, gdb output is suppressed (except for errors). Gdb will automatically quit when the script ends or an error occurs.

A dictionary of script arguments can be passed in and then retrieved inside the script using the ScriptUtilities class.

Compatibility

Multithreaded programs will not work with gdb. They will make gdb output something like "waiting for new child: No child processes" and then deadlock. GDB thread information (such as the info thread command) will most likely not work well either.

In programs that call fork(), gdb will completely ignore the child process and let it run freely. DO NOT change the follow-fork-mode or detach-on-fork options to fix this. They may cause the replay process to deadlock with gdb, though this will depend on the replay.

Unfortunately at the moment, processes that use vfork() will not work.

If you want to debug a subprocess made through fork-exec, just attach gdb to its specific replay group.

⚠️ **GitHub.com Fallback** ⚠️