From 91c7233d2da89a6bd4e784031af08c61cb1a5cff Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 21 Aug 2023 13:51:59 -0600 Subject: [PATCH] Select frame when fetching a frame variable in DAP Right now, if a program uses multiple languages, DAP value formatting will always use the language of the innermost frame. However, it is better to use the variable's defining frame instead. This patch does this by selecting the frame first. This also fixes a possibly latent bug in the "stepOut" command -- "finish" is sensitive to the selected frame, but the DAP code may already select other frames when convenient. The DAP stepOut request only works on the newest frame, so be sure to select it before invoking "finish". --- gdb/python/lib/gdb/dap/next.py | 11 ++++++++--- gdb/python/lib/gdb/dap/scopes.py | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/gdb/python/lib/gdb/dap/next.py b/gdb/python/lib/gdb/dap/next.py index 8b112770a0c..5046963cb81 100644 --- a/gdb/python/lib/gdb/dap/next.py +++ b/gdb/python/lib/gdb/dap/next.py @@ -23,9 +23,10 @@ from .state import set_thread # Helper function to set the current thread and the scheduler-locking # mode. Returns True if scheduler-locking was successfully set to -# 'on', False in all other cases, including error. +# 'on', False in all other cases, including error. When SELECT is +# True, also select that thread's newest frame. @in_gdb_thread -def _handle_thread_step(thread_id, single_thread): +def _handle_thread_step(thread_id, single_thread, select=False): # Ensure we're going to step the correct thread. set_thread(thread_id) if single_thread: @@ -41,6 +42,10 @@ def _handle_thread_step(thread_id, single_thread): gdb.execute("set scheduler-locking " + arg, from_tty=True, to_string=True) except gdb.error: result = False + # Other DAP code may select a frame, and the "finish" command uses + # the selected frame. + if select: + gdb.newest_frame().select() return result @@ -70,7 +75,7 @@ def step_in( @request("stepOut") def step_out(*, threadId: int, singleThread: bool = False): - send_gdb(lambda: _handle_thread_step(threadId, singleThread)) + send_gdb(lambda: _handle_thread_step(threadId, singleThread, True)) send_gdb(ExecutionInvoker("finish", StopKinds.STEP)) diff --git a/gdb/python/lib/gdb/dap/scopes.py b/gdb/python/lib/gdb/dap/scopes.py index 1687094c4ce..4874d001216 100644 --- a/gdb/python/lib/gdb/dap/scopes.py +++ b/gdb/python/lib/gdb/dap/scopes.py @@ -49,6 +49,10 @@ class _ScopeReference(BaseReference): @in_gdb_thread def fetch_one_child(self, idx): + # Make sure to select the frame first. Ideally this would not + # be needed, but this is a way to set the current language + # properly so that language-dependent APIs will work. + self.inf_frame.select() # Here SYM will conform to the SymValueWrapper interface. sym = self.var_list[idx] name = str(sym.symbol()) -- 2.30.2