https://github.com/eronnen updated https://github.com/llvm/llvm-project/pull/141426
>From cf84a67c669ef76ca0e5f5ec7dbc0c34a44a155a Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Wed, 21 May 2025 23:39:56 +0200 Subject: [PATCH 1/9] Reuse creation of Source objects for assembly and normal sources --- lldb/tools/lldb-dap/Breakpoint.cpp | 14 +- .../Handler/DisassembleRequestHandler.cpp | 21 +-- .../Handler/LocationsRequestHandler.cpp | 10 +- .../Handler/StackTraceRequestHandler.cpp | 6 +- lldb/tools/lldb-dap/JSONUtils.cpp | 123 +++++++++--------- lldb/tools/lldb-dap/JSONUtils.h | 49 ++----- lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 2 + 7 files changed, 100 insertions(+), 125 deletions(-) diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp index 2d0fd9c9c3954..440d589b912fc 100644 --- a/lldb/tools/lldb-dap/Breakpoint.cpp +++ b/lldb/tools/lldb-dap/Breakpoint.cpp @@ -9,12 +9,10 @@ #include "Breakpoint.h" #include "DAP.h" #include "JSONUtils.h" -#include "LLDBUtils.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBBreakpointLocation.h" #include "lldb/API/SBLineEntry.h" #include "lldb/API/SBMutex.h" -#include "lldb/lldb-enumerations.h" #include "llvm/ADT/StringExtras.h" #include <cstddef> #include <cstdint> @@ -66,17 +64,15 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() { "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(m_bp.GetTarget())); breakpoint.instructionReference = formatted_addr; - lldb::StopDisassemblyType stop_disassembly_display = - GetStopDisassemblyDisplay(m_dap.debugger); - auto line_entry = bp_addr.GetLineEntry(); - if (!ShouldDisplayAssemblySource(line_entry, stop_disassembly_display)) { + auto source = CreateSource(bp_addr, m_dap.debugger); + if (!source.IsAssemblySource()) { + auto line_entry = bp_addr.GetLineEntry(); const auto line = line_entry.GetLine(); if (line != LLDB_INVALID_LINE_NUMBER) breakpoint.line = line; const auto column = line_entry.GetColumn(); if (column != LLDB_INVALID_COLUMN_NUMBER) breakpoint.column = column; - breakpoint.source = CreateSource(line_entry); } else { // Assembly breakpoint. auto symbol = bp_addr.GetSymbol(); @@ -86,10 +82,10 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() { .ReadInstructions(symbol.GetStartAddress(), bp_addr, nullptr) .GetSize() + 1; - - breakpoint.source = CreateAssemblySource(m_dap.target, bp_addr); } } + + breakpoint.source = std::move(source); } return breakpoint; diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp index b3da869d18d68..2819fb9ed1b18 100644 --- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp @@ -13,6 +13,7 @@ #include "Protocol/ProtocolTypes.h" #include "RequestHandler.h" #include "lldb/API/SBAddress.h" +#include "lldb/API/SBDebugger.h" #include "lldb/API/SBInstruction.h" #include "lldb/API/SBTarget.h" #include "lldb/lldb-types.h" @@ -81,12 +82,15 @@ static lldb::SBAddress GetDisassembleStartAddress(lldb::SBTarget target, .GetAddress(); } -static DisassembledInstruction ConvertSBInstructionToDisassembledInstruction( - lldb::SBTarget &target, lldb::SBInstruction &inst, bool resolve_symbols) { +static DisassembledInstruction +ConvertSBInstructionToDisassembledInstruction(lldb::SBDebugger &debugger, + lldb::SBInstruction &inst, + bool resolve_symbols) { if (!inst.IsValid()) return GetInvalidInstruction(); - auto addr = inst.GetAddress(); + lldb::SBTarget target = debugger.GetSelectedTarget(); + lldb::SBAddress addr = inst.GetAddress(); const auto inst_addr = addr.GetLoadAddress(target); // FIXME: This is a workaround - this address might come from @@ -139,15 +143,14 @@ static DisassembledInstruction ConvertSBInstructionToDisassembledInstruction( disassembled_inst.instruction = std::move(instruction); + auto source = CreateSource(addr, debugger); auto line_entry = addr.GetLineEntry(); - // If the line number is 0 then the entry represents a compiler generated - // location. - if (line_entry.GetStartAddress() == addr && line_entry.IsValid() && + if (!source.IsAssemblySource() && line_entry.IsValid() && + line_entry.GetStartAddress() == addr && line_entry.IsValid() && line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0) { - auto source = CreateSource(line_entry); - disassembled_inst.location = std::move(source); + disassembled_inst.location = std::move(source); const auto line = line_entry.GetLine(); if (line != 0 && line != LLDB_INVALID_LINE_NUMBER) disassembled_inst.line = line; @@ -220,7 +223,7 @@ DisassembleRequestHandler::Run(const DisassembleArguments &args) const { original_address_index = i; instructions.push_back(ConvertSBInstructionToDisassembledInstruction( - dap.target, inst, resolve_symbols)); + dap.debugger, inst, resolve_symbols)); } // Check if we miss instructions at the beginning. diff --git a/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp index 15109d4b8e589..29f7356f46e42 100644 --- a/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp @@ -10,7 +10,9 @@ #include "EventHelper.h" #include "JSONUtils.h" #include "RequestHandler.h" +#include "lldb/API/SBAddress.h" #include "lldb/API/SBDeclaration.h" +#include "lldb/API/SBLineEntry.h" namespace lldb_dap { @@ -122,9 +124,9 @@ void LocationsRequestHandler::operator()( return; } - lldb::addr_t addr = variable.GetValueAsAddress(); - lldb::SBLineEntry line_entry = - dap.target.ResolveLoadAddress(addr).GetLineEntry(); + lldb::addr_t raw_addr = variable.GetValueAsAddress(); + lldb::SBAddress addr = dap.target.ResolveLoadAddress(raw_addr); + lldb::SBLineEntry line_entry = addr.GetLineEntry(); if (!line_entry.IsValid()) { response["success"] = false; @@ -133,7 +135,7 @@ void LocationsRequestHandler::operator()( return; } - body.try_emplace("source", CreateSource(line_entry.GetFileSpec())); + body.try_emplace("source", CreateSource(addr, dap.debugger)); if (int line = line_entry.GetLine()) body.try_emplace("line", line); if (int column = line_entry.GetColumn()) diff --git a/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp index ff326a47d9a48..1a4e87f8035ec 100644 --- a/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp @@ -9,9 +9,7 @@ #include "DAP.h" #include "EventHelper.h" #include "JSONUtils.h" -#include "LLDBUtils.h" #include "RequestHandler.h" -#include "lldb/lldb-enumerations.h" namespace lldb_dap { @@ -55,8 +53,6 @@ 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, const bool include_all) { - 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++) { @@ -74,7 +70,7 @@ static bool FillStackFrames(DAP &dap, lldb::SBThread &thread, } stack_frames.emplace_back( - CreateStackFrame(frame, frame_format, stop_disassembly_display)); + CreateStackFrame(frame, frame_format, dap.debugger)); } if (include_all && reached_end_of_stack) { diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index f0b3dfb595717..9ecd7f7742fe2 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -497,34 +497,33 @@ static std::string GetLoadAddressString(const lldb::addr_t addr) { return result; } -protocol::Source CreateSource(const lldb::SBFileSpec &file) { - protocol::Source source; - if (file.IsValid()) { - const char *name = file.GetFilename(); - if (name) - source.name = name; - char path[PATH_MAX] = ""; - if (file.GetPath(path, sizeof(path)) && - lldb::SBFileSpec::ResolvePath(path, path, PATH_MAX)) - source.path = path; - } - return source; -} +static bool ShouldDisplayAssemblySource( + lldb::SBAddress address, + lldb::StopDisassemblyType stop_disassembly_display) { + if (stop_disassembly_display == lldb::eStopDisassemblyTypeNever) + return false; -protocol::Source CreateSource(const lldb::SBLineEntry &line_entry) { - return CreateSource(line_entry.GetFileSpec()); -} + if (stop_disassembly_display == lldb::eStopDisassemblyTypeAlways) + return true; -protocol::Source CreateSource(llvm::StringRef source_path) { - protocol::Source source; - llvm::StringRef name = llvm::sys::path::filename(source_path); - source.name = name; - source.path = source_path; - return source; + // A line entry of 0 indicates the line is compiler generated i.e. no source + // file is associated with the frame. + auto line_entry = address.GetLineEntry(); + 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 == lldb::eStopDisassemblyTypeNoSource && + !file_spec.Exists()) { + return true; + } + + return false; } -protocol::Source CreateAssemblySource(const lldb::SBTarget &target, - lldb::SBAddress &address) { +static protocol::Source CreateAssemblySource(const lldb::SBTarget &target, + lldb::SBAddress address) { protocol::Source source; auto symbol = address.GetSymbol(); @@ -558,28 +557,36 @@ protocol::Source CreateAssemblySource(const lldb::SBTarget &target, return source; } -bool ShouldDisplayAssemblySource( - const lldb::SBLineEntry &line_entry, - lldb::StopDisassemblyType stop_disassembly_display) { - if (stop_disassembly_display == lldb::eStopDisassemblyTypeNever) - return false; - - if (stop_disassembly_display == lldb::eStopDisassemblyTypeAlways) - return true; +protocol::Source CreateSource(const lldb::SBFileSpec &file) { + protocol::Source source; + if (file.IsValid()) { + const char *name = file.GetFilename(); + if (name) + source.name = name; + char path[PATH_MAX] = ""; + if (file.GetPath(path, sizeof(path)) && + lldb::SBFileSpec::ResolvePath(path, path, PATH_MAX)) + source.path = path; + } + return source; +} - // 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; +protocol::Source CreateSource(lldb::SBAddress address, + lldb::SBDebugger &debugger) { + lldb::StopDisassemblyType stop_disassembly_display = + GetStopDisassemblyDisplay(debugger); + if (!ShouldDisplayAssemblySource(address, stop_disassembly_display)) + return CreateSource(address.GetLineEntry().GetFileSpec()); - if (stop_disassembly_display == lldb::eStopDisassemblyTypeNoSource && - !file_spec.Exists()) { - return true; - } + return CreateAssemblySource(debugger.GetSelectedTarget(), address); +} - return false; +protocol::Source CreateSource(llvm::StringRef source_path) { + protocol::Source source; + llvm::StringRef name = llvm::sys::path::filename(source_path); + source.name = name; + source.path = source_path; + return source; } // "StackFrame": { @@ -643,9 +650,8 @@ bool ShouldDisplayAssemblySource( // }, // "required": [ "id", "name", "line", "column" ] // } -llvm::json::Value -CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, - lldb::StopDisassemblyType stop_disassembly_display) { +llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, + lldb::SBDebugger &debugger) { llvm::json::Object object; int64_t frame_id = MakeDAPFrameID(frame); object.try_emplace("id", frame_id); @@ -673,22 +679,17 @@ CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, EmplaceSafeString(object, "name", frame_name); - auto line_entry = frame.GetLineEntry(); - if (!ShouldDisplayAssemblySource(line_entry, stop_disassembly_display)) { - object.try_emplace("source", CreateSource(line_entry)); + auto source = CreateSource(frame.GetPCAddress(), debugger); + if (!source.IsAssemblySource()) { + // This is a normal source with valid line entry. + auto line_entry = frame.GetLineEntry(); object.try_emplace("line", line_entry.GetLine()); auto column = line_entry.GetColumn(); object.try_emplace("column", column); } else if (frame.GetSymbol().IsValid()) { - // If no source is associated with the frame, use the DAPFrameID to track - // the 'source' and generate assembly. - auto frame_address = frame.GetPCAddress(); - object.try_emplace("source", CreateAssemblySource( - frame.GetThread().GetProcess().GetTarget(), - frame_address)); - - // Calculate the line of the current PC from the start of the current - // symbol. + // This is a source where the disassembly is used, but there is a valid + // symbol. Calculate the line of the current PC from the start of the + // current symbol. lldb::SBTarget target = frame.GetThread().GetProcess().GetTarget(); lldb::SBInstructionList inst_list = target.ReadInstructions( frame.GetSymbol().GetStartAddress(), frame.GetPCAddress(), nullptr); @@ -699,14 +700,12 @@ CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, object.try_emplace("column", 1); } else { // No valid line entry or symbol. - auto frame_address = frame.GetPCAddress(); - object.try_emplace("source", CreateAssemblySource( - frame.GetThread().GetProcess().GetTarget(), - frame_address)); object.try_emplace("line", 1); object.try_emplace("column", 1); } + object.try_emplace("source", std::move(source)); + const auto pc = frame.GetPC(); if (pc != LLDB_INVALID_ADDRESS) { std::string formatted_addr = "0x" + llvm::utohexstr(pc); diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h index 5758c3d56ec90..74866cdf32840 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -11,7 +11,9 @@ #include "DAPForward.h" #include "Protocol/ProtocolTypes.h" +#include "lldb/API/SBAddress.h" #include "lldb/API/SBCompileUnit.h" +#include "lldb/API/SBDebugger.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBFormat.h" #include "lldb/API/SBLineEntry.h" @@ -250,14 +252,17 @@ protocol::Source CreateSource(const lldb::SBFileSpec &file); /// Create a "Source" JSON object as described in the debug adapter definition. /// -/// \param[in] line_entry -/// The LLDB line table to use when populating out the "Source" -/// object +/// \param[in] address +/// The address to use when populating out the "Source" object. +/// +/// \param[in] debugger +/// The debugger, used to get relevant settings. /// /// \return /// A "Source" JSON object that follows the formal JSON /// definition outlined by Microsoft. -protocol::Source CreateSource(const lldb::SBLineEntry &line_entry); +protocol::Source CreateSource(lldb::SBAddress address, + lldb::SBDebugger &debugger); /// Create a "Source" object for a given source path. /// @@ -269,35 +274,6 @@ protocol::Source CreateSource(const lldb::SBLineEntry &line_entry); /// definition outlined by Microsoft. protocol::Source CreateSource(llvm::StringRef source_path); -/// Create a "Source" object for a given frame, using its assembly for source. -/// -/// \param[in] target -/// The relevant target. -/// -/// \param[in] address -/// The address to use when creating the "Source" object. -/// -/// \return -/// A "Source" JSON object that follows the formal JSON -/// definition outlined by Microsoft. -protocol::Source CreateAssemblySource(const lldb::SBTarget &target, - lldb::SBAddress &address); - -/// 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, - lldb::StopDisassemblyType stop_disassembly_display); - /// Create a "StackFrame" object for a LLDB frame object. /// /// This function will fill in the following keys in the returned @@ -316,14 +292,15 @@ bool ShouldDisplayAssemblySource( /// The LLDB format to use when populating out the "StackFrame" /// object. /// -/// \param[in] stop_disassembly_display -/// The value of the "stop-disassembly-display" setting. +/// \param[in] debugger +/// The LLDB debugger to use when populating out the "StackFrame" +/// object. /// /// \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, - lldb::StopDisassemblyType); + lldb::SBDebugger &debugger); /// Create a "StackFrame" label object for a LLDB thread. /// diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h index f5e21c96fe17f..b05b02d7092ea 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h @@ -317,6 +317,8 @@ struct Source { std::optional<PresentationHint> presentationHint; // unsupported keys: origin, sources, adapterData, checksums + + bool IsAssemblySource() const { return sourceReference.value_or(0) != 0; } }; bool fromJSON(const llvm::json::Value &, Source::PresentationHint &, llvm::json::Path); >From df319c7ca9ae2a88c2e082b514b881da7c8697ab Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Sun, 25 May 2025 21:18:40 +0200 Subject: [PATCH 2/9] apply source mapping when getting line entry from an address --- lldb/include/lldb/API/SBAddress.h | 7 ++++++ lldb/source/API/SBAddress.cpp | 22 ++++++++++++++++--- lldb/source/Core/Module.cpp | 3 +++ lldb/tools/lldb-dap/Breakpoint.cpp | 2 +- .../Handler/DisassembleRequestHandler.cpp | 22 +++++++++---------- .../Handler/LocationsRequestHandler.cpp | 5 +++-- .../Handler/StackTraceRequestHandler.cpp | 3 +-- lldb/tools/lldb-dap/JSONUtils.cpp | 22 +++++++++++-------- lldb/tools/lldb-dap/JSONUtils.h | 15 +++++-------- lldb/tools/lldb-dap/LLDBUtils.cpp | 7 ++++++ lldb/tools/lldb-dap/LLDBUtils.h | 14 ++++++++++++ 11 files changed, 84 insertions(+), 38 deletions(-) diff --git a/lldb/include/lldb/API/SBAddress.h b/lldb/include/lldb/API/SBAddress.h index 430dad4862dbf..c61f02702f1ca 100644 --- a/lldb/include/lldb/API/SBAddress.h +++ b/lldb/include/lldb/API/SBAddress.h @@ -11,6 +11,7 @@ #include "lldb/API/SBDefines.h" #include "lldb/API/SBModule.h" +#include "lldb/API/SBTarget.h" namespace lldb { @@ -58,6 +59,9 @@ class LLDB_API SBAddress { // "lldb::SBAddress SBTarget::ResolveLoadAddress (...)". lldb::SBSymbolContext GetSymbolContext(uint32_t resolve_scope); + lldb::SBSymbolContext GetSymbolContext(const SBTarget &target, + uint32_t resolve_scope); + // The following functions grab individual objects for a given address and // are less efficient if you want more than one symbol related objects. Use // one of the following when you want multiple debug symbol related objects @@ -122,6 +126,9 @@ class LLDB_API SBAddress { void SetAddress(const lldb_private::Address &address); + void CalculateSymbolContext(lldb_private::SymbolContext &sc, + uint32_t resolve_scope); + private: std::unique_ptr<lldb_private::Address> m_opaque_up; }; diff --git a/lldb/source/API/SBAddress.cpp b/lldb/source/API/SBAddress.cpp index e519f0bcc83c6..b6b9e238d3cbf 100644 --- a/lldb/source/API/SBAddress.cpp +++ b/lldb/source/API/SBAddress.cpp @@ -213,9 +213,18 @@ SBSymbolContext SBAddress::GetSymbolContext(uint32_t resolve_scope) { LLDB_INSTRUMENT_VA(this, resolve_scope); SBSymbolContext sb_sc; - SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope); - if (m_opaque_up->IsValid()) - m_opaque_up->CalculateSymbolContext(&sb_sc.ref(), scope); + CalculateSymbolContext(sb_sc.ref(), resolve_scope); + return sb_sc; +} + +SBSymbolContext SBAddress::GetSymbolContext(const SBTarget &target, + uint32_t resolve_scope) { + LLDB_INSTRUMENT_VA(this, target, resolve_scope); + + SBSymbolContext sb_sc; + lldb_private::SymbolContext &sc = sb_sc.ref(); + sc.target_sp = target.GetSP(); + CalculateSymbolContext(sc, resolve_scope); return sb_sc; } @@ -266,3 +275,10 @@ SBLineEntry SBAddress::GetLineEntry() { } return sb_line_entry; } + +void SBAddress::CalculateSymbolContext(lldb_private::SymbolContext &sc, + uint32_t resolve_scope) { + SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope); + if (m_opaque_up->IsValid()) + m_opaque_up->CalculateSymbolContext(&sc, scope); +} diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 625c14e4a2153..90997dada3666 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -483,6 +483,9 @@ uint32_t Module::ResolveSymbolContextForAddress( symfile->SetLoadDebugInfoEnabled(); resolved_flags |= symfile->ResolveSymbolContext(so_addr, resolve_scope, sc); + + if ((resolve_scope & eSymbolContextLineEntry) && sc.line_entry.IsValid()) + sc.line_entry.ApplyFileMappings(sc.target_sp); } // Resolve the symbol if requested, but don't re-look it up if we've diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp index 440d589b912fc..dea4dbadc0bda 100644 --- a/lldb/tools/lldb-dap/Breakpoint.cpp +++ b/lldb/tools/lldb-dap/Breakpoint.cpp @@ -64,7 +64,7 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() { "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(m_bp.GetTarget())); breakpoint.instructionReference = formatted_addr; - auto source = CreateSource(bp_addr, m_dap.debugger); + auto source = CreateSource(bp_addr, m_dap.target); if (!source.IsAssemblySource()) { auto line_entry = bp_addr.GetLineEntry(); const auto line = line_entry.GetLine(); diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp index 2819fb9ed1b18..05d3aa6417217 100644 --- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp @@ -9,11 +9,11 @@ #include "DAP.h" #include "EventHelper.h" #include "JSONUtils.h" +#include "LLDBUtils.h" #include "Protocol/ProtocolRequests.h" #include "Protocol/ProtocolTypes.h" #include "RequestHandler.h" #include "lldb/API/SBAddress.h" -#include "lldb/API/SBDebugger.h" #include "lldb/API/SBInstruction.h" #include "lldb/API/SBTarget.h" #include "lldb/lldb-types.h" @@ -82,15 +82,12 @@ static lldb::SBAddress GetDisassembleStartAddress(lldb::SBTarget target, .GetAddress(); } -static DisassembledInstruction -ConvertSBInstructionToDisassembledInstruction(lldb::SBDebugger &debugger, - lldb::SBInstruction &inst, - bool resolve_symbols) { +static DisassembledInstruction ConvertSBInstructionToDisassembledInstruction( + lldb::SBTarget &target, lldb::SBInstruction &inst, bool resolve_symbols) { if (!inst.IsValid()) return GetInvalidInstruction(); - lldb::SBTarget target = debugger.GetSelectedTarget(); - lldb::SBAddress addr = inst.GetAddress(); + auto addr = inst.GetAddress(); const auto inst_addr = addr.GetLoadAddress(target); // FIXME: This is a workaround - this address might come from @@ -143,9 +140,11 @@ ConvertSBInstructionToDisassembledInstruction(lldb::SBDebugger &debugger, disassembled_inst.instruction = std::move(instruction); - auto source = CreateSource(addr, debugger); - auto line_entry = addr.GetLineEntry(); + auto source = CreateSource(addr, target); + auto line_entry = GetLineEntryForAddress(target, addr); + // If the line number is 0 then the entry represents a compiler generated + // location. if (!source.IsAssemblySource() && line_entry.IsValid() && line_entry.GetStartAddress() == addr && line_entry.IsValid() && line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0) { @@ -159,7 +158,8 @@ ConvertSBInstructionToDisassembledInstruction(lldb::SBDebugger &debugger, if (column != 0 && column != LLDB_INVALID_COLUMN_NUMBER) disassembled_inst.column = column; - auto end_line_entry = line_entry.GetEndAddress().GetLineEntry(); + lldb::SBAddress end_addr = line_entry.GetEndAddress(); + auto end_line_entry = GetLineEntryForAddress(target, end_addr); if (end_line_entry.IsValid() && end_line_entry.GetFileSpec() == line_entry.GetFileSpec()) { const auto end_line = end_line_entry.GetLine(); @@ -223,7 +223,7 @@ DisassembleRequestHandler::Run(const DisassembleArguments &args) const { original_address_index = i; instructions.push_back(ConvertSBInstructionToDisassembledInstruction( - dap.debugger, inst, resolve_symbols)); + dap.target, inst, resolve_symbols)); } // Check if we miss instructions at the beginning. diff --git a/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp index 29f7356f46e42..39ad6949990c7 100644 --- a/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp @@ -9,6 +9,7 @@ #include "DAP.h" #include "EventHelper.h" #include "JSONUtils.h" +#include "LLDBUtils.h" #include "RequestHandler.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBDeclaration.h" @@ -126,7 +127,7 @@ void LocationsRequestHandler::operator()( lldb::addr_t raw_addr = variable.GetValueAsAddress(); lldb::SBAddress addr = dap.target.ResolveLoadAddress(raw_addr); - lldb::SBLineEntry line_entry = addr.GetLineEntry(); + lldb::SBLineEntry line_entry = GetLineEntryForAddress(dap.target, addr); if (!line_entry.IsValid()) { response["success"] = false; @@ -135,7 +136,7 @@ void LocationsRequestHandler::operator()( return; } - body.try_emplace("source", CreateSource(addr, dap.debugger)); + body.try_emplace("source", CreateSource(line_entry.GetFileSpec())); if (int line = line_entry.GetLine()) body.try_emplace("line", line); if (int column = line_entry.GetColumn()) diff --git a/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp index 1a4e87f8035ec..4ea4cd1e517d4 100644 --- a/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/StackTraceRequestHandler.cpp @@ -69,8 +69,7 @@ static bool FillStackFrames(DAP &dap, lldb::SBThread &thread, break; } - stack_frames.emplace_back( - CreateStackFrame(frame, frame_format, dap.debugger)); + stack_frames.emplace_back(CreateStackFrame(frame, frame_format)); } if (include_all && reached_end_of_stack) { diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 9ecd7f7742fe2..a7a78fe35969d 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -12,6 +12,7 @@ #include "LLDBUtils.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBCompileUnit.h" +#include "lldb/API/SBDebugger.h" #include "lldb/API/SBDeclaration.h" #include "lldb/API/SBEnvironment.h" #include "lldb/API/SBError.h" @@ -571,14 +572,16 @@ protocol::Source CreateSource(const lldb::SBFileSpec &file) { return source; } -protocol::Source CreateSource(lldb::SBAddress address, - lldb::SBDebugger &debugger) { +protocol::Source CreateSource(lldb::SBAddress address, lldb::SBTarget &target) { + lldb::SBDebugger debugger = target.GetDebugger(); lldb::StopDisassemblyType stop_disassembly_display = GetStopDisassemblyDisplay(debugger); - if (!ShouldDisplayAssemblySource(address, stop_disassembly_display)) - return CreateSource(address.GetLineEntry().GetFileSpec()); + if (!ShouldDisplayAssemblySource(address, stop_disassembly_display)) { + lldb::SBLineEntry line_entry = GetLineEntryForAddress(target, address); + return CreateSource(line_entry.GetFileSpec()); + } - return CreateAssemblySource(debugger.GetSelectedTarget(), address); + return CreateAssemblySource(target, address); } protocol::Source CreateSource(llvm::StringRef source_path) { @@ -650,8 +653,8 @@ protocol::Source CreateSource(llvm::StringRef source_path) { // }, // "required": [ "id", "name", "line", "column" ] // } -llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, - lldb::SBDebugger &debugger) { +llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, + lldb::SBFormat &format) { llvm::json::Object object; int64_t frame_id = MakeDAPFrameID(frame); object.try_emplace("id", frame_id); @@ -679,9 +682,10 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format, EmplaceSafeString(object, "name", frame_name); - auto source = CreateSource(frame.GetPCAddress(), debugger); + auto target = frame.GetThread().GetProcess().GetTarget(); + auto source = CreateSource(frame.GetPCAddress(), target); if (!source.IsAssemblySource()) { - // This is a normal source with valid line entry. + // This is a normal source with a valid line entry. auto line_entry = frame.GetLineEntry(); 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 74866cdf32840..3f9b3162ad027 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -255,14 +255,13 @@ protocol::Source CreateSource(const lldb::SBFileSpec &file); /// \param[in] address /// The address to use when populating out the "Source" object. /// -/// \param[in] debugger -/// The debugger, used to get relevant settings. +/// \param[in] target +/// The target that has the address. /// /// \return /// A "Source" JSON object that follows the formal JSON /// definition outlined by Microsoft. -protocol::Source CreateSource(lldb::SBAddress address, - lldb::SBDebugger &debugger); +protocol::Source CreateSource(lldb::SBAddress address, lldb::SBTarget &target); /// Create a "Source" object for a given source path. /// @@ -292,15 +291,11 @@ protocol::Source CreateSource(llvm::StringRef source_path); /// The LLDB format to use when populating out the "StackFrame" /// object. /// -/// \param[in] debugger -/// The LLDB debugger to use when populating out the "StackFrame" -/// object. -/// /// \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, - lldb::SBDebugger &debugger); +llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, + lldb::SBFormat &format); /// 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 fe0bcda19b4cd..eb23a89be78da 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.cpp +++ b/lldb/tools/lldb-dap/LLDBUtils.cpp @@ -252,4 +252,11 @@ std::string GetSBFileSpecPath(const lldb::SBFileSpec &file_spec) { return path; } +lldb::SBLineEntry GetLineEntryForAddress(lldb::SBTarget &target, + lldb::SBAddress &address) { + lldb::SBSymbolContext sc = + address.GetSymbolContext(target, lldb::eSymbolContextLineEntry); + return sc.GetLineEntry(); +} + } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h index 7fdf4b859ee61..74c10befdca67 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.h +++ b/lldb/tools/lldb-dap/LLDBUtils.h @@ -14,6 +14,8 @@ #include "lldb/API/SBEnvironment.h" #include "lldb/API/SBError.h" #include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBLineEntry.h" +#include "lldb/API/SBTarget.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -171,6 +173,18 @@ GetEnvironmentFromArguments(const llvm::json::Object &arguments); /// The file path as a string. std::string GetSBFileSpecPath(const lldb::SBFileSpec &file_spec); +/// Gets the line entry for a given address. +/// \param[in] target +/// The target that has the address. +/// +/// \param[in] address +/// The address for which to get the line entry. +/// +/// \return +/// The line entry for the given address. +lldb::SBLineEntry GetLineEntryForAddress(lldb::SBTarget &target, + lldb::SBAddress &address); + /// Helper for sending telemetry to lldb server, if client-telemetry is enabled. class TelemetryDispatcher { public: >From bb648c668ac7d184d267a921b0c98ad14c193987 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Wed, 28 May 2025 08:57:55 +0200 Subject: [PATCH 3/9] remove dead CreateSource version, move IsAssemblySource to ProtocolUtils.cpp --- lldb/tools/lldb-dap/Breakpoint.cpp | 3 ++- lldb/tools/lldb-dap/CMakeLists.txt | 1 + .../Handler/DisassembleRequestHandler.cpp | 3 ++- lldb/tools/lldb-dap/JSONUtils.cpp | 11 ++------- lldb/tools/lldb-dap/JSONUtils.h | 10 -------- lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 2 -- .../tools/lldb-dap/Protocol/ProtocolUtils.cpp | 17 +++++++++++++ lldb/tools/lldb-dap/Protocol/ProtocolUtils.h | 24 +++++++++++++++++++ 8 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp create mode 100644 lldb/tools/lldb-dap/Protocol/ProtocolUtils.h diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp index dea4dbadc0bda..ef9333713e940 100644 --- a/lldb/tools/lldb-dap/Breakpoint.cpp +++ b/lldb/tools/lldb-dap/Breakpoint.cpp @@ -9,6 +9,7 @@ #include "Breakpoint.h" #include "DAP.h" #include "JSONUtils.h" +#include "Protocol/ProtocolUtils.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBBreakpointLocation.h" #include "lldb/API/SBLineEntry.h" @@ -65,7 +66,7 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() { breakpoint.instructionReference = formatted_addr; auto source = CreateSource(bp_addr, m_dap.target); - if (!source.IsAssemblySource()) { + if (!IsAssemblySource(source)) { auto line_entry = bp_addr.GetLineEntry(); const auto line = line_entry.GetLine(); if (line != LLDB_INVALID_LINE_NUMBER) diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt index 490aa4710af1a..401e0672b5375 100644 --- a/lldb/tools/lldb-dap/CMakeLists.txt +++ b/lldb/tools/lldb-dap/CMakeLists.txt @@ -68,6 +68,7 @@ add_lldb_library(lldbDAP Protocol/ProtocolBase.cpp Protocol/ProtocolTypes.cpp Protocol/ProtocolRequests.cpp + Protocol/ProtocolUtils.cpp LINK_LIBS liblldb diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp index 05d3aa6417217..89af4b93120f4 100644 --- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp @@ -12,6 +12,7 @@ #include "LLDBUtils.h" #include "Protocol/ProtocolRequests.h" #include "Protocol/ProtocolTypes.h" +#include "Protocol/ProtocolUtils.h" #include "RequestHandler.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBInstruction.h" @@ -145,7 +146,7 @@ static DisassembledInstruction ConvertSBInstructionToDisassembledInstruction( // If the line number is 0 then the entry represents a compiler generated // location. - if (!source.IsAssemblySource() && line_entry.IsValid() && + if (!IsAssemblySource(source) && line_entry.IsValid() && line_entry.GetStartAddress() == addr && line_entry.IsValid() && line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0) { diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index a7a78fe35969d..ed9cb0a86a1d2 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -10,6 +10,7 @@ #include "DAP.h" #include "ExceptionBreakpoint.h" #include "LLDBUtils.h" +#include "Protocol/ProtocolUtils.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBCompileUnit.h" #include "lldb/API/SBDebugger.h" @@ -584,14 +585,6 @@ protocol::Source CreateSource(lldb::SBAddress address, lldb::SBTarget &target) { return CreateAssemblySource(target, address); } -protocol::Source CreateSource(llvm::StringRef source_path) { - protocol::Source source; - llvm::StringRef name = llvm::sys::path::filename(source_path); - source.name = name; - source.path = source_path; - return source; -} - // "StackFrame": { // "type": "object", // "description": "A Stackframe contains the source location.", @@ -684,7 +677,7 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, auto target = frame.GetThread().GetProcess().GetTarget(); auto source = CreateSource(frame.GetPCAddress(), target); - if (!source.IsAssemblySource()) { + if (!IsAssemblySource(source)) { // This is a normal source with a valid line entry. auto line_entry = frame.GetLineEntry(); object.try_emplace("line", line_entry.GetLine()); diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h index 3f9b3162ad027..f2a7c20c4e711 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -263,16 +263,6 @@ protocol::Source CreateSource(const lldb::SBFileSpec &file); /// definition outlined by Microsoft. protocol::Source CreateSource(lldb::SBAddress address, lldb::SBTarget &target); -/// Create a "Source" object for a given source path. -/// -/// \param[in] source_path -/// The path to the source to use when creating the "Source" object. -/// -/// \return -/// A "Source" JSON object that follows the formal JSON -/// definition outlined by Microsoft. -protocol::Source CreateSource(llvm::StringRef source_path); - /// Create a "StackFrame" object for a LLDB frame object. /// /// This function will fill in the following keys in the returned diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h index b05b02d7092ea..f5e21c96fe17f 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h @@ -317,8 +317,6 @@ struct Source { std::optional<PresentationHint> presentationHint; // unsupported keys: origin, sources, adapterData, checksums - - bool IsAssemblySource() const { return sourceReference.value_or(0) != 0; } }; bool fromJSON(const llvm::json::Value &, Source::PresentationHint &, llvm::json::Path); diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp new file mode 100644 index 0000000000000..63f16a1a927f3 --- /dev/null +++ b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp @@ -0,0 +1,17 @@ +//===-- ProtocolUtils.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Protocol/ProtocolUtils.h" + +namespace lldb_dap::protocol { + +bool IsAssemblySource(const protocol::Source &source) { + return source.sourceReference.value_or(0) != 0; +} + +} // namespace lldb_dap::protocol diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.h b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.h new file mode 100644 index 0000000000000..a78a0a9ca392b --- /dev/null +++ b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.h @@ -0,0 +1,24 @@ +//===-- ProtocolUtils.h ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains Utility function for protocol objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_UTILS_H +#define LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_UTILS_H + +#include "Protocol/ProtocolTypes.h" + +namespace lldb_dap::protocol { + +bool IsAssemblySource(const protocol::Source &source); + +} // namespace lldb_dap::protocol + +#endif >From e9d2fd00b413ddfa266010f47c2a84120b94affb Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Wed, 28 May 2025 21:51:42 +0200 Subject: [PATCH 4/9] add small GetSymbolContext comment --- lldb/include/lldb/API/SBAddress.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lldb/include/lldb/API/SBAddress.h b/lldb/include/lldb/API/SBAddress.h index c61f02702f1ca..6a1b9b9d40a50 100644 --- a/lldb/include/lldb/API/SBAddress.h +++ b/lldb/include/lldb/API/SBAddress.h @@ -59,6 +59,9 @@ class LLDB_API SBAddress { // "lldb::SBAddress SBTarget::ResolveLoadAddress (...)". lldb::SBSymbolContext GetSymbolContext(uint32_t resolve_scope); + /// Same as the previous function, but uses the given target in the symbol + /// context. This can help to resolve things that require the target, + // for example it's necessary in order to apply source map on SBLineEntry. lldb::SBSymbolContext GetSymbolContext(const SBTarget &target, uint32_t resolve_scope); >From 5968b05cc1e2beeb6c6a73c210f7ef9003cd0ae5 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Thu, 29 May 2025 23:55:12 +0200 Subject: [PATCH 5/9] use existing SBTarget::ResolveSymbolContextForAddress instead of adding new API --- lldb/include/lldb/API/SBAddress.h | 10 ---------- lldb/source/API/SBAddress.cpp | 22 +++------------------- lldb/source/API/SBTarget.cpp | 11 +++++++---- lldb/tools/lldb-dap/LLDBUtils.cpp | 2 +- 4 files changed, 11 insertions(+), 34 deletions(-) diff --git a/lldb/include/lldb/API/SBAddress.h b/lldb/include/lldb/API/SBAddress.h index 6a1b9b9d40a50..430dad4862dbf 100644 --- a/lldb/include/lldb/API/SBAddress.h +++ b/lldb/include/lldb/API/SBAddress.h @@ -11,7 +11,6 @@ #include "lldb/API/SBDefines.h" #include "lldb/API/SBModule.h" -#include "lldb/API/SBTarget.h" namespace lldb { @@ -59,12 +58,6 @@ class LLDB_API SBAddress { // "lldb::SBAddress SBTarget::ResolveLoadAddress (...)". lldb::SBSymbolContext GetSymbolContext(uint32_t resolve_scope); - /// Same as the previous function, but uses the given target in the symbol - /// context. This can help to resolve things that require the target, - // for example it's necessary in order to apply source map on SBLineEntry. - lldb::SBSymbolContext GetSymbolContext(const SBTarget &target, - uint32_t resolve_scope); - // The following functions grab individual objects for a given address and // are less efficient if you want more than one symbol related objects. Use // one of the following when you want multiple debug symbol related objects @@ -129,9 +122,6 @@ class LLDB_API SBAddress { void SetAddress(const lldb_private::Address &address); - void CalculateSymbolContext(lldb_private::SymbolContext &sc, - uint32_t resolve_scope); - private: std::unique_ptr<lldb_private::Address> m_opaque_up; }; diff --git a/lldb/source/API/SBAddress.cpp b/lldb/source/API/SBAddress.cpp index b6b9e238d3cbf..e519f0bcc83c6 100644 --- a/lldb/source/API/SBAddress.cpp +++ b/lldb/source/API/SBAddress.cpp @@ -213,18 +213,9 @@ SBSymbolContext SBAddress::GetSymbolContext(uint32_t resolve_scope) { LLDB_INSTRUMENT_VA(this, resolve_scope); SBSymbolContext sb_sc; - CalculateSymbolContext(sb_sc.ref(), resolve_scope); - return sb_sc; -} - -SBSymbolContext SBAddress::GetSymbolContext(const SBTarget &target, - uint32_t resolve_scope) { - LLDB_INSTRUMENT_VA(this, target, resolve_scope); - - SBSymbolContext sb_sc; - lldb_private::SymbolContext &sc = sb_sc.ref(); - sc.target_sp = target.GetSP(); - CalculateSymbolContext(sc, resolve_scope); + SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope); + if (m_opaque_up->IsValid()) + m_opaque_up->CalculateSymbolContext(&sb_sc.ref(), scope); return sb_sc; } @@ -275,10 +266,3 @@ SBLineEntry SBAddress::GetLineEntry() { } return sb_line_entry; } - -void SBAddress::CalculateSymbolContext(lldb_private::SymbolContext &sc, - uint32_t resolve_scope) { - SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope); - if (m_opaque_up->IsValid()) - m_opaque_up->CalculateSymbolContext(&sc, scope); -} diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 545ffcf5e44e6..f26f7951edc6f 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -636,14 +636,17 @@ SBTarget::ResolveSymbolContextForAddress(const SBAddress &addr, uint32_t resolve_scope) { LLDB_INSTRUMENT_VA(this, addr, resolve_scope); - SBSymbolContext sc; + SBSymbolContext sb_sc; SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope); if (addr.IsValid()) { - if (TargetSP target_sp = GetSP()) + if (TargetSP target_sp = GetSP()) { + lldb_private::SymbolContext &sc = sb_sc.ref(); + sc.target_sp = target_sp; target_sp->GetImages().ResolveSymbolContextForAddress(addr.ref(), scope, - sc.ref()); + sc); + } } - return sc; + return sb_sc; } size_t SBTarget::ReadMemory(const SBAddress addr, void *buf, size_t size, diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp index eb23a89be78da..bcd3308ffbccf 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.cpp +++ b/lldb/tools/lldb-dap/LLDBUtils.cpp @@ -255,7 +255,7 @@ std::string GetSBFileSpecPath(const lldb::SBFileSpec &file_spec) { lldb::SBLineEntry GetLineEntryForAddress(lldb::SBTarget &target, lldb::SBAddress &address) { lldb::SBSymbolContext sc = - address.GetSymbolContext(target, lldb::eSymbolContextLineEntry); + target.ResolveSymbolContextForAddress(address, lldb::eSymbolContextLineEntry); return sc.GetLineEntry(); } >From 1d14ddf89baa1c393289f84b451287b7233709fd Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Fri, 30 May 2025 00:05:49 +0200 Subject: [PATCH 6/9] format --- lldb/tools/lldb-dap/LLDBUtils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp index bcd3308ffbccf..3d3fc433a946b 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.cpp +++ b/lldb/tools/lldb-dap/LLDBUtils.cpp @@ -254,8 +254,8 @@ std::string GetSBFileSpecPath(const lldb::SBFileSpec &file_spec) { lldb::SBLineEntry GetLineEntryForAddress(lldb::SBTarget &target, lldb::SBAddress &address) { - lldb::SBSymbolContext sc = - target.ResolveSymbolContextForAddress(address, lldb::eSymbolContextLineEntry); + lldb::SBSymbolContext sc = target.ResolveSymbolContextForAddress( + address, lldb::eSymbolContextLineEntry); return sc.GetLineEntry(); } >From cd2f8347f6d3e2d1d433a6e16a06d63f11223775 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Fri, 30 May 2025 21:55:52 +0200 Subject: [PATCH 7/9] move CreaetSource function to ProtocolUtils instead of JSONUtils --- lldb/tools/lldb-dap/Breakpoint.cpp | 3 +- .../Handler/DisassembleRequestHandler.cpp | 5 +- .../Handler/LocationsRequestHandler.cpp | 6 +- lldb/tools/lldb-dap/JSONUtils.cpp | 98 +------------------ lldb/tools/lldb-dap/JSONUtils.h | 27 ----- .../tools/lldb-dap/Protocol/ProtocolUtils.cpp | 98 +++++++++++++++++++ lldb/tools/lldb-dap/Protocol/ProtocolUtils.h | 29 ++++++ 7 files changed, 137 insertions(+), 129 deletions(-) diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp index ef9333713e940..1ee4805ec2c8a 100644 --- a/lldb/tools/lldb-dap/Breakpoint.cpp +++ b/lldb/tools/lldb-dap/Breakpoint.cpp @@ -8,7 +8,6 @@ #include "Breakpoint.h" #include "DAP.h" -#include "JSONUtils.h" #include "Protocol/ProtocolUtils.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBBreakpointLocation.h" @@ -65,7 +64,7 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() { "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(m_bp.GetTarget())); breakpoint.instructionReference = formatted_addr; - auto source = CreateSource(bp_addr, m_dap.target); + auto source = protocol::CreateSource(bp_addr, m_dap.target); if (!IsAssemblySource(source)) { auto line_entry = bp_addr.GetLineEntry(); const auto line = line_entry.GetLine(); diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp index 89af4b93120f4..925317e611b08 100644 --- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp @@ -16,6 +16,7 @@ #include "RequestHandler.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBInstruction.h" +#include "lldb/API/SBLineEntry.h" #include "lldb/API/SBTarget.h" #include "lldb/lldb-types.h" #include "llvm/ADT/StringExtras.h" @@ -141,8 +142,8 @@ static DisassembledInstruction ConvertSBInstructionToDisassembledInstruction( disassembled_inst.instruction = std::move(instruction); - auto source = CreateSource(addr, target); - auto line_entry = GetLineEntryForAddress(target, addr); + protocol::Source source = CreateSource(addr, target); + lldb::SBLineEntry line_entry = GetLineEntryForAddress(target, addr); // If the line number is 0 then the entry represents a compiler generated // location. diff --git a/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp index 39ad6949990c7..2b2762f7580f4 100644 --- a/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp @@ -10,6 +10,7 @@ #include "EventHelper.h" #include "JSONUtils.h" #include "LLDBUtils.h" +#include "Protocol/ProtocolUtils.h" #include "RequestHandler.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBDeclaration.h" @@ -136,7 +137,8 @@ void LocationsRequestHandler::operator()( return; } - body.try_emplace("source", CreateSource(line_entry.GetFileSpec())); + body.try_emplace("source", + protocol::CreateSource(line_entry.GetFileSpec())); if (int line = line_entry.GetLine()) body.try_emplace("line", line); if (int column = line_entry.GetColumn()) @@ -151,7 +153,7 @@ void LocationsRequestHandler::operator()( return; } - body.try_emplace("source", CreateSource(decl.GetFileSpec())); + body.try_emplace("source", protocol::CreateSource(decl.GetFileSpec())); if (int line = decl.GetLine()) body.try_emplace("line", line); if (int column = decl.GetColumn()) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index ed9cb0a86a1d2..60d9ec1f87931 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -13,7 +13,6 @@ #include "Protocol/ProtocolUtils.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBCompileUnit.h" -#include "lldb/API/SBDebugger.h" #include "lldb/API/SBDeclaration.h" #include "lldb/API/SBEnvironment.h" #include "lldb/API/SBError.h" @@ -492,99 +491,6 @@ CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp) { return filter; } -static std::string GetLoadAddressString(const lldb::addr_t addr) { - std::string result; - llvm::raw_string_ostream os(result); - os << llvm::format_hex(addr, 18); - return result; -} - -static bool ShouldDisplayAssemblySource( - lldb::SBAddress address, - lldb::StopDisassemblyType stop_disassembly_display) { - if (stop_disassembly_display == lldb::eStopDisassemblyTypeNever) - return false; - - if (stop_disassembly_display == lldb::eStopDisassemblyTypeAlways) - return true; - - // A line entry of 0 indicates the line is compiler generated i.e. no source - // file is associated with the frame. - auto line_entry = address.GetLineEntry(); - 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 == lldb::eStopDisassemblyTypeNoSource && - !file_spec.Exists()) { - return true; - } - - return false; -} - -static protocol::Source CreateAssemblySource(const lldb::SBTarget &target, - lldb::SBAddress address) { - protocol::Source source; - - auto symbol = address.GetSymbol(); - std::string name; - if (symbol.IsValid()) { - source.sourceReference = symbol.GetStartAddress().GetLoadAddress(target); - name = symbol.GetName(); - } else { - const auto load_addr = address.GetLoadAddress(target); - source.sourceReference = load_addr; - name = GetLoadAddressString(load_addr); - } - - lldb::SBModule module = address.GetModule(); - if (module.IsValid()) { - lldb::SBFileSpec file_spec = module.GetFileSpec(); - if (file_spec.IsValid()) { - std::string path = GetSBFileSpecPath(file_spec); - if (!path.empty()) - source.path = path + '`' + name; - } - } - - source.name = std::move(name); - - // Mark the source as deemphasized since users will only be able to view - // assembly for these frames. - source.presentationHint = - protocol::Source::PresentationHint::eSourcePresentationHintDeemphasize; - - return source; -} - -protocol::Source CreateSource(const lldb::SBFileSpec &file) { - protocol::Source source; - if (file.IsValid()) { - const char *name = file.GetFilename(); - if (name) - source.name = name; - char path[PATH_MAX] = ""; - if (file.GetPath(path, sizeof(path)) && - lldb::SBFileSpec::ResolvePath(path, path, PATH_MAX)) - source.path = path; - } - return source; -} - -protocol::Source CreateSource(lldb::SBAddress address, lldb::SBTarget &target) { - lldb::SBDebugger debugger = target.GetDebugger(); - lldb::StopDisassemblyType stop_disassembly_display = - GetStopDisassemblyDisplay(debugger); - if (!ShouldDisplayAssemblySource(address, stop_disassembly_display)) { - lldb::SBLineEntry line_entry = GetLineEntryForAddress(target, address); - return CreateSource(line_entry.GetFileSpec()); - } - - return CreateAssemblySource(target, address); -} - // "StackFrame": { // "type": "object", // "description": "A Stackframe contains the source location.", @@ -666,7 +572,7 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, if (frame_name.empty()) { // If the function name is unavailable, display the pc address as a 16-digit // hex string, e.g. "0x0000000000012345" - frame_name = GetLoadAddressString(frame.GetPC()); + frame_name = protocol::GetLoadAddressString(frame.GetPC()); } // We only include `[opt]` if a custom frame format is not specified. @@ -676,7 +582,7 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, EmplaceSafeString(object, "name", frame_name); auto target = frame.GetThread().GetProcess().GetTarget(); - auto source = CreateSource(frame.GetPCAddress(), target); + auto source = protocol::CreateSource(frame.GetPCAddress(), target); if (!IsAssemblySource(source)) { // This is a normal source with a valid line entry. auto line_entry = frame.GetLineEntry(); diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h index f2a7c20c4e711..08699a94bbd87 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -11,12 +11,8 @@ #include "DAPForward.h" #include "Protocol/ProtocolTypes.h" -#include "lldb/API/SBAddress.h" #include "lldb/API/SBCompileUnit.h" -#include "lldb/API/SBDebugger.h" -#include "lldb/API/SBFileSpec.h" #include "lldb/API/SBFormat.h" -#include "lldb/API/SBLineEntry.h" #include "lldb/API/SBType.h" #include "lldb/API/SBValue.h" #include "lldb/lldb-types.h" @@ -240,29 +236,6 @@ llvm::json::Object CreateEventObject(const llvm::StringRef event_name); protocol::ExceptionBreakpointsFilter CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp); -/// Create a "Source" JSON object as described in the debug adapter definition. -/// -/// \param[in] file -/// The SBFileSpec to use when populating out the "Source" object -/// -/// \return -/// A "Source" JSON object that follows the formal JSON -/// definition outlined by Microsoft. -protocol::Source CreateSource(const lldb::SBFileSpec &file); - -/// Create a "Source" JSON object as described in the debug adapter definition. -/// -/// \param[in] address -/// The address to use when populating out the "Source" object. -/// -/// \param[in] target -/// The target that has the address. -/// -/// \return -/// A "Source" JSON object that follows the formal JSON -/// definition outlined by Microsoft. -protocol::Source CreateSource(lldb::SBAddress address, lldb::SBTarget &target); - /// Create a "StackFrame" object for a LLDB frame object. /// /// This function will fill in the following keys in the returned diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp index 63f16a1a927f3..bcaf666f97eec 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp @@ -7,11 +7,109 @@ //===----------------------------------------------------------------------===// #include "Protocol/ProtocolUtils.h" +#include "LLDBUtils.h" + +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBTarget.h" namespace lldb_dap::protocol { +static bool ShouldDisplayAssemblySource( + lldb::SBAddress address, + lldb::StopDisassemblyType stop_disassembly_display) { + if (stop_disassembly_display == lldb::eStopDisassemblyTypeNever) + return false; + + if (stop_disassembly_display == lldb::eStopDisassemblyTypeAlways) + return true; + + // A line entry of 0 indicates the line is compiler generated i.e. no source + // file is associated with the frame. + auto line_entry = address.GetLineEntry(); + 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 == lldb::eStopDisassemblyTypeNoSource && + !file_spec.Exists()) { + return true; + } + + return false; +} + +static protocol::Source CreateAssemblySource(const lldb::SBTarget &target, + lldb::SBAddress address) { + protocol::Source source; + + auto symbol = address.GetSymbol(); + std::string name; + if (symbol.IsValid()) { + source.sourceReference = symbol.GetStartAddress().GetLoadAddress(target); + name = symbol.GetName(); + } else { + const auto load_addr = address.GetLoadAddress(target); + source.sourceReference = load_addr; + name = GetLoadAddressString(load_addr); + } + + lldb::SBModule module = address.GetModule(); + if (module.IsValid()) { + lldb::SBFileSpec file_spec = module.GetFileSpec(); + if (file_spec.IsValid()) { + std::string path = GetSBFileSpecPath(file_spec); + if (!path.empty()) + source.path = path + '`' + name; + } + } + + source.name = std::move(name); + + // Mark the source as deemphasized since users will only be able to view + // assembly for these frames. + source.presentationHint = + protocol::Source::PresentationHint::eSourcePresentationHintDeemphasize; + + return source; +} + +protocol::Source CreateSource(const lldb::SBFileSpec &file) { + protocol::Source source; + if (file.IsValid()) { + if (const char *name = file.GetFilename()) + source.name = name; + char path[PATH_MAX] = ""; + if (file.GetPath(path, sizeof(path)) && + lldb::SBFileSpec::ResolvePath(path, path, PATH_MAX)) + source.path = path; + } + return source; +} + +protocol::Source CreateSource(lldb::SBAddress address, lldb::SBTarget &target) { + lldb::SBDebugger debugger = target.GetDebugger(); + lldb::StopDisassemblyType stop_disassembly_display = + GetStopDisassemblyDisplay(debugger); + if (ShouldDisplayAssemblySource(address, stop_disassembly_display)) + return CreateAssemblySource(target, address); + + lldb::SBLineEntry line_entry = GetLineEntryForAddress(target, address); + return CreateSource(line_entry.GetFileSpec()); +} + bool IsAssemblySource(const protocol::Source &source) { + // According to the specification, a source must have either `path` or + // `sourceReference` specified. We use `path` for sources with known source + // code, and `sourceReferences` when falling back to assembly. return source.sourceReference.value_or(0) != 0; } +std::string GetLoadAddressString(const lldb::addr_t addr) { + std::string result; + llvm::raw_string_ostream os(result); + os << llvm::format_hex(addr, 18); + return result; +} + } // namespace lldb_dap::protocol diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.h b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.h index a78a0a9ca392b..c66d0f1f3a11c 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.h @@ -15,10 +15,39 @@ #include "Protocol/ProtocolTypes.h" +#include "lldb/API/SBAddress.h" + namespace lldb_dap::protocol { +/// Create a "Source" JSON object as described in the debug adapter definition. +/// +/// \param[in] file +/// The SBFileSpec to use when populating out the "Source" object +/// +/// \return +/// A "Source" JSON object that follows the formal JSON +/// definition outlined by Microsoft. +protocol::Source CreateSource(const lldb::SBFileSpec &file); + +/// Create a "Source" JSON object as described in the debug adapter definition. +/// +/// \param[in] address +/// The address to use when populating out the "Source" object. +/// +/// \param[in] target +/// The target that has the address. +/// +/// \return +/// A "Source" JSON object that follows the formal JSON +/// definition outlined by Microsoft. +protocol::Source CreateSource(lldb::SBAddress address, lldb::SBTarget &target); + +/// Checks if the given source is for assembly code. bool IsAssemblySource(const protocol::Source &source); +/// Get the address as a 16-digit hex string, e.g. "0x0000000000012345" +std::string GetLoadAddressString(const lldb::addr_t addr); + } // namespace lldb_dap::protocol #endif >From 5db2a6e3a3cfe26fb7109744804ab6d91e772bd5 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Fri, 30 May 2025 23:44:15 +0200 Subject: [PATCH 8/9] use reference, move ProtocolUtils.h --- lldb/tools/lldb-dap/Breakpoint.cpp | 4 +- lldb/tools/lldb-dap/CMakeLists.txt | 2 +- .../Handler/DisassembleRequestHandler.cpp | 2 +- .../Handler/LocationsRequestHandler.cpp | 7 +- lldb/tools/lldb-dap/JSONUtils.cpp | 6 +- lldb/tools/lldb-dap/LLDBUtils.cpp | 2 +- lldb/tools/lldb-dap/LLDBUtils.h | 2 +- .../tools/lldb-dap/Protocol/ProtocolUtils.cpp | 7 +- lldb/tools/lldb-dap/ProtocolUtils.cpp | 112 ++++++++++++++++++ .../lldb-dap/{Protocol => }/ProtocolUtils.h | 4 +- 10 files changed, 128 insertions(+), 20 deletions(-) create mode 100644 lldb/tools/lldb-dap/ProtocolUtils.cpp rename lldb/tools/lldb-dap/{Protocol => }/ProtocolUtils.h (96%) diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp index 1ee4805ec2c8a..ef5646c4c3d16 100644 --- a/lldb/tools/lldb-dap/Breakpoint.cpp +++ b/lldb/tools/lldb-dap/Breakpoint.cpp @@ -8,7 +8,7 @@ #include "Breakpoint.h" #include "DAP.h" -#include "Protocol/ProtocolUtils.h" +#include "ProtocolUtils.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBBreakpointLocation.h" #include "lldb/API/SBLineEntry.h" @@ -64,7 +64,7 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() { "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(m_bp.GetTarget())); breakpoint.instructionReference = formatted_addr; - auto source = protocol::CreateSource(bp_addr, m_dap.target); + auto source = CreateSource(bp_addr, m_dap.target); if (!IsAssemblySource(source)) { auto line_entry = bp_addr.GetLineEntry(); const auto line = line_entry.GetLine(); diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt index 401e0672b5375..40cba16c141f0 100644 --- a/lldb/tools/lldb-dap/CMakeLists.txt +++ b/lldb/tools/lldb-dap/CMakeLists.txt @@ -21,6 +21,7 @@ add_lldb_library(lldbDAP LLDBUtils.cpp OutputRedirector.cpp ProgressEvent.cpp + ProtocolUtils.cpp RunInTerminal.cpp SourceBreakpoint.cpp Transport.cpp @@ -68,7 +69,6 @@ add_lldb_library(lldbDAP Protocol/ProtocolBase.cpp Protocol/ProtocolTypes.cpp Protocol/ProtocolRequests.cpp - Protocol/ProtocolUtils.cpp LINK_LIBS liblldb diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp index 925317e611b08..977333f75580a 100644 --- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp @@ -12,7 +12,7 @@ #include "LLDBUtils.h" #include "Protocol/ProtocolRequests.h" #include "Protocol/ProtocolTypes.h" -#include "Protocol/ProtocolUtils.h" +#include "ProtocolUtils.h" #include "RequestHandler.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBInstruction.h" diff --git a/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp index 2b2762f7580f4..804bdcd622a2b 100644 --- a/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/LocationsRequestHandler.cpp @@ -10,7 +10,7 @@ #include "EventHelper.h" #include "JSONUtils.h" #include "LLDBUtils.h" -#include "Protocol/ProtocolUtils.h" +#include "ProtocolUtils.h" #include "RequestHandler.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBDeclaration.h" @@ -137,8 +137,7 @@ void LocationsRequestHandler::operator()( return; } - body.try_emplace("source", - protocol::CreateSource(line_entry.GetFileSpec())); + body.try_emplace("source", CreateSource(line_entry.GetFileSpec())); if (int line = line_entry.GetLine()) body.try_emplace("line", line); if (int column = line_entry.GetColumn()) @@ -153,7 +152,7 @@ void LocationsRequestHandler::operator()( return; } - body.try_emplace("source", protocol::CreateSource(decl.GetFileSpec())); + body.try_emplace("source", CreateSource(decl.GetFileSpec())); if (int line = decl.GetLine()) body.try_emplace("line", line); if (int column = decl.GetColumn()) diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 60d9ec1f87931..573f3eba00f62 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -10,7 +10,7 @@ #include "DAP.h" #include "ExceptionBreakpoint.h" #include "LLDBUtils.h" -#include "Protocol/ProtocolUtils.h" +#include "ProtocolUtils.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBCompileUnit.h" #include "lldb/API/SBDeclaration.h" @@ -572,7 +572,7 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, if (frame_name.empty()) { // If the function name is unavailable, display the pc address as a 16-digit // hex string, e.g. "0x0000000000012345" - frame_name = protocol::GetLoadAddressString(frame.GetPC()); + frame_name = GetLoadAddressString(frame.GetPC()); } // We only include `[opt]` if a custom frame format is not specified. @@ -582,7 +582,7 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame, EmplaceSafeString(object, "name", frame_name); auto target = frame.GetThread().GetProcess().GetTarget(); - auto source = protocol::CreateSource(frame.GetPCAddress(), target); + auto source = CreateSource(frame.GetPCAddress(), target); if (!IsAssemblySource(source)) { // This is a normal source with a valid line entry. auto line_entry = frame.GetLineEntry(); diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp index 3d3fc433a946b..4db6caa1af38b 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.cpp +++ b/lldb/tools/lldb-dap/LLDBUtils.cpp @@ -253,7 +253,7 @@ std::string GetSBFileSpecPath(const lldb::SBFileSpec &file_spec) { } lldb::SBLineEntry GetLineEntryForAddress(lldb::SBTarget &target, - lldb::SBAddress &address) { + const lldb::SBAddress &address) { lldb::SBSymbolContext sc = target.ResolveSymbolContextForAddress( address, lldb::eSymbolContextLineEntry); return sc.GetLineEntry(); diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h index 74c10befdca67..9db721a47ccf7 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.h +++ b/lldb/tools/lldb-dap/LLDBUtils.h @@ -183,7 +183,7 @@ std::string GetSBFileSpecPath(const lldb::SBFileSpec &file_spec); /// \return /// The line entry for the given address. lldb::SBLineEntry GetLineEntryForAddress(lldb::SBTarget &target, - lldb::SBAddress &address); + const lldb::SBAddress &address); /// Helper for sending telemetry to lldb server, if client-telemetry is enabled. class TelemetryDispatcher { diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp index bcaf666f97eec..143c7416bfccd 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolUtils.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "Protocol/ProtocolUtils.h" +#include "ProtocolUtils.h" #include "LLDBUtils.h" #include "lldb/API/SBDebugger.h" @@ -106,10 +106,7 @@ bool IsAssemblySource(const protocol::Source &source) { } std::string GetLoadAddressString(const lldb::addr_t addr) { - std::string result; - llvm::raw_string_ostream os(result); - os << llvm::format_hex(addr, 18); - return result; + return "0x" + llvm::utohexstr(addr); } } // namespace lldb_dap::protocol diff --git a/lldb/tools/lldb-dap/ProtocolUtils.cpp b/lldb/tools/lldb-dap/ProtocolUtils.cpp new file mode 100644 index 0000000000000..9a9f8ba47aa33 --- /dev/null +++ b/lldb/tools/lldb-dap/ProtocolUtils.cpp @@ -0,0 +1,112 @@ +//===-- ProtocolUtils.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ProtocolUtils.h" +#include "LLDBUtils.h" + +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBTarget.h" + +namespace lldb_dap { + +static bool ShouldDisplayAssemblySource( + lldb::SBAddress address, + lldb::StopDisassemblyType stop_disassembly_display) { + if (stop_disassembly_display == lldb::eStopDisassemblyTypeNever) + return false; + + if (stop_disassembly_display == lldb::eStopDisassemblyTypeAlways) + return true; + + // A line entry of 0 indicates the line is compiler generated i.e. no source + // file is associated with the frame. + auto line_entry = address.GetLineEntry(); + 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 == lldb::eStopDisassemblyTypeNoSource && + !file_spec.Exists()) { + return true; + } + + return false; +} + +static protocol::Source CreateAssemblySource(const lldb::SBTarget &target, + lldb::SBAddress address) { + protocol::Source source; + + auto symbol = address.GetSymbol(); + std::string name; + if (symbol.IsValid()) { + source.sourceReference = symbol.GetStartAddress().GetLoadAddress(target); + name = symbol.GetName(); + } else { + const auto load_addr = address.GetLoadAddress(target); + source.sourceReference = load_addr; + name = GetLoadAddressString(load_addr); + } + + lldb::SBModule module = address.GetModule(); + if (module.IsValid()) { + lldb::SBFileSpec file_spec = module.GetFileSpec(); + if (file_spec.IsValid()) { + std::string path = GetSBFileSpecPath(file_spec); + if (!path.empty()) + source.path = path + '`' + name; + } + } + + source.name = std::move(name); + + // Mark the source as deemphasized since users will only be able to view + // assembly for these frames. + source.presentationHint = + protocol::Source::PresentationHint::eSourcePresentationHintDeemphasize; + + return source; +} + +protocol::Source CreateSource(const lldb::SBFileSpec &file) { + protocol::Source source; + if (file.IsValid()) { + if (const char *name = file.GetFilename()) + source.name = name; + char path[PATH_MAX] = ""; + if (file.GetPath(path, sizeof(path)) && + lldb::SBFileSpec::ResolvePath(path, path, PATH_MAX)) + source.path = path; + } + return source; +} + +protocol::Source CreateSource(lldb::SBAddress address, lldb::SBTarget &target) { + lldb::SBDebugger debugger = target.GetDebugger(); + lldb::StopDisassemblyType stop_disassembly_display = + GetStopDisassemblyDisplay(debugger); + if (ShouldDisplayAssemblySource(address, stop_disassembly_display)) + return CreateAssemblySource(target, address); + + lldb::SBLineEntry line_entry = GetLineEntryForAddress(target, address); + return CreateSource(line_entry.GetFileSpec()); +} + +bool IsAssemblySource(const protocol::Source &source) { + // According to the specification, a source must have either `path` or + // `sourceReference` specified. We use `path` for sources with known source + // code, and `sourceReferences` when falling back to assembly. + return source.sourceReference.value_or(0) != 0; +} + +std::string GetLoadAddressString(const lldb::addr_t addr) { + return "0x" + llvm::utohexstr(addr); +} + +} // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.h b/lldb/tools/lldb-dap/ProtocolUtils.h similarity index 96% rename from lldb/tools/lldb-dap/Protocol/ProtocolUtils.h rename to lldb/tools/lldb-dap/ProtocolUtils.h index c66d0f1f3a11c..6e4f07d6e3470 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolUtils.h +++ b/lldb/tools/lldb-dap/ProtocolUtils.h @@ -17,7 +17,7 @@ #include "lldb/API/SBAddress.h" -namespace lldb_dap::protocol { +namespace lldb_dap { /// Create a "Source" JSON object as described in the debug adapter definition. /// @@ -48,6 +48,6 @@ bool IsAssemblySource(const protocol::Source &source); /// Get the address as a 16-digit hex string, e.g. "0x0000000000012345" std::string GetLoadAddressString(const lldb::addr_t addr); -} // namespace lldb_dap::protocol +} // namespace lldb_dap #endif >From 92e8f22c5d626af26061c434aaad08c044ac7b23 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Sat, 31 May 2025 01:02:57 +0200 Subject: [PATCH 9/9] fix hex width --- lldb/tools/lldb-dap/ProtocolUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/tools/lldb-dap/ProtocolUtils.cpp b/lldb/tools/lldb-dap/ProtocolUtils.cpp index 9a9f8ba47aa33..4848d1ecee1aa 100644 --- a/lldb/tools/lldb-dap/ProtocolUtils.cpp +++ b/lldb/tools/lldb-dap/ProtocolUtils.cpp @@ -106,7 +106,7 @@ bool IsAssemblySource(const protocol::Source &source) { } std::string GetLoadAddressString(const lldb::addr_t addr) { - return "0x" + llvm::utohexstr(addr); + return "0x" + llvm::utohexstr(addr, false, 15); } } // namespace lldb_dap _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits