Merge remote-tracking branch

'origin/GP-4750_d-millar_brk_cmd_w_c--SQUASHED' (Closes #6678)
This commit is contained in:
Ryan Kurtz 2024-07-10 08:52:56 -04:00
commit 75cfd4036e
4 changed files with 54 additions and 12 deletions

View File

@ -595,6 +595,7 @@ def putreg(frame, reg_descs):
cobj.insert()
mapper = STATE.trace.register_mapper
values = []
# NB: This command will fail if the process is running
endian = arch.get_endian()
for desc in reg_descs:
v = frame.read_register(desc.name)
@ -616,7 +617,7 @@ def ghidra_trace_putreg(group='all', *, is_mi, **kwargs):
"""
STATE.require_tx()
frame = gdb.selected_frame()
frame = util.selected_frame()
with STATE.client.batch() as b:
return putreg(frame, util.get_register_descs(frame.architecture(), group))
@ -631,7 +632,7 @@ def ghidra_trace_delreg(group='all', *, is_mi, **kwargs):
STATE.require_tx()
inf = gdb.selected_inferior()
frame = gdb.selected_frame()
frame = util.selected_frame()
space = 'Inferiors[{}].Threads[{}].Stack[{}].Registers'.format(
inf.num, gdb.selected_thread().num, util.get_level(frame)
)
@ -957,9 +958,10 @@ def activate(path=None):
if t is None:
path = INFERIOR_PATTERN.format(infnum=inf.num)
else:
frame = gdb.selected_frame()
path = FRAME_PATTERN.format(
infnum=inf.num, tnum=t.num, level=util.get_level(frame))
frame = util.selected_frame()
if frame is not None:
path = FRAME_PATTERN.format(
infnum=inf.num, tnum=t.num, level=util.get_level(frame))
trace.proxy_object_path(path).activate()
@ -1329,7 +1331,7 @@ def convert_tid(t):
@contextmanager
def restore_frame():
f = gdb.selected_frame()
f = util.selected_frame()
yield
f.select()
@ -1400,8 +1402,12 @@ def put_frames():
t = gdb.selected_thread()
if t is None:
return
# NB: This command will fail if the process is running
bt = gdb.execute('bt', to_string=True).strip().split('\n')
f = newest_frame(gdb.selected_frame())
f = util.selected_frame()
if f is None:
return
f = newest_frame(f)
keys = []
level = 0
while f is not None:

View File

@ -33,13 +33,14 @@ GhidraHookPrefix()
class HookState(object):
__slots__ = ('installed', 'mem_catchpoint', 'batch', 'skip_continue')
__slots__ = ('installed', 'mem_catchpoint', 'batch', 'skip_continue', 'in_break_w_cont')
def __init__(self):
self.installed = False
self.mem_catchpoint = None
self.batch = None
self.skip_continue = False
self.in_break_w_cont = False
def ensure_batch(self):
if self.batch is None:
@ -86,9 +87,12 @@ class InferiorState(object):
thread = gdb.selected_thread()
if thread is not None:
if first or thread not in self.visited:
# NB: This command will fail if the process is running
commands.put_frames()
self.visited.add(thread)
frame = gdb.selected_frame()
frame = util.selected_frame()
if frame is None:
return
hashable_frame = (thread, util.get_level(frame))
if first or hashable_frame not in self.visited:
commands.putreg(
@ -102,6 +106,7 @@ class InferiorState(object):
except MemoryError as e:
print(f"Couldn't record page with SP: {e}")
self.visited.add(hashable_frame)
# NB: These commands (put_modules/put_regions) will fail if the process is running
if first or self.regions or self.threads or self.modules:
# Sections, memory syscalls, or stack allocations
commands.put_modules()
@ -238,7 +243,9 @@ def on_frame_selected():
if trace is None:
return
t = gdb.selected_thread()
f = gdb.selected_frame()
f = util.selected_frame()
if f is None:
return
HOOK_STATE.ensure_batch()
with trace.open_tx("Frame {}.{}.{} selected".format(inf.num, t.num, util.get_level(f))):
INF_STATES[inf.num].record()
@ -299,11 +306,28 @@ def on_cont(event):
state.record_continued()
def check_for_continue(event):
if hasattr(event, 'breakpoints'):
if HOOK_STATE.in_break_w_cont:
return True
for brk in event.breakpoints:
if hasattr(brk, 'commands'):
for cmd in brk.commands:
if cmd == 'c' or cmd.startswith('cont'):
HOOK_STATE.in_break_w_cont = True
return True
HOOK_STATE.in_break_w_cont = False
return False
@log_errors
def on_stop(event):
if hasattr(event, 'breakpoints') and HOOK_STATE.mem_catchpoint in event.breakpoints:
HOOK_STATE.skip_continue = True
return
if check_for_continue(event):
HOOK_STATE.skip_continue = True
return
inf = gdb.selected_inferior()
if inf.num not in INF_STATES:
return

View File

@ -171,7 +171,9 @@ def find_thread_by_stack_obj(object):
def find_frame_by_level(thread, level):
# Because threads don't have any attribute to get at frames
thread.switch()
f = gdb.selected_frame()
f = util.selected_frame()
if f is None:
return None
# Navigate up or down, because I can't just get by level
down = level - util.get_level(f)
@ -340,7 +342,10 @@ def refresh_stack(node: sch.Schema('Stack')):
@REGISTRY.method(action='refresh', display='Refresh Registers')
def refresh_registers(node: sch.Schema('RegisterValueContainer')):
"""Refresh the register values for the frame."""
find_frame_by_regs_obj(node).select()
f = find_frame_by_regs_obj(node)
if f is None:
return
f.select()
# TODO: Groups?
with commands.open_tracked_tx('Refresh Registers'):
gdb.execute('ghidra trace putreg')

View File

@ -429,3 +429,10 @@ def get_register_descs(arch, group='all'):
tokens = line.strip().split()
descs.append(RegisterDesc(tokens[0]))
return descs
def selected_frame():
try:
return gdb.selected_frame()
except Exception as e:
print("No selected frame")
return None