init
The Pwndbg REPL that is the interface to all debugging on LLDB.
Pwndbg has an event system that allows it to react to events in the process being debugged, such as when new executable modules get added to the its address space, when the value of memory and registers change, and pretty much all possible changes to its execution state. We'd like to have the event system work the same way under LLDB as it does under GDB.
Fortunately for us, the events types that are native to LLDB map really well to the event types in GDB and Pwndbg. Very, very unfortunately for us, however, that's basically where our luck ends.
LLDB, as of version 18, only provides two ways to capture events: registering directly with the broadcaster, or registering globally. The former is not available to us in the standard LLDB REPL, as we don't get access to the process object until after it's been launched1. Likewise for the latter, as the interactive debugger will register to receive the global process state change events before everyone else, and LLDB doesn't allow for multiple listeners for the same event bits in the same event class2.
This leaves us with handling process management ourselves as the only option we really have to implement event dispatch in Pwndbg. Easy, right? We can just hijack the commands that deal with target and process creation, and leave everything else untouched. Unfortunately for us, again, shadowing builtin commands is simply not allowed3.
So, really, all that's left for us is either implement our own REPL, or get rid of the event system.
LLDB_EXCLUSIVE = [('script', lambda cmd: cmd.startswith('sc') and 'script'.startswith(cmd)), ('expression', lambda cmd: cmd.startswith('e') and 'expression'.startswith(cmd))]
module-attribute
¶
continue_ap = argparse.ArgumentParser(add_help=False)
module-attribute
¶
continue_unsupported = ['ignore-count']
module-attribute
¶
gdb_remote_ap = argparse.ArgumentParser(add_help=False)
module-attribute
¶
process_connect_ap = argparse.ArgumentParser(add_help=False)
module-attribute
¶
process_launch_ap = argparse.ArgumentParser(add_help=False)
module-attribute
¶
process_launch_unsupported = ['disable-aslr', 'script-class', 'environment', 'plugin', 'shell-expand-args', 'arch', 'shell', 'stderr', 'stdin', 'structured-data-key', 'no-stdio', 'stdout', 'tty', 'structured-data-value', 'working-dir']
module-attribute
¶
show_tip = pwndbg.config.add_param('show-tips', True, 'whether to display the tip of the day on startup')
module-attribute
¶
target_create_ap = argparse.ArgumentParser(add_help=False)
module-attribute
¶
target_create_unsupported = ['build', 'core', 'no-dependents', 'remote-file', 'symfile', 'version']
module-attribute
¶
EventRelay
¶
Bases: EventHandler
The event system that is sensible for the REPL process driver to use isn't an exact match with the one used by the rest of Pwndbg. They're close, but there's a bit of work we have to do to properly convey certain events.
continue_process(driver, args, dbg)
¶
Continues the execution of a process.
gdb_remote(driver, relay, args, dbg)
¶
Like process_connect
, but more lenient with the remote URL format.
lex_args(args)
¶
Splits the arguments, respecting quotation marks.
parse(args, parser, unsupported)
¶
Parses a list of string arguments into an object containing the parsed data.
process_connect(driver, relay, args, dbg)
¶
Connects to the given remote process.
process_launch(driver, relay, args, dbg)
¶
Launches a process with the given arguments.
run(startup=None, debug=False)
¶
Runs the Pwndbg REPL under LLDB. Optionally enters the commands given in startup
as part of the startup process.
run_ipython_shell()
¶
show_greeting()
¶
Show the Pwndbg greeting, the same way the GDB version of Pwndbg would. This one is considerably simpler than the GDB version, however, as we control the lifetime of the program, we know exactly when the greeting needs to be shown, so we don't bother with any of the lifetime checks.
target_create(args, dbg)
¶
Creates a new target, registers it with the Pwndbg LLDB implementation, and sets up listeners for it.