diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py index b1e52de754..20f4d64778 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py @@ -888,7 +888,11 @@ def activate(path=None): if nthrd is None: path = PROCESS_PATTERN.format(procnum=nproc) else: - path = THREAD_PATTERN.format(procnum=nproc, tnum=nthrd) + frame = util.selected_frame() + if frame is None: + path = THREAD_PATTERN.format(procnum=nproc, tnum=nthrd) + else: + path = FRAME_PATTERN.format(procnum=nproc, tnum=nthrd, level=frame) trace.proxy_object_path(path).activate() diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py index 4251c99050..fd0eee45d3 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py @@ -140,8 +140,12 @@ def find_thread_by_regs_obj(object): return find_thread_by_pattern(REGS_PATTERN0, object, "a RegisterValueContainer") +@util.dbg.eng_thread def find_frame_by_level(level): - return dbg().backtrace_list()[level] + for f in util.dbg._base.backtrace_list(): + if f.FrameNumber == level: + return f + #return dbg().backtrace_list()[level] def find_frame_by_pattern(pattern, object, err_msg): @@ -269,13 +273,16 @@ def refresh_threads(node: sch.Schema('ThreadContainer')): def refresh_stack(node: sch.Schema('Stack')): """Refresh the backtrace for the thread.""" tnum = find_thread_by_stack_obj(node) + util.reset_frames() with commands.open_tracked_tx('Refresh Stack'): commands.ghidra_trace_put_frames() + with commands.open_tracked_tx('Refresh Registers'): + commands.ghidra_trace_putreg() @REGISTRY.method(action='refresh', display='Refresh Registers') def refresh_registers(node: sch.Schema('RegisterValueContainer')): - """Refresh the register values for the frame.""" + """Refresh the register values for the selected frame""" tnum = find_thread_by_regs_obj(node) with commands.open_tracked_tx('Refresh Registers'): commands.ghidra_trace_putreg() @@ -314,7 +321,12 @@ def activate_thread(thread: sch.Schema('Thread')): @REGISTRY.method(action='activate') def activate_frame(frame: sch.Schema('StackFrame')): """Select the frame.""" - find_frame_by_obj(frame) + f = find_frame_by_obj(frame) + util.select_frame(f.FrameNumber) + with commands.open_tracked_tx('Refresh Stack'): + commands.ghidra_trace_put_frames() + with commands.open_tracked_tx('Refresh Registers'): + commands.ghidra_trace_putreg() @REGISTRY.method(action='delete') diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/util.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/util.py index 9c5f0f593d..714af3b158 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/util.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/util.py @@ -1,17 +1,17 @@ ## ### -# IP: GHIDRA -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# IP: GHIDRA +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. ## from collections import namedtuple from concurrent.futures import Future @@ -530,7 +530,12 @@ def select_thread(id: int): @dbg.eng_thread def select_frame(id: int): - return dbg.cmd('.frame 0x{:x}'.format(id)) + return dbg.cmd('.frame /c {}'.format(id)) + + +@dbg.eng_thread +def reset_frames(): + return dbg.cmd('.cxr') @dbg.eng_thread diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/commands.py b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/commands.py index 019f1038ab..531073c90e 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/commands.py +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/commands.py @@ -1427,6 +1427,8 @@ def put_frames(): f = f.older() level += 1 fobj.insert() + robj = STATE.trace.create_object(fpath+".Registers") + robj.insert() STATE.trace.proxy_object_path(STACK_PATTERN.format( infnum=inf.num, tnum=t.num)).retain_values(keys) diff --git a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py index a71055cdbb..bebc60f387 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py +++ b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py @@ -1,17 +1,17 @@ ## ### -# IP: GHIDRA -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# IP: GHIDRA +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. ## from contextlib import contextmanager import functools @@ -26,7 +26,7 @@ import time try: import psutil except ImportError: - print(f"Unable to import 'psutil' - check that it has been installed") + print("Unable to import 'psutil' - check that it has been installed") from ghidratrace import sch from ghidratrace.client import Client, Address, AddressRange, TraceObject @@ -1867,6 +1867,8 @@ def put_frames(): fobj.set_value('Function', str(f.GetFunctionName())) fobj.set_value('_display', util.get_description(f)) fobj.insert() + robj = STATE.trace.create_object(fpath+".Registers") + robj.insert() STATE.trace.proxy_object_path(STACK_PATTERN.format( procnum=proc.GetProcessID(), tnum=t.GetThreadID())).retain_values(keys)