Skip to content

Commit

Permalink
Support FinishBreakpoint for GDB API (#2114)
Browse files Browse the repository at this point in the history
* Support FinishBreakpoint for GDB API

* Evaluate args outside FinishBreakpoint callbacks
  • Loading branch information
j3soon committed Dec 29, 2022
1 parent 826f4f3 commit 838e9ec
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
46 changes: 46 additions & 0 deletions pwnlib/gdb.py
Expand Up @@ -665,6 +665,48 @@ def exposed_stop(self):
# Handle stop() call from the server.
return self.stop()

class FinishBreakpoint:
"""Mirror of ``gdb.FinishBreakpoint`` class.
See https://sourceware.org/gdb/onlinedocs/gdb/Finish-Breakpoints-in-Python.html
for more information.
"""

def __init__(self, conn, *args, **kwargs):
"""Do not create instances of this class directly.
Use ``pwnlib.gdb.Gdb.FinishBreakpoint`` instead.
"""
# Creates a real finish breakpoint and connects it with this mirror
self.conn = conn
self.server_breakpoint = conn.root.set_finish_breakpoint(
self, hasattr(self, 'stop'), hasattr(self, 'out_of_scope'),
*args, **kwargs)

def __getattr__(self, item):
"""Return attributes of the real breakpoint."""
if item in (
'____id_pack__',
'__name__',
'____conn__',
'stop',
'out_of_scope',
):
# Ignore RPyC netref attributes.
# Also, if stop() or out_of_scope() are not defined, hasattr() call
# in our __init__() will bring us here. Don't contact the
# server in this case either.
raise AttributeError()
return getattr(self.server_breakpoint, item)

def exposed_stop(self):
# Handle stop() call from the server.
return self.stop()

def exposed_out_of_scope(self):
# Handle out_of_scope() call from the server.
return self.out_of_scope()

class Gdb:
"""Mirror of ``gdb`` module.
Expand All @@ -682,8 +724,12 @@ def __init__(self, conn):
class _Breakpoint(Breakpoint):
def __init__(self, *args, **kwargs):
super().__init__(conn, *args, **kwargs)
class _FinishBreakpoint(FinishBreakpoint):
def __init__(self, *args, **kwargs):
super().__init__(conn, *args, **kwargs)

self.Breakpoint = _Breakpoint
self.FinishBreakpoint = _FinishBreakpoint
self.stopped = Event()

def stop_handler(event):
Expand Down
11 changes: 11 additions & 0 deletions pwnlib/gdb_api_bridge.py
Expand Up @@ -89,6 +89,17 @@ def stop(self):
return Breakpoint(*args, **kwargs)
return gdb.Breakpoint(*args, **kwargs)

def exposed_set_finish_breakpoint(self, client, has_stop, has_out_of_scope, *args, **kwargs):
"""Create a finish breakpoint and connect it with the client-side mirror."""
class FinishBreakpoint(gdb.FinishBreakpoint):
if has_stop:
def stop(self):
return client.stop()
if has_out_of_scope:
def out_of_scope(self):
client.out_of_scope()
return FinishBreakpoint(*args, **kwargs)

def exposed_quit(self):
"""Terminate GDB."""
gdb.post_event(lambda: gdb.execute('quit'))
Expand Down

0 comments on commit 838e9ec

Please sign in to comment.