https://github.com/eronnen updated https://github.com/llvm/llvm-project/pull/136494
>From 9bb3be7a7fe315cda2e63dd10d90b161e6677263 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Sun, 20 Apr 2025 17:07:09 +0200 Subject: [PATCH 1/5] fallback to assembly when source code is not available --- lldb/tools/lldb-dap/JSONUtils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 33f10c93d2ada..1a44df7740639 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -750,9 +750,10 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, EmplaceSafeString(object, "name", frame_name); auto line_entry = frame.GetLineEntry(); + auto file_spec = line_entry.GetFileSpec(); // A line entry of 0 indicates the line is compiler generated i.e. no source // file is associated with the frame. - if (line_entry.GetFileSpec().IsValid() && + if (file_spec.IsValid() && file_spec.Exists() && (line_entry.GetLine() != 0 || line_entry.GetLine() != LLDB_INVALID_LINE_NUMBER)) { object.try_emplace("source", CreateSource(line_entry)); >From 87426fea3817fb4b54cf2a25560edfed763fe999 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Sun, 20 Apr 2025 21:03:02 +0200 Subject: [PATCH 2/5] fix TestDAP_coreFile.py with source maps --- .../API/tools/lldb-dap/coreFile/TestDAP_coreFile.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py b/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py index 1896acea15a99..ce54133a61f3e 100644 --- a/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py +++ b/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py @@ -19,7 +19,9 @@ def test_core_file(self): core_file = os.path.join(current_dir, "linux-x86_64.core") self.create_debug_adapter() - self.attach(exe_file, coreFile=core_file) + + source_map = [["/home/labath/test", current_dir]] + self.attach(exe_file, coreFile=core_file, sourceMap=source_map) expected_frames = [ { @@ -27,7 +29,7 @@ def test_core_file(self): "id": 524288, "line": 4, "name": "bar", - "source": {"name": "main.c", "path": "/home/labath/test/main.c"}, + "source": {"name": "main.c", "path": os.path.join(current_dir, "main.c")}, "instructionPointerReference": "0x40011C", }, { @@ -35,7 +37,7 @@ def test_core_file(self): "id": 524289, "line": 10, "name": "foo", - "source": {"name": "main.c", "path": "/home/labath/test/main.c"}, + "source": {"name": "main.c", "path": os.path.join(current_dir, "main.c")}, "instructionPointerReference": "0x400142", }, { @@ -43,7 +45,7 @@ def test_core_file(self): "id": 524290, "line": 16, "name": "_start", - "source": {"name": "main.c", "path": "/home/labath/test/main.c"}, + "source": {"name": "main.c", "path": os.path.join(current_dir, "main.c")}, "instructionPointerReference": "0x40015F", }, ] >From e9043dc00010c603553ae067d5ff1e30aba0985e Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Sun, 20 Apr 2025 21:04:46 +0200 Subject: [PATCH 3/5] use stop-disassembly-display setting to determine when to show disassembly --- .../lldb-dap/coreFile/TestDAP_coreFile.py | 10 +- .../stackTraceDisassemblyDisplay/Makefile | 3 + .../TestDAP_stackTraceDisassemblyDisplay.py | 195 ++++++++++++++++++ .../stackTraceDisassemblyDisplay/main.c | 10 + lldb/tools/lldb-dap/DAP.h | 4 + .../lldb-dap/Handler/AttachRequestHandler.cpp | 1 + .../lldb-dap/Handler/LaunchRequestHandler.cpp | 1 + .../tools/lldb-dap/Handler/RequestHandler.cpp | 4 + lldb/tools/lldb-dap/Handler/RequestHandler.h | 3 + .../Handler/StackTraceRequestHandler.cpp | 3 +- lldb/tools/lldb-dap/JSONUtils.cpp | 34 ++- lldb/tools/lldb-dap/JSONUtils.h | 21 +- lldb/tools/lldb-dap/LLDBUtils.cpp | 19 ++ lldb/tools/lldb-dap/LLDBUtils.h | 9 + 14 files changed, 300 insertions(+), 17 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py create mode 100644 lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/main.c diff --git a/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py b/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py index ce54133a61f3e..1896acea15a99 100644 --- a/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py +++ b/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py @@ -19,9 +19,7 @@ def test_core_file(self): core_file = os.path.join(current_dir, "linux-x86_64.core") self.create_debug_adapter() - - source_map = [["/home/labath/test", current_dir]] - self.attach(exe_file, coreFile=core_file, sourceMap=source_map) + self.attach(exe_file, coreFile=core_file) expected_frames = [ { @@ -29,7 +27,7 @@ def test_core_file(self): "id": 524288, "line": 4, "name": "bar", - "source": {"name": "main.c", "path": os.path.join(current_dir, "main.c")}, + "source": {"name": "main.c", "path": "/home/labath/test/main.c"}, "instructionPointerReference": "0x40011C", }, { @@ -37,7 +35,7 @@ def test_core_file(self): "id": 524289, "line": 10, "name": "foo", - "source": {"name": "main.c", "path": os.path.join(current_dir, "main.c")}, + "source": {"name": "main.c", "path": "/home/labath/test/main.c"}, "instructionPointerReference": "0x400142", }, { @@ -45,7 +43,7 @@ def test_core_file(self): "id": 524290, "line": 16, "name": "_start", - "source": {"name": "main.c", "path": os.path.join(current_dir, "main.c")}, + "source": {"name": "main.c", "path": "/home/labath/test/main.c"}, "instructionPointerReference": "0x40015F", }, ] diff --git a/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/Makefile b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/Makefile new file mode 100644 index 0000000000000..118f0aa59ef6f --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c other.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py new file mode 100644 index 0000000000000..e56b87b0d52c3 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py @@ -0,0 +1,195 @@ +""" +Test lldb-dap stack trace when some of the source paths are missing +""" + +from lldbsuite.test.decorators import skipIfWindows +from lldbsuite.test.lldbtest import line_number +import lldbdap_testcase +from contextlib import contextmanager +import os + + +OTHER_C_SOURCE_CODE = """ +int fibonacci(int n) { + if (n < 0) return -1; + if (n == 0) return 0; + if (n == 1) return 1; + int a = 0, b = 1, c; + for (int i = 2; i <= n; ++i) { + c = a + b; + a = b; + b = c; + } + + return b; // Break here +} +""" + + +@contextmanager +def delete_file_on_exit(path): + try: + yield path + finally: + if os.path.exists(path): + os.remove(path) + + +class TestDAP_stackTraceMissingSourcePath(lldbdap_testcase.DAPTestCaseBase): + def build_and_run_until_breakpoint(self, stop_disassembly_display: str): + """ + Build the program and run until the breakpoint is hit, and return the stack frames. + """ + other_source_file = "other.c" + with delete_file_on_exit(other_source_file): + with open(other_source_file, "w") as f: + f.write(OTHER_C_SOURCE_CODE) + + breakpoint_line = line_number(other_source_file, "// Break here") + + program = self.getBuildArtifact("a.out") + init_commands = [ + f"settings set stop-disassembly-display {stop_disassembly_display}" + ] + self.build_and_launch(program, initCommands=init_commands) + + breakpoint_ids = self.set_source_breakpoints( + other_source_file, [breakpoint_line] + ) + self.assertEqual( + len(breakpoint_ids), 1, "expect correct number of breakpoints" + ) + + self.continue_to_breakpoints(breakpoint_ids) + + frames = self.get_stackFrames() + self.assertLessEqual(2, len(frames), "expect at least 2 frames") + + self.assertIn( + "path", + frames[0]["source"], + "Expect source path to always be in frame (other.c)", + ) + self.assertIn( + "path", + frames[1]["source"], + "Expect source path in always be in frame (main.c)", + ) + + return frames + + @skipIfWindows + def test_stopDisassemblyDispay_noSource(self): + """ + Test that with with stop-disassembly-display = no-source - frames without source available give assembly code. + """ + frames = self.build_and_run_until_breakpoint("no-source") + + self.assertNotIn( + "other.c", + frames[0]["source"]["path"], + "Expect original source path to not be in unavailable source frame (other.c)", + ) + self.assertIn( + "sourceReference", + frames[0]["source"], + "Expect sourceReference source path in to be in unavailable source frame (other.c)", + ) + + self.assertIn( + "main.c", + frames[1]["source"]["path"], + "Expect original source path to be in source code frame (main.c)", + ) + self.assertNotIn( + "sourceReference", + frames[1]["source"], + "Expect no sourceReference in source code frame (main.c)", + ) + + @skipIfWindows + def test_stopDisassemblyDispay_noDebuginfo(self): + """ + Test that with with stop-disassembly-display = no-debuginfo - all frames give source code even when source not available. + """ + frames = self.build_and_run_until_breakpoint("no-debuginfo") + + self.assertIn( + "other.c", + frames[0]["source"]["path"], + "Expect original source path to be in unavailable source frame (other.c)", + ) + self.assertNotIn( + "sourceReference", + frames[0]["source"], + "Expect sourceReference source path in to be in unavailable source frame (other.c)", + ) + + self.assertIn( + "main.c", + frames[1]["source"]["path"], + "Expect original source path to be in source code frame (main.c)", + ) + self.assertNotIn( + "sourceReference", + frames[1]["source"], + "Expect no sourceReference in source code frame (main.c)", + ) + + @skipIfWindows + def test_stopDisassemblyDispay_never(self): + """ + Test that with with stop-disassembly-display = never - all frames don't give assembly code. + """ + frames = self.build_and_run_until_breakpoint("never") + + self.assertIn( + "other.c", + frames[0]["source"]["path"], + "Expect original source path to be in unavailable source frame (other.c)", + ) + self.assertNotIn( + "sourceReference", + frames[0]["source"], + "Expect sourceReference source path in to be in unavailable source frame (other.c)", + ) + + self.assertIn( + "main.c", + frames[1]["source"]["path"], + "Expect original source path to be in source code frame (main.c)", + ) + self.assertNotIn( + "sourceReference", + frames[1]["source"], + "Expect no sourceReference in source code frame (main.c)", + ) + + @skipIfWindows + def test_stopDisassemblyDispay_always(self): + """ + Test that with with stop-disassembly-display = always - all frames give source code. + """ + frames = self.build_and_run_until_breakpoint("always") + + self.assertNotIn( + "other.c", + frames[0]["source"]["path"], + "Expect original source path to not be in unavailable source frame (other.c)", + ) + self.assertIn( + "sourceReference", + frames[0]["source"], + "Expect sourceReference source path in to be in unavailable source frame (other.c)", + ) + + self.assertNotIn( + "main.c", + frames[1]["source"]["path"], + "Expect original source path to not be in source code frame (main.c)", + ) + self.assertIn( + "sourceReference", + frames[1]["source"], + "Expect sourceReference in source code frame (main.c)", + ) diff --git a/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/main.c b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/main.c new file mode 100644 index 0000000000000..760f60092d5c8 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/main.c @@ -0,0 +1,10 @@ +#include <stdint.h> +#include <stdio.h> + +int fibonacci(int n); + +int main(int argc, char const *argv[]) { + int result = fibonacci(10); + printf("Fibonacci of 10 is: %d\n", result); + return 0; +} diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h index 727e5c00623e8..b24a8ff0d5ea6 100644 --- a/lldb/tools/lldb-dap/DAP.h +++ b/lldb/tools/lldb-dap/DAP.h @@ -202,6 +202,10 @@ struct DAP { lldb::SBFormat frame_format; lldb::SBFormat thread_format; + + /// The value of stop-disassembly-display setting in LLDB. + std::string stop_disassembly_display; + // This is used to allow request_evaluate to handle empty expressions // (ie the user pressed 'return' and expects the previous expression to // repeat). If the previous expression was a command, this string will be diff --git a/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp index 5e622f3d3dcd4..ce7444304a97d 100644 --- a/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp @@ -108,6 +108,7 @@ void AttachRequestHandler::operator()(const llvm::json::Object &request) const { } SetSourceMapFromArguments(*arguments); + SetStopDisassemblyDisplayFromSettings(); lldb::SBError status; dap.SetTarget(dap.CreateTargetFromArguments(*arguments, status)); diff --git a/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp index 5f14cb074e37e..7b66b9b08ee55 100644 --- a/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp @@ -95,6 +95,7 @@ void LaunchRequestHandler::operator()(const llvm::json::Object &request) const { } SetSourceMapFromArguments(*arguments); + SetStopDisassemblyDisplayFromSettings(); lldb::SBError status; dap.SetTarget(dap.CreateTargetFromArguments(*arguments, status)); diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp index be9273963654a..ad51fc6bbb35c 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp @@ -99,6 +99,10 @@ void BaseRequestHandler::SetSourceMapFromArguments( } } +void BaseRequestHandler::SetStopDisassemblyDisplayFromSettings() const { + dap.stop_disassembly_display = GetStopDisassemblyDisplay(dap.debugger); +} + static llvm::Error RunInTerminal(DAP &dap, const llvm::json::Object &launch_request, const uint64_t timeout_seconds) { diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index e13f7a3749e00..fa672721b761b 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -63,6 +63,9 @@ class BaseRequestHandler { /// argument (or neither), from which we need to set the target.source-map. void SetSourceMapFromArguments(const llvm::json::Object &arguments) const; + /// Sets the stop-disassembly-display setting + void SetStopDisassemblyDisplayFromSettings() const; + /// Prints a welcome message on the editor if the preprocessor variable /// LLDB_DAP_WELCOME_MESSAGE is defined. void PrintWelcomeMessage() const; diff --git a/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp index a58e3325af100..acf16dbcd5a2f 100644 --- a/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp @@ -67,7 +67,8 @@ static bool FillStackFrames(DAP &dap, lldb::SBThread &thread, break; } - stack_frames.emplace_back(CreateStackFrame(frame, dap.frame_format)); + stack_frames.emplace_back(CreateStackFrame(frame, dap.frame_format, + dap.stop_disassembly_display)); } if (dap.configuration.displayExtendedBacktrace && reached_end_of_stack) { diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 1a44df7740639..d3e0f2a050a36 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -658,6 +658,28 @@ llvm::json::Value CreateSource(llvm::StringRef source_path) { return llvm::json::Value(std::move(source)); } +bool ShouldDisplayAssemblySource(const lldb::SBLineEntry &line_entry, + const std::string &stop_disassembly_display) { + if (stop_disassembly_display == "never") + return false; + + if (stop_disassembly_display == "always") + return true; + + // A line entry of 0 indicates the line is compiler generated i.e. no source + // file is associated with the frame. + auto file_spec = line_entry.GetFileSpec(); + if (!file_spec.IsValid() || line_entry.GetLine() == 0 || + line_entry.GetLine() == LLDB_INVALID_LINE_NUMBER) + return true; + + if (stop_disassembly_display == "no-source" && !file_spec.Exists()) { + return true; + } + + return false; +} + // "StackFrame": { // "type": "object", // "description": "A Stackframe contains the source location.", @@ -719,8 +741,9 @@ llvm::json::Value CreateSource(llvm::StringRef source_path) { // }, // "required": [ "id", "name", "line", "column" ] // } -llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, - lldb::SBFormat &format) { +llvm::json::Value +CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, + const std::string &stop_disassembly_display) { llvm::json::Object object; int64_t frame_id = MakeDAPFrameID(frame); object.try_emplace("id", frame_id); @@ -750,12 +773,7 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, EmplaceSafeString(object, "name", frame_name); auto line_entry = frame.GetLineEntry(); - auto file_spec = line_entry.GetFileSpec(); - // A line entry of 0 indicates the line is compiler generated i.e. no source - // file is associated with the frame. - if (file_spec.IsValid() && file_spec.Exists() && - (line_entry.GetLine() != 0 || - line_entry.GetLine() != LLDB_INVALID_LINE_NUMBER)) { + if (!ShouldDisplayAssemblySource(line_entry, stop_disassembly_display)) { object.try_emplace("source", CreateSource(line_entry)); object.try_emplace("line", line_entry.GetLine()); auto column = line_entry.GetColumn(); diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h index b8c53353bf42d..7186f222b04e8 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -345,6 +345,20 @@ llvm::json::Value CreateSource(const lldb::SBLineEntry &line_entry); /// definition outlined by Microsoft. llvm::json::Value CreateSource(llvm::StringRef source_path); +/// Return true if the given line entry should be displayed as assembly. +/// +/// \param[in] line_entry +/// The LLDB line entry to check. +/// +/// \param[in] stop_disassembly_display +/// The value of the "stop-disassembly-display" setting. +/// +/// \return +/// True if the line entry should be displayed as assembly, false +/// otherwise. +bool ShouldDisplayAssemblySource(const lldb::SBLineEntry &line_entry, + const std::string &stop_disassembly_display); + /// Create a "StackFrame" object for a LLDB frame object. /// /// This function will fill in the following keys in the returned @@ -363,11 +377,14 @@ llvm::json::Value CreateSource(llvm::StringRef source_path); /// The LLDB format to use when populating out the "StackFrame" /// object. /// +/// \param[in] stop_disassembly_display +/// The value of the "stop-disassembly-display" setting. +/// /// \return /// A "StackFrame" JSON object with that follows the formal JSON /// definition outlined by Microsoft. -llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, - lldb::SBFormat &format); +llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, + const std::string &stop_disassembly_display); /// Create a "StackFrame" label object for a LLDB thread. /// diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp index a27beff0b030d..7dd7d41d96a6a 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.cpp +++ b/lldb/tools/lldb-dap/LLDBUtils.cpp @@ -163,6 +163,25 @@ GetEnvironmentFromArguments(const llvm::json::Object &arguments) { return envs; } +std::string GetStopDisassemblyDisplay(lldb::SBDebugger &debugger) { + std::string stop_disassembly_display = "no-debuginfo"; // default value + lldb::SBCommandReturnObject result; + debugger.GetCommandInterpreter().HandleCommand( + "settings show stop-disassembly-display", result); + if (result.Succeeded()) { + std::string output = result.GetOutput(); + size_t pos = output.find("stop-disassembly-display"); + if (pos != std::string::npos) { + size_t start = output.find("= ", pos) + 2; + size_t end = output.find("\n", start); + stop_disassembly_display = + output.substr(start, end - start); // trim whitespace + } + } + + return stop_disassembly_display; +} + llvm::Error ToError(const lldb::SBError &error) { if (error.Success()) return llvm::Error::success(); diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h index 2c57847303cb3..1ecb95122da04 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.h +++ b/lldb/tools/lldb-dap/LLDBUtils.h @@ -156,6 +156,15 @@ uint32_t GetLLDBFrameID(uint64_t dap_frame_id); lldb::SBEnvironment GetEnvironmentFromArguments(const llvm::json::Object &arguments); +/// Get the stop-disassembly-display settings +/// +/// \param[in] debugger +/// The debugger that will execute the lldb commands. +/// +/// \return +/// The value of the stop-disassembly-display setting +std::string GetStopDisassemblyDisplay(lldb::SBDebugger &debugger); + /// Take ownership of the stored error. llvm::Error ToError(const lldb::SBError &error); >From b8659b288c5efa5631d46b6b606795b424a2784d Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Mon, 21 Apr 2025 23:12:47 +0200 Subject: [PATCH 4/5] * Use GetSetting instead of Handle command * Implement OptionValueEnumeration::ToJSON --- .../lldb/Interpreter/OptionValueEnumeration.h | 2 ++ .../Interpreter/OptionValueEnumeration.cpp | 12 ++++++++++ lldb/tools/lldb-dap/LLDBUtils.cpp | 22 +++++++------------ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lldb/include/lldb/Interpreter/OptionValueEnumeration.h b/lldb/include/lldb/Interpreter/OptionValueEnumeration.h index 7dc6eea4e69de..924fcc10cbb00 100644 --- a/lldb/include/lldb/Interpreter/OptionValueEnumeration.h +++ b/lldb/include/lldb/Interpreter/OptionValueEnumeration.h @@ -41,6 +41,8 @@ class OptionValueEnumeration void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/lldb/source/Interpreter/OptionValueEnumeration.cpp b/lldb/source/Interpreter/OptionValueEnumeration.cpp index 8088695243545..798a683268d11 100644 --- a/lldb/source/Interpreter/OptionValueEnumeration.cpp +++ b/lldb/source/Interpreter/OptionValueEnumeration.cpp @@ -37,6 +37,18 @@ void OptionValueEnumeration::DumpValue(const ExecutionContext *exe_ctx, } } +llvm::json::Value +OptionValueEnumeration::ToJSON(const ExecutionContext *exe_ctx) { + const size_t count = m_enumerations.GetSize(); + for (size_t i = 0; i < count; ++i) { + if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value) { + return m_enumerations.GetCStringAtIndex(i).GetStringRef(); + } + } + + return m_current_value; +} + Status OptionValueEnumeration::SetValueFromString(llvm::StringRef value, VarSetOperationType op) { Status error; diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp index 7dd7d41d96a6a..3933be4cd8188 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.cpp +++ b/lldb/tools/lldb-dap/LLDBUtils.cpp @@ -164,22 +164,16 @@ GetEnvironmentFromArguments(const llvm::json::Object &arguments) { } std::string GetStopDisassemblyDisplay(lldb::SBDebugger &debugger) { - std::string stop_disassembly_display = "no-debuginfo"; // default value - lldb::SBCommandReturnObject result; - debugger.GetCommandInterpreter().HandleCommand( - "settings show stop-disassembly-display", result); - if (result.Succeeded()) { - std::string output = result.GetOutput(); - size_t pos = output.find("stop-disassembly-display"); - if (pos != std::string::npos) { - size_t start = output.find("= ", pos) + 2; - size_t end = output.find("\n", start); - stop_disassembly_display = - output.substr(start, end - start); // trim whitespace - } + lldb::SBStructuredData result = + debugger.GetSetting("stop-disassembly-display"); + const size_t result_length = result.GetStringValue(nullptr, 0); + if (result_length > 0) { + std::string result_string(result_length, '\0'); + result.GetStringValue(result_string.data(), result_length + 1); + return result_string; } - return stop_disassembly_display; + return "no-debuginfo"; } llvm::Error ToError(const lldb::SBError &error) { >From 2ec7e347c7f26ab44da2a4c5af8ace5fa3a1f2ac Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Thu, 24 Apr 2025 02:22:55 +0200 Subject: [PATCH 5/5] export StopDisassemblyType enum --- lldb/include/lldb/Core/Debugger.h | 10 +------ lldb/include/lldb/lldb-enumerations.h | 8 ++++++ lldb/source/Core/CoreProperties.td | 12 +++++---- lldb/source/Core/Debugger.cpp | 14 +++++----- .../Interpreter/OptionValueEnumeration.cpp | 3 +-- lldb/source/Target/StackFrame.cpp | 11 ++++---- lldb/tools/lldb-dap/DAP.h | 4 --- .../lldb-dap/Handler/AttachRequestHandler.cpp | 1 - .../lldb-dap/Handler/LaunchRequestHandler.cpp | 1 - .../tools/lldb-dap/Handler/RequestHandler.cpp | 4 --- lldb/tools/lldb-dap/Handler/RequestHandler.h | 3 --- .../Handler/StackTraceRequestHandler.cpp | 8 ++++-- lldb/tools/lldb-dap/JSONUtils.cpp | 14 +++++----- lldb/tools/lldb-dap/JSONUtils.h | 7 ++--- lldb/tools/lldb-dap/LLDBUtils.cpp | 27 ++++++++++++++----- lldb/tools/lldb-dap/LLDBUtils.h | 2 +- 16 files changed, 69 insertions(+), 60 deletions(-) diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index c2e7d6f1d64b7..0595125b1813d 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -232,14 +232,6 @@ class Debugger : public std::enable_shared_from_this<Debugger>, void SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton); - // Properties Functions - enum StopDisassemblyType { - eStopDisassemblyTypeNever = 0, - eStopDisassemblyTypeNoDebugInfo, - eStopDisassemblyTypeNoSource, - eStopDisassemblyTypeAlways - }; - Status SetPropertyValue(const ExecutionContext *exe_ctx, VarSetOperationType op, llvm::StringRef property_path, llvm::StringRef value) override; @@ -336,7 +328,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>, uint64_t GetStopSourceLineCount(bool before) const; - StopDisassemblyType GetStopDisassemblyDisplay() const; + lldb::StopDisassemblyType GetStopDisassemblyDisplay() const; uint64_t GetDisassemblyLineCount() const; diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 8e962428260f8..5db0a57e8830a 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -1383,6 +1383,14 @@ enum CommandReturnObjectCallbackResult { eCommandReturnObjectPrintCallbackHandled = 1, }; +// Used to determine when to show disassembly +enum StopDisassemblyType { + eStopDisassemblyTypeNever = 0, + eStopDisassemblyTypeNoDebugInfo, + eStopDisassemblyTypeNoSource, + eStopDisassemblyTypeAlways +}; + } // namespace lldb #endif // LLDB_LLDB_ENUMERATIONS_H diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td index f5d86b663de13..a1a4e994c3b9c 100644 --- a/lldb/source/Core/CoreProperties.td +++ b/lldb/source/Core/CoreProperties.td @@ -91,11 +91,13 @@ let Definition = "debugger" in { Global, DefaultUnsignedValue<4>, Desc<"The number of disassembly lines to show when displaying a stopped context.">; - def StopDisassemblyDisplay: Property<"stop-disassembly-display", "Enum">, - Global, - DefaultEnumValue<"Debugger::eStopDisassemblyTypeNoDebugInfo">, - EnumValues<"OptionEnumValues(g_show_disassembly_enum_values)">, - Desc<"Control when to display disassembly when displaying a stopped context.">; + def StopDisassemblyDisplay + : Property<"stop-disassembly-display", "Enum">, + Global, + DefaultEnumValue<"eStopDisassemblyTypeNoDebugInfo">, + EnumValues<"OptionEnumValues(g_show_disassembly_enum_values)">, + Desc<"Control when to display disassembly when displaying a stopped " + "context.">; def StopDisassemblyMaxSize: Property<"stop-disassembly-max-size", "UInt64">, Global, DefaultUnsignedValue<32000>, diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index cd8726eeba632..1a0723a2f3b3f 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -112,24 +112,24 @@ static llvm::DefaultThreadPool *g_thread_pool = nullptr; static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = { { - Debugger::eStopDisassemblyTypeNever, + lldb::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context.", }, { - Debugger::eStopDisassemblyTypeNoDebugInfo, + lldb::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo", "Show disassembly when there is no debug information.", }, { - Debugger::eStopDisassemblyTypeNoSource, + lldb::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source " "file " "is missing when displaying a stop context.", }, { - Debugger::eStopDisassemblyTypeAlways, + lldb::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context.", }, @@ -611,10 +611,10 @@ uint64_t Debugger::GetStopSourceLineCount(bool before) const { idx, g_debugger_properties[idx].default_uint_value); } -Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const { +lldb::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const { const uint32_t idx = ePropertyStopDisassemblyDisplay; - return GetPropertyAtIndexAs<Debugger::StopDisassemblyType>( - idx, static_cast<Debugger::StopDisassemblyType>( + return GetPropertyAtIndexAs<lldb::StopDisassemblyType>( + idx, static_cast<lldb::StopDisassemblyType>( g_debugger_properties[idx].default_uint_value)); } diff --git a/lldb/source/Interpreter/OptionValueEnumeration.cpp b/lldb/source/Interpreter/OptionValueEnumeration.cpp index 798a683268d11..f6f839bed8963 100644 --- a/lldb/source/Interpreter/OptionValueEnumeration.cpp +++ b/lldb/source/Interpreter/OptionValueEnumeration.cpp @@ -41,9 +41,8 @@ llvm::json::Value OptionValueEnumeration::ToJSON(const ExecutionContext *exe_ctx) { const size_t count = m_enumerations.GetSize(); for (size_t i = 0; i < count; ++i) { - if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value) { + if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value) return m_enumerations.GetCStringAtIndex(i).GetStringRef(); - } } return m_current_value; diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 0306f68169a98..691541f0ec5bb 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -2030,8 +2030,7 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, if (show_source) { ExecutionContext exe_ctx(shared_from_this()); bool have_source = false, have_debuginfo = false; - Debugger::StopDisassemblyType disasm_display = - Debugger::eStopDisassemblyTypeNever; + lldb::StopDisassemblyType disasm_display = lldb::eStopDisassemblyTypeNever; Target *target = exe_ctx.GetTargetPtr(); if (target) { Debugger &debugger = target->GetDebugger(); @@ -2064,20 +2063,20 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, } } switch (disasm_display) { - case Debugger::eStopDisassemblyTypeNever: + case lldb::eStopDisassemblyTypeNever: break; - case Debugger::eStopDisassemblyTypeNoDebugInfo: + case lldb::eStopDisassemblyTypeNoDebugInfo: if (have_debuginfo) break; [[fallthrough]]; - case Debugger::eStopDisassemblyTypeNoSource: + case lldb::eStopDisassemblyTypeNoSource: if (have_source) break; [[fallthrough]]; - case Debugger::eStopDisassemblyTypeAlways: + case lldb::eStopDisassemblyTypeAlways: if (target) { const uint32_t disasm_lines = debugger.GetDisassemblyLineCount(); if (disasm_lines > 0) { diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h index b24a8ff0d5ea6..727e5c00623e8 100644 --- a/lldb/tools/lldb-dap/DAP.h +++ b/lldb/tools/lldb-dap/DAP.h @@ -202,10 +202,6 @@ struct DAP { lldb::SBFormat frame_format; lldb::SBFormat thread_format; - - /// The value of stop-disassembly-display setting in LLDB. - std::string stop_disassembly_display; - // This is used to allow request_evaluate to handle empty expressions // (ie the user pressed 'return' and expects the previous expression to // repeat). If the previous expression was a command, this string will be diff --git a/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp index ce7444304a97d..5e622f3d3dcd4 100644 --- a/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/AttachRequestHandler.cpp @@ -108,7 +108,6 @@ void AttachRequestHandler::operator()(const llvm::json::Object &request) const { } SetSourceMapFromArguments(*arguments); - SetStopDisassemblyDisplayFromSettings(); lldb::SBError status; dap.SetTarget(dap.CreateTargetFromArguments(*arguments, status)); diff --git a/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp index 7b66b9b08ee55..5f14cb074e37e 100644 --- a/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp @@ -95,7 +95,6 @@ void LaunchRequestHandler::operator()(const llvm::json::Object &request) const { } SetSourceMapFromArguments(*arguments); - SetStopDisassemblyDisplayFromSettings(); lldb::SBError status; dap.SetTarget(dap.CreateTargetFromArguments(*arguments, status)); diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp index ad51fc6bbb35c..be9273963654a 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp @@ -99,10 +99,6 @@ void BaseRequestHandler::SetSourceMapFromArguments( } } -void BaseRequestHandler::SetStopDisassemblyDisplayFromSettings() const { - dap.stop_disassembly_display = GetStopDisassemblyDisplay(dap.debugger); -} - static llvm::Error RunInTerminal(DAP &dap, const llvm::json::Object &launch_request, const uint64_t timeout_seconds) { diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index fa672721b761b..e13f7a3749e00 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -63,9 +63,6 @@ class BaseRequestHandler { /// argument (or neither), from which we need to set the target.source-map. void SetSourceMapFromArguments(const llvm::json::Object &arguments) const; - /// Sets the stop-disassembly-display setting - void SetStopDisassemblyDisplayFromSettings() const; - /// Prints a welcome message on the editor if the preprocessor variable /// LLDB_DAP_WELCOME_MESSAGE is defined. void PrintWelcomeMessage() const; diff --git a/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp index acf16dbcd5a2f..029253dd1f7b6 100644 --- a/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp @@ -9,7 +9,9 @@ #include "DAP.h" #include "EventHelper.h" #include "JSONUtils.h" +#include "LLDBUtils.h" #include "RequestHandler.h" +#include "lldb/lldb-enumerations.h" namespace lldb_dap { @@ -51,6 +53,8 @@ static constexpr int StackPageSize = 20; static bool FillStackFrames(DAP &dap, lldb::SBThread &thread, llvm::json::Array &stack_frames, int64_t &offset, const int64_t start_frame, const int64_t levels) { + lldb::StopDisassemblyType stop_disassembly_display = + GetStopDisassemblyDisplay(dap.debugger); bool reached_end_of_stack = false; for (int64_t i = start_frame; static_cast<int64_t>(stack_frames.size()) < levels; i++) { @@ -67,8 +71,8 @@ static bool FillStackFrames(DAP &dap, lldb::SBThread &thread, break; } - stack_frames.emplace_back(CreateStackFrame(frame, dap.frame_format, - dap.stop_disassembly_display)); + stack_frames.emplace_back( + CreateStackFrame(frame, dap.frame_format, stop_disassembly_display)); } if (dap.configuration.displayExtendedBacktrace && reached_end_of_stack) { diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index d3e0f2a050a36..ad597495202cb 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -658,12 +658,13 @@ llvm::json::Value CreateSource(llvm::StringRef source_path) { return llvm::json::Value(std::move(source)); } -bool ShouldDisplayAssemblySource(const lldb::SBLineEntry &line_entry, - const std::string &stop_disassembly_display) { - if (stop_disassembly_display == "never") +bool ShouldDisplayAssemblySource( + const lldb::SBLineEntry &line_entry, + lldb::StopDisassemblyType stop_disassembly_display) { + if (stop_disassembly_display == lldb::eStopDisassemblyTypeNever) return false; - if (stop_disassembly_display == "always") + if (stop_disassembly_display == lldb::eStopDisassemblyTypeAlways) return true; // A line entry of 0 indicates the line is compiler generated i.e. no source @@ -673,7 +674,8 @@ bool ShouldDisplayAssemblySource(const lldb::SBLineEntry &line_entry, line_entry.GetLine() == LLDB_INVALID_LINE_NUMBER) return true; - if (stop_disassembly_display == "no-source" && !file_spec.Exists()) { + if (stop_disassembly_display == lldb::eStopDisassemblyTypeNoSource && + !file_spec.Exists()) { return true; } @@ -743,7 +745,7 @@ bool ShouldDisplayAssemblySource(const lldb::SBLineEntry &line_entry, // } llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, - const std::string &stop_disassembly_display) { + lldb::StopDisassemblyType stop_disassembly_display) { llvm::json::Object object; int64_t frame_id = MakeDAPFrameID(frame); object.try_emplace("id", frame_id); diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h index 7186f222b04e8..a52b87d9a8606 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -356,8 +356,9 @@ llvm::json::Value CreateSource(llvm::StringRef source_path); /// \return /// True if the line entry should be displayed as assembly, false /// otherwise. -bool ShouldDisplayAssemblySource(const lldb::SBLineEntry &line_entry, - const std::string &stop_disassembly_display); +bool ShouldDisplayAssemblySource( + const lldb::SBLineEntry &line_entry, + lldb::StopDisassemblyType stop_disassembly_display); /// Create a "StackFrame" object for a LLDB frame object. /// @@ -384,7 +385,7 @@ bool ShouldDisplayAssemblySource(const lldb::SBLineEntry &line_entry, /// A "StackFrame" JSON object with that follows the formal JSON /// definition outlined by Microsoft. llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, - const std::string &stop_disassembly_display); + lldb::StopDisassemblyType); /// Create a "StackFrame" label object for a LLDB thread. /// diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp index 3933be4cd8188..3a393c31bb91d 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.cpp +++ b/lldb/tools/lldb-dap/LLDBUtils.cpp @@ -10,6 +10,7 @@ #include "DAP.h" #include "JSONUtils.h" #include "lldb/API/SBStringList.h" +#include "llvm/ADT/StringSwitch.h" #include <mutex> @@ -163,17 +164,31 @@ GetEnvironmentFromArguments(const llvm::json::Object &arguments) { return envs; } -std::string GetStopDisassemblyDisplay(lldb::SBDebugger &debugger) { - lldb::SBStructuredData result = +lldb::StopDisassemblyType +GetStopDisassemblyDisplay(lldb::SBDebugger &debugger) { + lldb::StopDisassemblyType result = + lldb::StopDisassemblyType::eStopDisassemblyTypeNoDebugInfo; + lldb::SBStructuredData string_result = debugger.GetSetting("stop-disassembly-display"); - const size_t result_length = result.GetStringValue(nullptr, 0); + const size_t result_length = string_result.GetStringValue(nullptr, 0); if (result_length > 0) { std::string result_string(result_length, '\0'); - result.GetStringValue(result_string.data(), result_length + 1); - return result_string; + string_result.GetStringValue(result_string.data(), result_length + 1); + + result = + llvm::StringSwitch<lldb::StopDisassemblyType>(result_string) + .Case("never", lldb::StopDisassemblyType::eStopDisassemblyTypeNever) + .Case("always", + lldb::StopDisassemblyType::eStopDisassemblyTypeAlways) + .Case("no-source", + lldb::StopDisassemblyType::eStopDisassemblyTypeNoSource) + .Case("no-debuginfo", + lldb::StopDisassemblyType::eStopDisassemblyTypeNoDebugInfo) + .Default( + lldb::StopDisassemblyType::eStopDisassemblyTypeNoDebugInfo); } - return "no-debuginfo"; + return result; } llvm::Error ToError(const lldb::SBError &error) { diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h index 1ecb95122da04..0ba42a9d5cd6c 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.h +++ b/lldb/tools/lldb-dap/LLDBUtils.h @@ -163,7 +163,7 @@ GetEnvironmentFromArguments(const llvm::json::Object &arguments); /// /// \return /// The value of the stop-disassembly-display setting -std::string GetStopDisassemblyDisplay(lldb::SBDebugger &debugger); +lldb::StopDisassemblyType GetStopDisassemblyDisplay(lldb::SBDebugger &debugger); /// Take ownership of the stored error. llvm::Error ToError(const lldb::SBError &error); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits