Scripting ZeroBugs with Python

The ZeroBugs debugger allows you to automate debugging tasks using the Python programming language. If you have a build of ZeroBugs that includes the zpython.so plug-in (the Python Gate) then you may specify a script with the command line option --py-run=path to your script.

The python plugin is unloaded if no script is specified in the command line.

As of September 2nd all builds on the download page include the Python Gate.

"Standard" Debugger Callbacks

The debugger engine broadcasts notifications to the plug-ins. The Python Gate plug-in receives these like any other plug-in, and exposes them to user-written Python scripts. It looks up the user script for a number of functions with predefined names. If found, these functions are invoked when the events they correspond to occur. See example.

These functions are:

  • on_process(process, thread)
    Called when the debugger attaches to a new process (either by starting it, attaching to an already running process; process in this context also applies to loading a core file and accessing information about the crashed process).
  • on_thread(thread)
    Called when the debugger attaches to a new thread
  • on_process_detach(process)
  • on_thread_detach(thread)
  • on_event(event)
    A debugging event occurred. event.type() gives the exact cause, which may be one of:
    • Update -- a notification for the script to update any internal state
    • Signal
    • Breakpoint
    • SysCallEnter -- only received if debugger.set_option(zero.Debugger.Option.TraceSysCalls) is called. See example
    • SysCallLeave -- ditto
    • SingleStep
    • DoneStepping
    • CallReturned -- debuggee returned from function after thread.step(zero.Step.Return)
    NOTE: on_event is not called for scripted breakpoints (i.e. a breakpoint that has a corresponding callback function in the Python script). When such a breakpoint is hit, control is passed directly to the callback function without going through the on_event notification.
  • on_progress(message, percentage)
Defining any of these functions is optional.

Accessing the Debugger Instance

The debugger instance can be accessed from either the Process and Thread objects like so:


process.debugger()
thread.debugger()
The reason I have not exposed it as a global variable (say, zero.debugger) is that at some point in the future I might have several instances of the debugger engine running in parallel. Thus it makes more sense to think in terms of "the debugger that is attached to this thread", or "the debugger instance that is attached to this process" rather than "the debugger". I simply do not want to introduce a singleton architectural limitation at this point.

Examples

I hope to put some more format documentation together soon, meanwhile please refer to these examples.

  1. Standard Callbacks
  2. Stack Traces
  3. Breakpoints
  4. Breakpoints, Stack Traces, CPU Registers
  5. Stepping Through Code
  6. Monitoring System Calls
  7. Zero, Python and GTK
  8. Expression Evaluation and Function Invocation

You need to get the glade file and glade project in order to run the Gtk example.

The source code for a more sophisticated Gtk project that wants to replace the current GUI with a lightweight Python implementation can be browsed here and downloaded from here.