Merge remote-tracking branch 'origin/GP-6374_d-millar_handlers_for_dbgeng'

This commit is contained in:
Ryan Kurtz
2026-02-03 05:54:27 -05:00
4 changed files with 93 additions and 0 deletions

View File

@@ -1068,6 +1068,10 @@ def put_single_breakpoint(bp, ibobj, nproc: int, ikeys: List[str]) -> None:
tid = "%04x" % tid
except exception.E_NOINTERFACE_Error:
tid = "****"
try:
handler = util.BPT_HANDLERS[bp.GetId()]
except Exception:
handler = ""
if bp.GetType()[0] == DbgEng.DEBUG_BREAKPOINT_DATA:
width, prot = bp.GetDataParameters()
@@ -1103,6 +1107,8 @@ def put_single_breakpoint(bp, ibobj, nproc: int, ikeys: List[str]) -> None:
brkobj.set_value('Flags', bp.GetFlags())
if tid != None:
brkobj.set_value('Match TID', tid)
if handler != None:
brkobj.set_value('Handler', handler)
brkobj.set_value('Command', bp.GetCommand())
brkobj.insert()
@@ -1531,6 +1537,11 @@ def put_single_exception(obj: TraceObject, objpath: str,
exc_cmd2 = util.GetExceptionFilterSecondCommand(
offset + index, p.SecondCommandSize)
exc_code = hex(p.ExceptionCode)
try:
util.EXC_CODES[index] = exc_code
handler = util.EXC_HANDLERS[exc_code]
except Exception:
handler = ""
obj.set_value('Code', exc_code)
trace = STATE.require_trace()
contobj = trace.create_object(objpath+".Cont")
@@ -1545,6 +1556,8 @@ def put_single_exception(obj: TraceObject, objpath: str,
obj.set_value('Cmd', exc_cmd)
if exc_cmd2 is not None:
obj.set_value('Cmd2', exc_cmd2)
if handler is not None:
obj.set_value('Handler', handler)
obj.set_value('_display', "{} {} [{}]".format(index, exc_name, exc_code))
obj.insert()

View File

@@ -382,6 +382,7 @@ def on_cont(*args) -> None:
def on_stop(*args) -> None:
# print("ON STOP")
proc = util.selected_process()
if proc not in PROC_STATE:
return
@@ -505,12 +506,28 @@ def on_breakpoint_deleted(bpid) -> None:
@log_errors
def on_breakpoint_hit(*args) -> None:
# print("ON_BREAKPOINT_HIT: args={}".format(args))
id = util.get_breakpoint_id(args[0])
if id in util.BPT_HANDLERS:
try:
handler = util.BPT_HANDLERS[id]
func = globals()[handler]
func(*args)
except Exception as e:
print(f"Error in breakpoint handler: {e}")
return DbgEng.DEBUG_STATUS_NO_CHANGE
@log_errors
def on_exception(*args) -> None:
# print("ON_EXCEPTION: args={}".format(args))
id = str(hex(args[0][0].ExceptionCode))
if id in util.EXC_HANDLERS:
try:
handler = util.EXC_HANDLERS[id]
func = globals()[handler]
func(*args)
except Exception as e:
print(f"Error in exception handler: {e}")
return DbgEng.DEBUG_STATUS_NO_CHANGE

View File

@@ -321,6 +321,14 @@ class ExceptionContainer(TraceObject):
pass
class Event(TraceObject):
pass
class Exception(TraceObject):
pass
class ContinueOption(TraceObject):
pass
@@ -865,5 +873,49 @@ def refresh_trace_events_custom(node: State,
commands.ghidra_trace_put_trace_events_custom(prefix, cmd)
@REGISTRY.method(action='add_handler', display='Add Handler')
def add_handler_breakpoint(node: BreakpointSpec, handler: str) -> None:
"""
Add python handler
"""
mat = PROC_BREAKBPT_PATTERN.fullmatch(node.path)
if mat is None:
raise TypeError(f"{node} is not {err_msg}")
bptnum = int(mat['breaknum'])
with commands.open_tracked_tx('Add Exception Handler'):
util.BPT_HANDLERS[bptnum] = handler
commands.ghidra_trace_put_breakpoints()
@REGISTRY.method(action='add_handler', display='Add Handler')
def add_handler_exception(node: Exception, handler: str) -> None:
"""
Add python handler
"""
mat = PROC_EXCEPTION_PATTERN.fullmatch(node.path)
if mat is None:
raise TypeError(f"{node} is not {err_msg}")
excnum = int(mat['excnum'])
with commands.open_tracked_tx('Add Exception Handler'):
exc_code = util.EXC_CODES[excnum]
util.EXC_HANDLERS[exc_code] = handler
commands.ghidra_trace_put_exceptions()
# TODO?
# @REGISTRY.method(action='add_handler', display='Add Handler')
# def add_handler_event(node: Event, handler: str) -> None:
# """
# Add python handler
# """
# mat = PROC_EVENT_PATTERN.fullmatch(node.path)
# if mat is None:
# raise TypeError(f"{node} is not {err_msg}")
# evtnum = int(mat['eventnum'])
# with commands.open_tracked_tx('Add Event Handler'):
# util.EVT_HANDLERS[evtnum] = handler
# commands.ghidra_trace_put_events()
def dbg():
return util.dbg._base

View File

@@ -44,12 +44,17 @@ from pybag.dbgeng import core as DbgEng # type: ignore
from pybag.dbgeng import exception # type: ignore
from pybag.dbgeng import util as DbgUtil # type: ignore
from pybag.dbgeng.callbacks import DbgEngCallbacks # type: ignore
from pybag.dbgeng.idebugbreakpoint import DebugBreakpoint # type: ignore
from pybag.dbgeng.idebugclient import DebugClient # type: ignore
DESCRIPTION_PATTERN = '[{major:X}:{minor:X}] {type}'
DbgVersion = namedtuple('DbgVersion', ['full', 'name', 'dotted', 'arch'])
BPT_HANDLERS: Dict[int, str] = {}
EXC_CODES: Dict[int, str] = {}
EXC_HANDLERS: Dict[str, str] = {}
EVT_HANDLERS: Dict[int, str] = {}
class StdInputCallbacks(CoClass):
# This is the UUID listed for IDebugInputCallbacks in DbgEng.h
@@ -501,6 +506,12 @@ def get_breakpoints() -> Iterable[Tuple[str, str, str, str, str]]:
return zip(offset_set, expr_set, prot_set, width_set, stat_set)
@dbg.eng_thread
def get_breakpoint_id(bp: DbgEng.IDebugBreakpoint) -> int:
bpt = DebugBreakpoint(bp)
return bpt.GetId()
@dbg.eng_thread
def selected_process() -> int:
try: