https://github.com/eronnen created https://github.com/llvm/llvm-project/pull/136777
* Fix error in lldb-dap when the stack trace contains a frame without a module by simply showing the first 32 assembly instructions after the PC >From 93764e39ce2588ea0f86cf8283fa6c82bd89a8de Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Wed, 23 Apr 2025 00:06:28 +0200 Subject: [PATCH] [lldb-dap] handle stack frames without a module --- .../lldb-dap/stackTraceMissingModule/Makefile | 2 + .../TestDAP_stackTraceMissingModule.py | 54 +++++++++++++++++++ .../lldb-dap/stackTraceMissingModule/main.c | 37 +++++++++++++ .../lldb-dap/Handler/SourceRequestHandler.cpp | 14 ++++- lldb/tools/lldb-dap/JSONUtils.cpp | 10 ++++ 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/stackTraceMissingModule/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/stackTraceMissingModule/TestDAP_stackTraceMissingModule.py create mode 100644 lldb/test/API/tools/lldb-dap/stackTraceMissingModule/main.c diff --git a/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/Makefile b/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/Makefile new file mode 100644 index 0000000000000..c9319d6e6888a --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/Makefile @@ -0,0 +1,2 @@ +C_SOURCES := main.c +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/TestDAP_stackTraceMissingModule.py b/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/TestDAP_stackTraceMissingModule.py new file mode 100644 index 0000000000000..1eb00f9935a22 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/TestDAP_stackTraceMissingModule.py @@ -0,0 +1,54 @@ +""" +Test lldb-dap stack trace when module is missing +""" + +from lldbsuite.test.decorators import skipUnlessPlatform +from lldbsuite.test.lldbtest import line_number +import lldbdap_testcase +import re + + +class TestDAP_stackTraceMissingModule(lldbdap_testcase.DAPTestCaseBase): + @skipUnlessPlatform(["linux"]) + def test_missingModule(self): + """ + Test that the stack frame without a module still has assembly source. + """ + program = self.getBuildArtifact("a.out") + self.build_and_launch(program, commandEscapePrefix="") + + source = "main.c" + self.set_source_breakpoints( + source, + [line_number(source, "// Break here")], + ) + self.continue_to_next_stop() + + # Evaluate expr -- func + expr_result = self.dap_server.request_evaluate( + expression="expr -f pointer -- func", + context="repl", + ) + + expr_result_address = re.search( + r"0x[0-9a-fA-F]+", expr_result["body"]["result"] + ) + self.assertIsNotNone( + expr_result_address, "Failed to get address of dynamic allocated func" + ) + func_address = expr_result_address.group(0) + + self.dap_server.request_evaluate( + expression=f"breakpoint set --address {func_address}", + context="repl", + ) + + self.continue_to_next_stop() + + frame_without_module = self.get_stackFrames()[0] + + self.assertIn("line", frame_without_module, "Line number missing.") + self.assertIn("column", frame_without_module, "Column number missing.") + self.assertIn("source", frame_without_module, "Source location missing.") + source = frame_without_module["source"] + self.assertIn("sourceReference", source, "Source reference missing.") diff --git a/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/main.c b/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/main.c new file mode 100644 index 0000000000000..d706231fbd5c2 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/main.c @@ -0,0 +1,37 @@ +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <sys/mman.h> +#include <unistd.h> + +extern uint8_t __start_target_section[]; +extern uint8_t __stop_target_section[]; + +__attribute__((used, section("target_section"))) int target_function(void) { + return 42; +} + +typedef int (*target_function_t)(void); + +int main(void) { + size_t target_function_size = __stop_target_section - __start_target_section; + size_t page_size = sysconf(_SC_PAGESIZE); + size_t page_aligned_size = + (target_function_size + page_size - 1) & ~(page_size - 1); + + void *executable_memory = + mmap(NULL, page_aligned_size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (executable_memory == MAP_FAILED) { + perror("mmap"); + return 1; + } + + memcpy(executable_memory, __start_target_section, target_function_size); + + target_function_t func = (target_function_t)executable_memory; + int result = func(); // Break here + printf("Result from target function: %d\n", result); + + return 0; +} diff --git a/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp index 1a7a13d9f267a..99c3692f15283 100644 --- a/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp @@ -15,6 +15,7 @@ #include "lldb/API/SBInstructionList.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBSymbol.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" #include "llvm/Support/Error.h" @@ -41,9 +42,18 @@ SourceRequestHandler::Run(const protocol::SourceArguments &args) const { if (!frame.IsValid()) return llvm::make_error<DAPError>("source not found"); - lldb::SBInstructionList insts = frame.GetSymbol().GetInstructions(dap.target); lldb::SBStream stream; - insts.GetDescription(stream); + lldb::SBSymbol symbol = frame.GetSymbol(); + + if (symbol.IsValid()) { + lldb::SBInstructionList insts = symbol.GetInstructions(dap.target); + insts.GetDescription(stream); + } else { + // No valid symbol, just return the disassembly + lldb::SBInstructionList insts = + dap.target.ReadInstructions(frame.GetPCAddress(), 32); + insts.GetDescription(stream); + } return protocol::SourceResponseBody{/*content=*/stream.GetData(), /*mimeType=*/"text/x-lldb.disassembly"}; diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 33f10c93d2ada..30d277abce11e 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -783,6 +783,16 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, // Line numbers are 1-based. object.try_emplace("line", inst_line + 1); object.try_emplace("column", 1); + } else { + // No valid line entry or symbol + llvm::json::Object source; + EmplaceSafeString(source, "name", frame_name); + source.try_emplace("sourceReference", MakeDAPFrameID(frame)); + EmplaceSafeString(source, "presentationHint", "deemphasize"); + object.try_emplace("source", std::move(source)); + + object.try_emplace("line", 1); + object.try_emplace("column", 1); } const auto pc = frame.GetPC(); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits