From 9882d688b8431df59bfac598d41796bfe557e73a Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 9 Aug 2025 15:40:53 +0200 Subject: [PATCH 01/44] add DAP gettModuleSymbols request --- lldb/tools/lldb-dap/Handler/RequestHandler.h | 10 ++++++ lldb/tools/lldb-dap/Protocol/DAPTypes.cpp | 30 ++++++++++++++++ lldb/tools/lldb-dap/Protocol/DAPTypes.h | 31 ++++++++++++++++ .../lldb-dap/Protocol/ProtocolRequests.h | 14 ++++++++ lldb/unittests/DAP/CMakeLists.txt | 1 + lldb/unittests/DAP/DAPTypesTest.cpp | 35 +++++++++++++++++++ 6 files changed, 121 insertions(+) create mode 100644 lldb/unittests/DAP/DAPTypesTest.cpp diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index 16f8062f97d7b..b010b6525a8d1 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -594,6 +594,16 @@ class CancelRequestHandler : public RequestHandler> { +public: + using RequestHandler::RequestHandler; + static llvm::StringLiteral GetCommand() { return "dapGetModuleSymbols"; } + llvm::Expected + Run(const protocol::DAPGetModuleSymbolsArguments &args) const override; +}; + /// A request used in testing to get the details on all breakpoints that are /// currently set in the target. This helps us to test "setBreakpoints" and /// "setFunctionBreakpoints" requests to verify we have the correct set of diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp index ecb4baef56e80..1c73328680cdb 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp @@ -33,4 +33,34 @@ llvm::json::Value toJSON(const SourceLLDBData &SLD) { return result; } +bool fromJSON(const llvm::json::Value &Params, DAPSymbol &DS, + llvm::json::Path P) { + json::ObjectMapper O(Params, P); + return O && O.map("userId", DS.userId) && + O.map("isDebug", DS.isDebug) && + O.map("isSynthesized", DS.isSynthesized) && + O.map("isExternal", DS.isExternal) && + O.map("type", DS.type) && + O.map("fileAddress", DS.fileAddress) && + O.mapOptional("loadAddress", DS.loadAddress) && + O.map("size", DS.size) && + O.map("name", DS.name); +} + +llvm::json::Value toJSON(const DAPSymbol &DS) { + json::Object result{ + {"userId", DS.userId}, + {"isDebug", DS.isDebug}, + {"isSynthesized", DS.isSynthesized}, + {"isExternal", DS.isExternal}, + {"type", DS.type}, + {"fileAddress", DS.fileAddress}, + {"loadAddress", DS.loadAddress}, + {"size", DS.size}, + {"name", DS.name}, + }; + + return result; +} + } // namespace lldb_dap::protocol \ No newline at end of file diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.h b/lldb/tools/lldb-dap/Protocol/DAPTypes.h index 716d8b491b258..3f2bec81a0436 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.h +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.h @@ -48,6 +48,37 @@ struct SourceLLDBData { bool fromJSON(const llvm::json::Value &, SourceLLDBData &, llvm::json::Path); llvm::json::Value toJSON(const SourceLLDBData &); +struct DAPSymbol { + /// The symbol uid. + uint32_t userId; + + /// True if this symbol is debug information in a symbol. + bool isDebug; + + /// True if this symbol is not actually in the symbol table, but synthesized from other info in the object file. + bool isSynthesized; + + /// True if this symbol is globally visible. + bool isExternal; + + /// The symbol type. + std::string type; + + /// The symbol file address. + lldb::addr_t fileAddress; + + /// The symbol load address. + std::optional loadAddress; + + /// The symbol size. + lldb::addr_t size; + + /// The symbol name. + std::string name; +}; +bool fromJSON(const llvm::json::Value &, DAPSymbol &, llvm::json::Path); +llvm::json::Value toJSON(const DAPSymbol &); + } // namespace lldb_dap::protocol #endif diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index c45ee10e77d1c..d496433cc02ac 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -981,6 +981,20 @@ struct WriteMemoryResponseBody { }; llvm::json::Value toJSON(const WriteMemoryResponseBody &); +struct DAPGetModuleSymbolsArguments { + /// The module for which to retrieve symbols. + std::string moduleId; +}; +bool fromJSON(const llvm::json::Value &, + DAPGetModuleSymbolsArguments &, llvm::json::Path); + +/// Response to `getModuleSymbols` request. +struct DAPGetModuleSymbolsResponseBody { + /// The symbols for the specified module. + std::vector symbols; +}; +llvm::json::Value toJSON(const DAPGetModuleSymbolsResponseBody &); + } // namespace lldb_dap::protocol #endif diff --git a/lldb/unittests/DAP/CMakeLists.txt b/lldb/unittests/DAP/CMakeLists.txt index 156cd625546bd..716159b454231 100644 --- a/lldb/unittests/DAP/CMakeLists.txt +++ b/lldb/unittests/DAP/CMakeLists.txt @@ -1,6 +1,7 @@ add_lldb_unittest(DAPTests DAPErrorTest.cpp DAPTest.cpp + DAPTypesTest.cpp FifoFilesTest.cpp Handler/DisconnectTest.cpp Handler/ContinueTest.cpp diff --git a/lldb/unittests/DAP/DAPTypesTest.cpp b/lldb/unittests/DAP/DAPTypesTest.cpp new file mode 100644 index 0000000000000..8226fc7660d60 --- /dev/null +++ b/lldb/unittests/DAP/DAPTypesTest.cpp @@ -0,0 +1,35 @@ +//===-- DAPTypesTest.cpp ----------------------------------------*- C++ -*-===// +// +// 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/DAPTypes.h" +#include "TestingSupport/TestUtilities.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/JSON.h" +#include "llvm/Testing/Support/Error.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; +using namespace lldb; +using namespace lldb_dap; +using namespace lldb_dap::protocol; +using lldb_private::roundtripJSON; + +TEST(DAPTypesTest, SourceLLDBData) { + SourceLLDBData source_data; + source_data.persistenceData = PersistenceData{"module_path123", "symbol_name456"}; + + llvm::Expected deserialized_data = roundtripJSON(source_data); + ASSERT_THAT_EXPECTED(deserialized_data, llvm::Succeeded()); + + EXPECT_EQ(source_data.persistenceData->module_path, + deserialized_data->persistenceData->module_path); + EXPECT_EQ(source_data.persistenceData->symbol_name, + deserialized_data->persistenceData->symbol_name); +} From 82430e3a824c816f9c0a30bdebd815e59801410e Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 9 Aug 2025 19:12:09 +0200 Subject: [PATCH 02/44] implement DAPGetModuleSymbolsRequestHandler --- lldb/include/lldb/API/SBSymbol.h | 5 + lldb/include/lldb/API/SBTarget.h | 2 + lldb/source/API/SBSymbol.cpp | 16 ++ lldb/source/API/SBTarget.cpp | 12 ++ lldb/tools/lldb-dap/CMakeLists.txt | 1 + lldb/tools/lldb-dap/DAP.cpp | 1 + .../DAPGetModuleSymbolsRequestHandler.cpp | 146 ++++++++++++++++++ lldb/tools/lldb-dap/Handler/RequestHandler.h | 5 +- lldb/tools/lldb-dap/Protocol/DAPTypes.cpp | 13 +- lldb/tools/lldb-dap/Protocol/DAPTypes.h | 5 +- .../lldb-dap/Protocol/ProtocolRequests.cpp | 13 ++ .../lldb-dap/Protocol/ProtocolRequests.h | 11 +- lldb/unittests/DAP/DAPTypesTest.cpp | 29 +++- 13 files changed, 242 insertions(+), 17 deletions(-) create mode 100644 lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp diff --git a/lldb/include/lldb/API/SBSymbol.h b/lldb/include/lldb/API/SBSymbol.h index 94521881f82f9..6777494bad1d2 100644 --- a/lldb/include/lldb/API/SBSymbol.h +++ b/lldb/include/lldb/API/SBSymbol.h @@ -85,6 +85,8 @@ class LLDB_API SBSymbol { SymbolType GetType(); + uint32_t GetID(); + bool operator==(const lldb::SBSymbol &rhs) const; bool operator!=(const lldb::SBSymbol &rhs) const; @@ -99,6 +101,9 @@ class LLDB_API SBSymbol { // other than the actual symbol table itself in the object file. bool IsSynthetic(); + /// Returns true if the symbol is a debug symbol. + bool IsDebug(); + protected: lldb_private::Symbol *get(); diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 22b6c63ed5b97..90fada3aea4ec 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -324,6 +324,8 @@ class LLDB_API SBTarget { lldb::SBModule FindModule(const lldb::SBFileSpec &file_spec); + lldb::SBModule FindModule(const lldb::SBModuleSpec &module_spec); + /// Find compile units related to *this target and passed source /// file. /// diff --git a/lldb/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp index 79477dd3a70fc..7bcc7f99079c4 100644 --- a/lldb/source/API/SBSymbol.cpp +++ b/lldb/source/API/SBSymbol.cpp @@ -193,6 +193,14 @@ SymbolType SBSymbol::GetType() { return eSymbolTypeInvalid; } +uint32_t SBSymbol::GetID() { + LLDB_INSTRUMENT_VA(this); + + if (m_opaque_ptr) + return m_opaque_ptr->GetID(); + return 0; +} + bool SBSymbol::IsExternal() { LLDB_INSTRUMENT_VA(this); @@ -208,3 +216,11 @@ bool SBSymbol::IsSynthetic() { return m_opaque_ptr->IsSynthetic(); return false; } + +bool SBSymbol::IsDebug() { + LLDB_INSTRUMENT_VA(this); + + if (m_opaque_ptr) + return m_opaque_ptr->IsDebug(); + return false; +} diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 6aa41c52f3731..c761b96135a86 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -1570,6 +1570,18 @@ SBModule SBTarget::FindModule(const SBFileSpec &sb_file_spec) { return sb_module; } +SBModule SBTarget::FindModule(const SBModuleSpec &sb_module_spec) { + LLDB_INSTRUMENT_VA(this, sb_module_spec); + + SBModule sb_module; + if (TargetSP target_sp = GetSP(); target_sp && sb_module_spec.IsValid()) { + // The module list is thread safe, no need to lock + sb_module.SetSP( + target_sp->GetImages().FindFirstModule(*sb_module_spec.m_opaque_up)); + } + return sb_module; +} + SBSymbolContextList SBTarget::FindCompileUnits(const SBFileSpec &sb_file_spec) { LLDB_INSTRUMENT_VA(this, sb_file_spec); diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt index 5e0ad53b82f89..c3ba53754f8ad 100644 --- a/lldb/tools/lldb-dap/CMakeLists.txt +++ b/lldb/tools/lldb-dap/CMakeLists.txt @@ -36,6 +36,7 @@ add_lldb_library(lldbDAP Handler/CompletionsHandler.cpp Handler/ConfigurationDoneRequestHandler.cpp Handler/ContinueRequestHandler.cpp + Handler/DAPGetModuleSymbolsRequestHandler.cpp Handler/DataBreakpointInfoRequestHandler.cpp Handler/DisassembleRequestHandler.cpp Handler/DisconnectRequestHandler.cpp diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index e51ed096073fe..393d977922346 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -1614,6 +1614,7 @@ void DAP::RegisterRequests() { // Custom requests RegisterRequest(); RegisterRequest(); + RegisterRequest(); // Testing requests RegisterRequest(); diff --git a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp new file mode 100644 index 0000000000000..aeea45ee2224d --- /dev/null +++ b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp @@ -0,0 +1,146 @@ +//===-- DAPGetModuleSymbolsRequestHandler.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 "DAP.h" +#include "DAPError.h" +#include "Protocol/DAPTypes.h" +#include "RequestHandler.h" +#include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBModule.h" +#include "lldb/API/SBModuleSpec.h" +#include "lldb/lldb-enumerations.h" +#include "llvm/Support/Error.h" +#include + +using namespace lldb_dap::protocol; +namespace lldb_dap { + +static std::string SymbolTypeToString(lldb::SymbolType symbol_type) { + switch (symbol_type) { + case lldb::eSymbolTypeInvalid: + return "Invalid"; + case lldb::eSymbolTypeAbsolute: + return "Absolute"; + case lldb::eSymbolTypeCode: + return "Code"; + case lldb::eSymbolTypeResolver: + return "Resolver"; + case lldb::eSymbolTypeData: + return "Data"; + case lldb::eSymbolTypeTrampoline: + return "Trampoline"; + case lldb::eSymbolTypeRuntime: + return "Runtime"; + case lldb::eSymbolTypeException: + return "Exception"; + case lldb::eSymbolTypeSourceFile: + return "SourceFile"; + case lldb::eSymbolTypeHeaderFile: + return "HeaderFile"; + case lldb::eSymbolTypeObjectFile: + return "ObjectFile"; + case lldb::eSymbolTypeCommonBlock: + return "CommonBlock"; + case lldb::eSymbolTypeBlock: + return "Block"; + case lldb::eSymbolTypeLocal: + return "Local"; + case lldb::eSymbolTypeParam: + return "Param"; + case lldb::eSymbolTypeVariable: + return "Variable"; + case lldb::eSymbolTypeVariableType: + return "VariableType"; + case lldb::eSymbolTypeLineEntry: + return "LineEntry"; + case lldb::eSymbolTypeLineHeader: + return "LineHeader"; + case lldb::eSymbolTypeScopeBegin: + return "ScopeBegin"; + case lldb::eSymbolTypeScopeEnd: + return "ScopeEnd"; + case lldb::eSymbolTypeAdditional: + return "Additional"; + case lldb::eSymbolTypeCompiler: + return "Compiler"; + case lldb::eSymbolTypeInstrumentation: + return "Instrumentation"; + case lldb::eSymbolTypeUndefined: + return "Undefined"; + case lldb::eSymbolTypeObjCClass: + return "ObjCClass"; + case lldb::eSymbolTypeObjCMetaClass: + return "ObjCMetaClass"; + case lldb::eSymbolTypeObjCIVar: + return "ObjCIVar"; + case lldb::eSymbolTypeReExported: + return "ReExported"; + } + + llvm_unreachable("unhandled symbol type."); +} + +/// Modules can be retrieved from the debug adapter with this request which can +/// either return all modules or a range of modules to support paging. +/// +/// Clients should only call this request if the corresponding capability +/// `supportsModulesRequest` is true. +llvm::Expected +DAPGetModuleSymbolsRequestHandler::Run( + const DAPGetModuleSymbolsArguments &args) const { + DAPGetModuleSymbolsResponseBody response; + + lldb::SBModuleSpec module_spec; + if (args.moduleId) + module_spec.SetUUIDBytes( + reinterpret_cast(args.moduleId->data()), + args.moduleId->size()); + + if (args.moduleName) { + lldb::SBFileSpec file_spec; + file_spec.SetFilename(args.moduleName->c_str()); + module_spec.SetFileSpec(file_spec); + } + + // Empty request, return empty response. + // We use it in the client to check if the lldb-dap server supports this + // request. + if (!module_spec.IsValid()) + return response; + + std::vector &symbols = response.symbols; + lldb::SBModule module = dap.target.FindModule(module_spec); + if (!module.IsValid()) + return llvm::make_error("Module not found"); + + size_t num_symbols = module.GetNumSymbols(); + for (size_t i = 0; i < num_symbols; ++i) { + lldb::SBSymbol symbol = module.GetSymbolAtIndex(i); + if (!symbol.IsValid()) + continue; + + DAPSymbol dap_symbol; + dap_symbol.userId = symbol.GetID(); + dap_symbol.type = SymbolTypeToString(symbol.GetType()); + dap_symbol.isDebug = symbol.IsDebug(); + dap_symbol.isSynthetic = symbol.IsSynthetic(); + dap_symbol.isExternal = symbol.IsExternal(); + + dap_symbol.fileAddress = symbol.GetStartAddress().GetFileAddress(); + dap_symbol.loadAddress = + symbol.GetStartAddress().GetLoadAddress(dap.target); + dap_symbol.size = symbol.GetSize(); + + dap_symbol.name = symbol.GetName(); + symbols.push_back(std::move(dap_symbol)); + } + + return response; +} + +} // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index b010b6525a8d1..e605a8bc1b9f1 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -595,8 +595,9 @@ class CancelRequestHandler : public RequestHandler> { + : public RequestHandler< + protocol::DAPGetModuleSymbolsArguments, + llvm::Expected> { public: using RequestHandler::RequestHandler; static llvm::StringLiteral GetCommand() { return "dapGetModuleSymbols"; } diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp index 1c73328680cdb..212bbd2fe7be6 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp @@ -36,22 +36,19 @@ llvm::json::Value toJSON(const SourceLLDBData &SLD) { bool fromJSON(const llvm::json::Value &Params, DAPSymbol &DS, llvm::json::Path P) { json::ObjectMapper O(Params, P); - return O && O.map("userId", DS.userId) && - O.map("isDebug", DS.isDebug) && - O.map("isSynthesized", DS.isSynthesized) && - O.map("isExternal", DS.isExternal) && - O.map("type", DS.type) && + return O && O.map("userId", DS.userId) && O.map("isDebug", DS.isDebug) && + O.map("isSynthetic", DS.isSynthetic) && + O.map("isExternal", DS.isExternal) && O.map("type", DS.type) && O.map("fileAddress", DS.fileAddress) && O.mapOptional("loadAddress", DS.loadAddress) && - O.map("size", DS.size) && - O.map("name", DS.name); + O.map("size", DS.size) && O.map("name", DS.name); } llvm::json::Value toJSON(const DAPSymbol &DS) { json::Object result{ {"userId", DS.userId}, {"isDebug", DS.isDebug}, - {"isSynthesized", DS.isSynthesized}, + {"isSynthetic", DS.isSynthetic}, {"isExternal", DS.isExternal}, {"type", DS.type}, {"fileAddress", DS.fileAddress}, diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.h b/lldb/tools/lldb-dap/Protocol/DAPTypes.h index 3f2bec81a0436..83f9947b1ab57 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.h +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.h @@ -55,8 +55,9 @@ struct DAPSymbol { /// True if this symbol is debug information in a symbol. bool isDebug; - /// True if this symbol is not actually in the symbol table, but synthesized from other info in the object file. - bool isSynthesized; + /// True if this symbol is not actually in the symbol table, but synthesized + /// from other info in the object file. + bool isSynthetic; /// True if this symbol is globally visible. bool isExternal; diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp index 29855ca50e9e0..e0d49a7d03ce5 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp @@ -598,4 +598,17 @@ json::Value toJSON(const WriteMemoryResponseBody &WMR) { return result; } +bool fromJSON(const llvm::json::Value &Params, + DAPGetModuleSymbolsArguments &Args, llvm::json::Path P) { + json::ObjectMapper O(Params, P); + return O && O.mapOptional("moduleId", Args.moduleId) && + O.mapOptional("moduleName", Args.moduleName); +} + +llvm::json::Value toJSON(const DAPGetModuleSymbolsResponseBody &DGMSR) { + json::Object result; + result.insert({"symbols", DGMSR.symbols}); + return result; +} + } // namespace lldb_dap::protocol diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index d496433cc02ac..ebf58424f6aa4 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -982,11 +982,14 @@ struct WriteMemoryResponseBody { llvm::json::Value toJSON(const WriteMemoryResponseBody &); struct DAPGetModuleSymbolsArguments { - /// The module for which to retrieve symbols. - std::string moduleId; + /// The module UUID for which to retrieve symbols. + std::optional moduleId; + + /// The module path. + std::optional moduleName; }; -bool fromJSON(const llvm::json::Value &, - DAPGetModuleSymbolsArguments &, llvm::json::Path); +bool fromJSON(const llvm::json::Value &, DAPGetModuleSymbolsArguments &, + llvm::json::Path); /// Response to `getModuleSymbols` request. struct DAPGetModuleSymbolsResponseBody { diff --git a/lldb/unittests/DAP/DAPTypesTest.cpp b/lldb/unittests/DAP/DAPTypesTest.cpp index 8226fc7660d60..180917364b0e2 100644 --- a/lldb/unittests/DAP/DAPTypesTest.cpp +++ b/lldb/unittests/DAP/DAPTypesTest.cpp @@ -23,7 +23,8 @@ using lldb_private::roundtripJSON; TEST(DAPTypesTest, SourceLLDBData) { SourceLLDBData source_data; - source_data.persistenceData = PersistenceData{"module_path123", "symbol_name456"}; + source_data.persistenceData = + PersistenceData{"module_path123", "symbol_name456"}; llvm::Expected deserialized_data = roundtripJSON(source_data); ASSERT_THAT_EXPECTED(deserialized_data, llvm::Succeeded()); @@ -33,3 +34,29 @@ TEST(DAPTypesTest, SourceLLDBData) { EXPECT_EQ(source_data.persistenceData->symbol_name, deserialized_data->persistenceData->symbol_name); } + +TEST(DAPTypesTest, DAPSymbol) { + DAPSymbol symbol; + symbol.userId = 42; + symbol.isDebug = true; + symbol.isExternal = false; + symbol.isSynthetic = true; + symbol.type = "Trampoline"; + symbol.fileAddress = 0x12345678; + symbol.loadAddress = 0x87654321; + symbol.size = 64; + symbol.name = "testSymbol"; + + llvm::Expected deserialized_symbol = roundtripJSON(symbol); + ASSERT_THAT_EXPECTED(deserialized_symbol, llvm::Succeeded()); + + EXPECT_EQ(symbol.userId, deserialized_symbol->userId); + EXPECT_EQ(symbol.isDebug, deserialized_symbol->isDebug); + EXPECT_EQ(symbol.isExternal, deserialized_symbol->isExternal); + EXPECT_EQ(symbol.isSynthetic, deserialized_symbol->isSynthetic); + EXPECT_EQ(symbol.type, deserialized_symbol->type); + EXPECT_EQ(symbol.fileAddress, deserialized_symbol->fileAddress); + EXPECT_EQ(symbol.loadAddress, deserialized_symbol->loadAddress); + EXPECT_EQ(symbol.size, deserialized_symbol->size); + EXPECT_EQ(symbol.name, deserialized_symbol->name); +} From 5496e202e2f0e52fcd6be0827259052df067daf3 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Mon, 11 Aug 2025 01:25:15 +0200 Subject: [PATCH 03/44] adding lldb-dap.modules.showSymbols to the commandPallette --- .../DAPGetModuleSymbolsRequestHandler.cpp | 12 +- lldb/tools/lldb-dap/package.json | 9 ++ lldb/tools/lldb-dap/src-ts/extension.ts | 7 +- .../lldb-dap/src-ts/ui/symbols-provider.ts | 133 ++++++++++++++++++ 4 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts diff --git a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp index aeea45ee2224d..d502897027993 100644 --- a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp @@ -13,6 +13,7 @@ #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBModule.h" #include "lldb/API/SBModuleSpec.h" +#include "lldb/Utility/UUID.h" #include "lldb/lldb-enumerations.h" #include "llvm/Support/Error.h" #include @@ -96,10 +97,15 @@ DAPGetModuleSymbolsRequestHandler::Run( DAPGetModuleSymbolsResponseBody response; lldb::SBModuleSpec module_spec; - if (args.moduleId) + if (args.moduleId) { + llvm::SmallVector uuid_bytes; + if (!lldb_private::UUID::DecodeUUIDBytesFromString(*args.moduleId, uuid_bytes).empty()) + return llvm::make_error("Invalid module ID"); + module_spec.SetUUIDBytes( - reinterpret_cast(args.moduleId->data()), - args.moduleId->size()); + uuid_bytes.data(), + uuid_bytes.size()); + } if (args.moduleName) { lldb::SBFileSpec file_spec; diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index d677a81cc7974..b93fd732d93ab 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -259,6 +259,11 @@ { "command": "lldb-dap.modules.copyProperty", "title": "Copy Value" + }, + { + "category": "lldb-dap", + "command": "lldb-dap.modules.showSymbols", + "title": "Show Module Symbols" } ], "menus": { @@ -266,6 +271,10 @@ { "command": "lldb-dap.modules.copyProperty", "when": "false" + }, + { + "command": "lldb-dap.modules.showSymbols", + "when": "debuggersAvailable && debugType == 'lldb-dap'" } ], "view/item/context": [ diff --git a/lldb/tools/lldb-dap/src-ts/extension.ts b/lldb/tools/lldb-dap/src-ts/extension.ts index 4b7a35e6944c6..a54831b5a4025 100644 --- a/lldb/tools/lldb-dap/src-ts/extension.ts +++ b/lldb/tools/lldb-dap/src-ts/extension.ts @@ -12,6 +12,7 @@ import { ModuleProperty, } from "./ui/modules-data-provider"; import { LogFilePathProvider } from "./logging"; +import { SymbolsProvider } from "./ui/symbols-provider"; /** * This class represents the extension and manages its life cycle. Other extensions @@ -52,10 +53,12 @@ export class LLDBDapExtension extends DisposableContext { vscode.window.registerUriHandler(new LaunchUriHandler()), ); - vscode.commands.registerCommand( + this.pushSubscription(vscode.commands.registerCommand( "lldb-dap.modules.copyProperty", (node: ModuleProperty) => vscode.env.clipboard.writeText(node.value), - ); + )); + + this.pushSubscription(new SymbolsProvider(sessionTracker)); } } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts new file mode 100644 index 0000000000000..28fe59e15e484 --- /dev/null +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -0,0 +1,133 @@ +import * as vscode from "vscode"; +import { DebugProtocol } from "@vscode/debugprotocol"; + +import { DebugSessionTracker } from "../debug-session-tracker"; +import { DisposableContext } from "../disposable-context"; + +export class SymbolsProvider extends DisposableContext { + constructor(private readonly tracker: DebugSessionTracker) { + super(); + + this.pushSubscription(vscode.commands.registerCommand( + "lldb-dap.modules.showSymbols", + () => { + this.SelectModuleAndShowSymbols(); + }, + )); + } + + static async doesServerSupportSymbolsRequest(session: vscode.DebugSession): Promise { + try { + const dummyArguments = { _dummy: true }; + const _result = await session.customRequest("dapGetModuleSymbols", dummyArguments); + return true; + } catch (_error) { + return false; + } + } + + private async SelectModuleAndShowSymbols() { + const session = vscode.debug.activeDebugSession; + if (!session) { + return; + } + + if (!await SymbolsProvider.doesServerSupportSymbolsRequest(session)) { + vscode.window.showErrorMessage("The debug adapter does not support symbol requests."); + return; + } + + const modules = this.tracker.debugSessionModules(session); + if (!modules || modules.length === 0) { + return; + } + + // Let the user select a module to show symbols for + const selectedModule = await vscode.window.showQuickPick(modules.map(m => new ModuleQuickPickItem(m)), { + placeHolder: "Select a module to show symbols for" + }); + if (!selectedModule) { + return; + } + + let symbols = []; + try { + symbols = await this.getSymbolsForModule(session, selectedModule.module.id.toString()); + this.showSymbolsForModule(selectedModule.module.name.toString(), symbols); + } catch (error) { + if (error instanceof Error) { + vscode.window.showErrorMessage("Failed to retrieve symbols: " + error.message); + } else { + vscode.window.showErrorMessage("Failed to retrieve symbols due to an unknown error."); + } + + return; + } + + this.showSymbolsForModule(selectedModule.module.name.toString(), symbols); + } + + private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { + console.log(`Getting symbols for module: ${moduleId}`); + const symbols_response: { symbols: Array } = await session.customRequest("dapGetModuleSymbols", { moduleId }); + + + return symbols_response?.symbols.map(symbol => new DAPSymbol( + symbol.userId, + symbol.isDebug, + symbol.isSynthetic, + symbol.isExternal, + symbol.type, + symbol.fileAddress, + symbol.loadAddress, + symbol.size, + symbol.name, + )) || []; + } + + private showSymbolsForModule(moduleName: string, symbols: DAPSymbol[]) { + console.log(`Showing symbols for module: ${moduleName}`); + symbols.forEach(symbol => { + console.log(` - ${symbol.name} (${symbol.type})`); + }); + } +} + +class ModuleQuickPickItem implements vscode.QuickPickItem { + constructor(public readonly module: DebugProtocol.Module) {} + + get label(): string { + return this.module.name; + } + + get description(): string { + return this.module.id.toString(); + } +} + +/// The symbol type we get from the lldb-dap server +type DAPSymbolType = { + userId: number; + isDebug: boolean; + isSynthetic: boolean; + isExternal: boolean; + type: string; + fileAddress: number; + loadAddress?: number; + size: number; + name: string; +}; + +class DAPSymbol { + constructor( + public readonly userId: number, + public readonly isDebug: boolean, + public readonly isSynthetic: boolean, + public readonly isExternal: boolean, + public readonly type: string, + public readonly fileAddress: number, + public readonly loadAddress: number | undefined, + public readonly size: number, + public readonly name: string, + ) {} +} From b5ee84e962ccc296f17ab05f0c6657e2e74121b0 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Mon, 11 Aug 2025 01:34:58 +0200 Subject: [PATCH 04/44] basic HTML for symbols webview --- .../lldb-dap/src-ts/ui/symbols-provider.ts | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 28fe59e15e484..9c2f0c7799efe 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -50,9 +50,8 @@ export class SymbolsProvider extends DisposableContext { return; } - let symbols = []; try { - symbols = await this.getSymbolsForModule(session, selectedModule.module.id.toString()); + const symbols = await this.getSymbolsForModule(session, selectedModule.module.id.toString()); this.showSymbolsForModule(selectedModule.module.name.toString(), symbols); } catch (error) { if (error instanceof Error) { @@ -63,8 +62,6 @@ export class SymbolsProvider extends DisposableContext { return; } - - this.showSymbolsForModule(selectedModule.module.name.toString(), symbols); } private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { @@ -85,11 +82,20 @@ export class SymbolsProvider extends DisposableContext { )) || []; } - private showSymbolsForModule(moduleName: string, symbols: DAPSymbol[]) { - console.log(`Showing symbols for module: ${moduleName}`); - symbols.forEach(symbol => { - console.log(` - ${symbol.name} (${symbol.type})`); - }); + private async showSymbolsForModule(moduleName: string, symbols: DAPSymbol[]) { + const panel = vscode.window.createWebviewPanel( + "lldb-dap.symbols", + `Symbols for ${moduleName}`, + vscode.ViewColumn.Active, + {} + ); + + panel.webview.html = SymbolsProvider.getHTMLContentForSymbols(moduleName, symbols); + } + + private static getHTMLContentForSymbols(moduleName: string, symbols: DAPSymbol[]): string { + const symbolLines = symbols.map(symbol => ` - ${symbol.name} (${symbol.type})`); + return `Symbols for module: ${moduleName}\n${symbolLines.join("\n")}`; } } From 9f17c74d93817e4a99b66e06517db6d2f0759bab Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Tue, 12 Aug 2025 00:56:52 +0200 Subject: [PATCH 05/44] show symbols in a simple tabulator table --- lldb/tools/lldb-dap/package-lock.json | 12 +++- lldb/tools/lldb-dap/package.json | 6 +- lldb/tools/lldb-dap/src-ts/extension.ts | 5 +- .../lldb-dap/src-ts/ui/symbols-provider.ts | 59 +++++++++++++++++-- 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/lldb/tools/lldb-dap/package-lock.json b/lldb/tools/lldb-dap/package-lock.json index 1969b196accc6..a3dd8e0dd5142 100644 --- a/lldb/tools/lldb-dap/package-lock.json +++ b/lldb/tools/lldb-dap/package-lock.json @@ -1,12 +1,12 @@ { "name": "lldb-dap", - "version": "0.2.15", + "version": "0.2.16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lldb-dap", - "version": "0.2.15", + "version": "0.2.16", "license": "Apache 2.0 License with LLVM exceptions", "devDependencies": { "@types/node": "^18.19.41", @@ -15,6 +15,7 @@ "@vscode/vsce": "^3.2.2", "prettier": "^3.4.2", "prettier-plugin-curly": "^0.3.1", + "tabulator-tables": "^6.3.1", "typescript": "^5.7.3" }, "engines": { @@ -2557,6 +2558,13 @@ "node": ">=4" } }, + "node_modules/tabulator-tables": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-6.3.1.tgz", + "integrity": "sha512-qFW7kfadtcaISQIibKAIy0f3eeIXUVi8242Vly1iJfMD79kfEGzfczNuPBN/80hDxHzQJXYbmJ8VipI40hQtfA==", + "dev": true, + "license": "MIT" + }, "node_modules/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index b93fd732d93ab..3c7c5c288fc55 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -34,6 +34,7 @@ "@vscode/vsce": "^3.2.2", "prettier": "^3.4.2", "prettier-plugin-curly": "^0.3.1", + "tabulator-tables": "^6.3.1", "typescript": "^5.7.3" }, "activationEvents": [ @@ -42,8 +43,9 @@ ], "main": "./out/extension", "scripts": { - "vscode:prepublish": "tsc -p ./", - "watch": "tsc -watch -p ./", + "bundle-assets": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/ && cp node_modules/tabulator-tables/dist/css/tabulator.min.css ./out/", + "vscode:prepublish": "npm run bundle-assets && tsc -p ./", + "watch": "npm run bundle-assets && tsc -watch -p ./", "format": "npx prettier './src-ts/' --write", "package": "rm -rf ./out/lldb-dap.vsix && vsce package --out ./out/lldb-dap.vsix", "publish": "vsce publish", diff --git a/lldb/tools/lldb-dap/src-ts/extension.ts b/lldb/tools/lldb-dap/src-ts/extension.ts index a54831b5a4025..7119cba972fa4 100644 --- a/lldb/tools/lldb-dap/src-ts/extension.ts +++ b/lldb/tools/lldb-dap/src-ts/extension.ts @@ -20,6 +20,7 @@ import { SymbolsProvider } from "./ui/symbols-provider"; */ export class LLDBDapExtension extends DisposableContext { constructor( + context: vscode.ExtensionContext, logger: vscode.LogOutputChannel, logFilePath: LogFilePathProvider, outputChannel: vscode.OutputChannel, @@ -58,7 +59,7 @@ export class LLDBDapExtension extends DisposableContext { (node: ModuleProperty) => vscode.env.clipboard.writeText(node.value), )); - this.pushSubscription(new SymbolsProvider(sessionTracker)); + this.pushSubscription(new SymbolsProvider(sessionTracker, context)); } } @@ -70,7 +71,7 @@ export async function activate(context: vscode.ExtensionContext) { outputChannel.info("LLDB-DAP extension activating..."); const logFilePath = new LogFilePathProvider(context, outputChannel); context.subscriptions.push( - new LLDBDapExtension(outputChannel, logFilePath, outputChannel), + new LLDBDapExtension(context, outputChannel, logFilePath, outputChannel), ); outputChannel.info("LLDB-DAP extension activated"); } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 9c2f0c7799efe..d82d1a68c5001 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -5,7 +5,10 @@ import { DebugSessionTracker } from "../debug-session-tracker"; import { DisposableContext } from "../disposable-context"; export class SymbolsProvider extends DisposableContext { - constructor(private readonly tracker: DebugSessionTracker) { + constructor( + private readonly tracker: DebugSessionTracker, + private readonly extensionContext: vscode.ExtensionContext, + ) { super(); this.pushSubscription(vscode.commands.registerCommand( @@ -87,15 +90,59 @@ export class SymbolsProvider extends DisposableContext { "lldb-dap.symbols", `Symbols for ${moduleName}`, vscode.ViewColumn.Active, - {} + { + enableScripts: true, + localResourceRoots: [ + this.getExtensionResourcePath() + ] + } ); - panel.webview.html = SymbolsProvider.getHTMLContentForSymbols(moduleName, symbols); + const tabulatorJsPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.js")); + const tabulatorCssPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.css")); + + panel.webview.html = this.getHTMLContentForSymbols(tabulatorJsPath, tabulatorCssPath, symbols); + } + + private getHTMLContentForSymbols(tabulatorJsPath: vscode.Uri, tabulatorCssPath: vscode.Uri, symbols: DAPSymbol[]): string { + const dataJson = JSON.stringify(symbols); + return ` + + + + + + + +
+ + + +`; } - private static getHTMLContentForSymbols(moduleName: string, symbols: DAPSymbol[]): string { - const symbolLines = symbols.map(symbol => ` - ${symbol.name} (${symbol.type})`); - return `Symbols for module: ${moduleName}\n${symbolLines.join("\n")}`; + private getExtensionResourcePath(): vscode.Uri { + return vscode.Uri.joinPath(this.extensionContext.extensionUri, "out"); } } From bf6309ae3878f8f66fde74b6582978c79a6b6805 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Wed, 13 Aug 2025 09:55:15 +0200 Subject: [PATCH 06/44] split symbols webview script to a new ts directory --- lldb/tools/lldb-dap/package-lock.json | 8 +++ lldb/tools/lldb-dap/package.json | 7 +-- .../src-ts-webview/symbols-table-view.ts | 52 +++++++++++++++++++ .../lldb-dap/src-ts-webview/tsconfig.json | 10 ++++ .../tools/lldb-dap/{ => src-ts}/tsconfig.json | 9 ++-- .../lldb-dap/src-ts/ui/symbols-provider.ts | 28 +++------- 6 files changed, 85 insertions(+), 29 deletions(-) create mode 100644 lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts create mode 100644 lldb/tools/lldb-dap/src-ts-webview/tsconfig.json rename lldb/tools/lldb-dap/{ => src-ts}/tsconfig.json (58%) diff --git a/lldb/tools/lldb-dap/package-lock.json b/lldb/tools/lldb-dap/package-lock.json index a3dd8e0dd5142..b419b1589b85a 100644 --- a/lldb/tools/lldb-dap/package-lock.json +++ b/lldb/tools/lldb-dap/package-lock.json @@ -10,6 +10,7 @@ "license": "Apache 2.0 License with LLVM exceptions", "devDependencies": { "@types/node": "^18.19.41", + "@types/tabulator-tables": "^6.2.10", "@types/vscode": "1.75.0", "@vscode/debugprotocol": "^1.68.0", "@vscode/vsce": "^3.2.2", @@ -400,6 +401,13 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/tabulator-tables": { + "version": "6.2.10", + "resolved": "https://registry.npmjs.org/@types/tabulator-tables/-/tabulator-tables-6.2.10.tgz", + "integrity": "sha512-g6o0gG3lu/ozmxPw9rLY1p57T6rvV8OhbJKyzWwPwjdnN3JuSQ3gWxb06v2+dl2tdoqNXTvlylipSSKpS8UzzQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/vscode": { "version": "1.75.0", "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.0.tgz", diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index 3c7c5c288fc55..9e3b215adea35 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -29,6 +29,7 @@ ], "devDependencies": { "@types/node": "^18.19.41", + "@types/tabulator-tables": "^6.2.10", "@types/vscode": "1.75.0", "@vscode/debugprotocol": "^1.68.0", "@vscode/vsce": "^3.2.2", @@ -43,9 +44,9 @@ ], "main": "./out/extension", "scripts": { - "bundle-assets": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/ && cp node_modules/tabulator-tables/dist/css/tabulator.min.css ./out/", - "vscode:prepublish": "npm run bundle-assets && tsc -p ./", - "watch": "npm run bundle-assets && tsc -watch -p ./", + "bundle-webview": "tsc -p ./src-ts-webview/ && cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator.min.css ./out/webview/", + "vscode:prepublish": "npm run bundle-webview && tsc -p ./src-ts/", + "watch": "npm run bundle-webview && tsc -watch -p ./src-ts/", "format": "npx prettier './src-ts/' --write", "package": "rm -rf ./out/lldb-dap.vsix && vsce package --out ./out/lldb-dap.vsix", "publish": "vsce publish", diff --git a/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts new file mode 100644 index 0000000000000..75f62d5f68d6b --- /dev/null +++ b/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts @@ -0,0 +1,52 @@ +import type { ColumnDefinition } from "tabulator-tables"; + +const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ + { title: "User ID", field: "userId", sorter: "number" }, + { title: "Debug", field: "isDebug", sorter: "boolean" }, + { title: "Synthetic", field: "isSynthetic", sorter: "boolean" }, + { title: "External", field: "isExternal", sorter: "boolean" }, + { title: "Type", field: "type", sorter: "string" }, + { + title: "File Address", + field: "fileAddress", + sorter: "number", + formatter: cell => "0x" + cell.getValue().toString(16).toUpperCase() + }, + { + title: "Load Address", + field: "loadAddress", + sorter: "number", + formatter: cell => { + const val = cell.getValue(); + return val !== undefined ? "0x" + val.toString(16).toUpperCase() : ""; + } + }, + { title: "Size", field: "size", sorter: "number" }, + { + title: "Name", + field: "name", + sorter: "string", + widthGrow: 2, + minWidth: 200 + } +] + +console.log("FUCK"); +console.log("Symbols table columns:", SYMBOL_TABLE_COLUMNS); + +declare const Tabulator: any; // HACK: real definition comes from tabulator.min.js +const SYMBOLS_TABLE = new Tabulator("#symbols-table", { + columns: SYMBOL_TABLE_COLUMNS, + layout: "fitData", + data: [], +}); + +window.addEventListener("message", (event: MessageEvent) => { + const message = event.data; + switch (message.type) { + case "updateSymbols": + SYMBOLS_TABLE.setData(message.symbols); + break; + } +}); + diff --git a/lldb/tools/lldb-dap/src-ts-webview/tsconfig.json b/lldb/tools/lldb-dap/src-ts-webview/tsconfig.json new file mode 100644 index 0000000000000..2ba15e79be4f7 --- /dev/null +++ b/lldb/tools/lldb-dap/src-ts-webview/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "module": "ESNext", + "target": "ESNext", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "outDir": "../out/webview" + }, + "include": ["./**/*"] +} diff --git a/lldb/tools/lldb-dap/tsconfig.json b/lldb/tools/lldb-dap/src-ts/tsconfig.json similarity index 58% rename from lldb/tools/lldb-dap/tsconfig.json rename to lldb/tools/lldb-dap/src-ts/tsconfig.json index 2092148888904..04b74ae0d90fd 100644 --- a/lldb/tools/lldb-dap/tsconfig.json +++ b/lldb/tools/lldb-dap/src-ts/tsconfig.json @@ -1,16 +1,17 @@ { "compilerOptions": { + "moduleResolution": "node", "module": "commonjs", - "outDir": "out", - "rootDir": "src-ts", + "outDir": "../out", + "rootDir": ".", "sourceMap": true, "strict": true, "target": "es6" }, "include": [ - "src-ts" + "./**/*" ], "exclude": [ - "node_modules", + "../node_modules", ] } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index d82d1a68c5001..bb1fe5a29d83f 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -100,12 +100,13 @@ export class SymbolsProvider extends DisposableContext { const tabulatorJsPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.js")); const tabulatorCssPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.css")); + const symbolsTableScriptPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "symbols-table-view.js")); - panel.webview.html = this.getHTMLContentForSymbols(tabulatorJsPath, tabulatorCssPath, symbols); + panel.webview.html = this.getHTMLContentForSymbols(tabulatorJsPath, tabulatorCssPath, symbolsTableScriptPath, symbols); + panel.webview.postMessage({ command: "setSymbols", symbols: symbols }); } - private getHTMLContentForSymbols(tabulatorJsPath: vscode.Uri, tabulatorCssPath: vscode.Uri, symbols: DAPSymbol[]): string { - const dataJson = JSON.stringify(symbols); + private getHTMLContentForSymbols(tabulatorJsPath: vscode.Uri, tabulatorCssPath: vscode.Uri, symbolsTableScriptPath: vscode.Uri, symbols: DAPSymbol[]): string { return ` @@ -119,30 +120,13 @@ export class SymbolsProvider extends DisposableContext {
- + `; } private getExtensionResourcePath(): vscode.Uri { - return vscode.Uri.joinPath(this.extensionContext.extensionUri, "out"); + return vscode.Uri.joinPath(this.extensionContext.extensionUri, "out", "webview"); } } From c37369f80d790506ea5e5f5f43b6be624d471c2a Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Thu, 14 Aug 2025 22:59:10 +0200 Subject: [PATCH 07/44] working symbol table white default theme --- lldb/tools/lldb-dap/package-lock.json | 485 ++++++++++++++++++ lldb/tools/lldb-dap/package.json | 5 +- .../src-ts-webview/symbols-table-view.ts | 9 +- .../lldb-dap/src-ts/ui/symbols-provider.ts | 2 +- 4 files changed, 494 insertions(+), 7 deletions(-) diff --git a/lldb/tools/lldb-dap/package-lock.json b/lldb/tools/lldb-dap/package-lock.json index b419b1589b85a..38c477d73fa7d 100644 --- a/lldb/tools/lldb-dap/package-lock.json +++ b/lldb/tools/lldb-dap/package-lock.json @@ -14,6 +14,7 @@ "@types/vscode": "1.75.0", "@vscode/debugprotocol": "^1.68.0", "@vscode/vsce": "^3.2.2", + "esbuild": "^0.25.9", "prettier": "^3.4.2", "prettier-plugin-curly": "^0.3.1", "tabulator-tables": "^6.3.1", @@ -320,6 +321,448 @@ "node": ">=6.9.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1178,6 +1621,48 @@ "node": ">= 0.4" } }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index 9e3b215adea35..a3c7650636778 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -33,6 +33,7 @@ "@types/vscode": "1.75.0", "@vscode/debugprotocol": "^1.68.0", "@vscode/vsce": "^3.2.2", + "esbuild": "^0.25.9", "prettier": "^3.4.2", "prettier-plugin-curly": "^0.3.1", "tabulator-tables": "^6.3.1", @@ -44,7 +45,9 @@ ], "main": "./out/extension", "scripts": { - "bundle-webview": "tsc -p ./src-ts-webview/ && cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator.min.css ./out/webview/", + "bundle-symbols-table-view": "npx esbuild src-ts-webview/symbols-table-view.ts --bundle --format=iife --outdir=./out/webview", + "bundle-tabulator": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator.min.css ./out/webview/", + "bundle-webview": "npm run bundle-symbols-table-view && npm run bundle-tabulator", "vscode:prepublish": "npm run bundle-webview && tsc -p ./src-ts/", "watch": "npm run bundle-webview && tsc -watch -p ./src-ts/", "format": "npx prettier './src-ts/' --write", diff --git a/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts index 75f62d5f68d6b..38effc196ac32 100644 --- a/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts @@ -31,20 +31,19 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ } ] -console.log("FUCK"); -console.log("Symbols table columns:", SYMBOL_TABLE_COLUMNS); - declare const Tabulator: any; // HACK: real definition comes from tabulator.min.js -const SYMBOLS_TABLE = new Tabulator("#symbols-table", { +const SYMBOLS_TABLE = new Tabulator("#table", { columns: SYMBOL_TABLE_COLUMNS, layout: "fitData", data: [], }); window.addEventListener("message", (event: MessageEvent) => { + console.log("FUCK1"); const message = event.data; - switch (message.type) { + switch (message.command) { case "updateSymbols": + console.log("Received symbols update:", message.symbols); SYMBOLS_TABLE.setData(message.symbols); break; } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index bb1fe5a29d83f..cd9879778f27f 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -103,7 +103,7 @@ export class SymbolsProvider extends DisposableContext { const symbolsTableScriptPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "symbols-table-view.js")); panel.webview.html = this.getHTMLContentForSymbols(tabulatorJsPath, tabulatorCssPath, symbolsTableScriptPath, symbols); - panel.webview.postMessage({ command: "setSymbols", symbols: symbols }); + panel.webview.postMessage({ command: "updateSymbols", symbols: symbols }); } private getHTMLContentForSymbols(tabulatorJsPath: vscode.Uri, tabulatorCssPath: vscode.Uri, symbolsTableScriptPath: vscode.Uri, symbols: DAPSymbol[]): string { From e76bb2f7c8ab64c611ab580c2fed8df2c145876b Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 00:13:12 +0200 Subject: [PATCH 08/44] common formatter --- .../lldb-dap/src-ts-webview/symbols-table-view.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts index 38effc196ac32..9e0da64b95c8b 100644 --- a/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts @@ -1,4 +1,9 @@ -import type { ColumnDefinition } from "tabulator-tables"; +import type { CellComponent, ColumnDefinition } from "tabulator-tables"; + +const TABULATOR_HEXA_FORMATTER = (cell: CellComponent) => { + const val = cell.getValue(); + return val !== undefined ? "0x" + val.toString(16).toUpperCase() : ""; +}; const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ { title: "User ID", field: "userId", sorter: "number" }, @@ -10,16 +15,13 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ title: "File Address", field: "fileAddress", sorter: "number", - formatter: cell => "0x" + cell.getValue().toString(16).toUpperCase() + formatter: TABULATOR_HEXA_FORMATTER, }, { title: "Load Address", field: "loadAddress", sorter: "number", - formatter: cell => { - const val = cell.getValue(); - return val !== undefined ? "0x" + val.toString(16).toUpperCase() : ""; - } + formatter: TABULATOR_HEXA_FORMATTER, }, { title: "Size", field: "size", sorter: "number" }, { From 738962f0e1f56da89f46dd3cbba04d193f2ce404 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 00:17:47 +0200 Subject: [PATCH 09/44] restore ts files to src-ts --- lldb/tools/lldb-dap/package.json | 2 +- lldb/tools/lldb-dap/src-ts-webview/tsconfig.json | 10 ---------- .../webview}/symbols-table-view.ts | 0 lldb/tools/lldb-dap/{src-ts => }/tsconfig.json | 9 +++++---- 4 files changed, 6 insertions(+), 15 deletions(-) delete mode 100644 lldb/tools/lldb-dap/src-ts-webview/tsconfig.json rename lldb/tools/lldb-dap/{src-ts-webview => src-ts/webview}/symbols-table-view.ts (100%) rename lldb/tools/lldb-dap/{src-ts => }/tsconfig.json (65%) diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index a3c7650636778..031a80941d9b8 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -45,7 +45,7 @@ ], "main": "./out/extension", "scripts": { - "bundle-symbols-table-view": "npx esbuild src-ts-webview/symbols-table-view.ts --bundle --format=iife --outdir=./out/webview", + "bundle-symbols-table-view": "npx esbuild src-ts/webview/symbols-table-view.ts --bundle --format=iife --outdir=./out/webview", "bundle-tabulator": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator.min.css ./out/webview/", "bundle-webview": "npm run bundle-symbols-table-view && npm run bundle-tabulator", "vscode:prepublish": "npm run bundle-webview && tsc -p ./src-ts/", diff --git a/lldb/tools/lldb-dap/src-ts-webview/tsconfig.json b/lldb/tools/lldb-dap/src-ts-webview/tsconfig.json deleted file mode 100644 index 2ba15e79be4f7..0000000000000 --- a/lldb/tools/lldb-dap/src-ts-webview/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "moduleResolution": "node", - "module": "ESNext", - "target": "ESNext", - "lib": ["ESNext", "DOM", "DOM.Iterable"], - "outDir": "../out/webview" - }, - "include": ["./**/*"] -} diff --git a/lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts similarity index 100% rename from lldb/tools/lldb-dap/src-ts-webview/symbols-table-view.ts rename to lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts diff --git a/lldb/tools/lldb-dap/src-ts/tsconfig.json b/lldb/tools/lldb-dap/tsconfig.json similarity index 65% rename from lldb/tools/lldb-dap/src-ts/tsconfig.json rename to lldb/tools/lldb-dap/tsconfig.json index 04b74ae0d90fd..06a484a1fc263 100644 --- a/lldb/tools/lldb-dap/src-ts/tsconfig.json +++ b/lldb/tools/lldb-dap/tsconfig.json @@ -2,16 +2,17 @@ "compilerOptions": { "moduleResolution": "node", "module": "commonjs", - "outDir": "../out", - "rootDir": ".", + "outDir": "out", + "rootDir": "src-ts", "sourceMap": true, "strict": true, "target": "es6" }, "include": [ - "./**/*" + "src-ts" ], "exclude": [ - "../node_modules", + "node_modules", + "src-ts/webview", ] } From de3ee14d12f98e3400c27a64a753b6706e58e7c7 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 11:09:27 +0200 Subject: [PATCH 10/44] fit table columns to viewport --- lldb/tools/lldb-dap/package.json | 4 +- .../lldb-dap/src-ts/ui/symbols-provider.ts | 22 ++----- .../src-ts/webview/symbols-table-view.ts | 65 ++++++++++++------- 3 files changed, 50 insertions(+), 41 deletions(-) diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index 031a80941d9b8..76e78281888d0 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -48,8 +48,8 @@ "bundle-symbols-table-view": "npx esbuild src-ts/webview/symbols-table-view.ts --bundle --format=iife --outdir=./out/webview", "bundle-tabulator": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator.min.css ./out/webview/", "bundle-webview": "npm run bundle-symbols-table-view && npm run bundle-tabulator", - "vscode:prepublish": "npm run bundle-webview && tsc -p ./src-ts/", - "watch": "npm run bundle-webview && tsc -watch -p ./src-ts/", + "vscode:prepublish": "npm run bundle-webview && tsc -p ./", + "watch": "npm run bundle-webview && tsc -watch -p ./", "format": "npx prettier './src-ts/' --write", "package": "rm -rf ./out/lldb-dap.vsix && vsce package --out ./out/lldb-dap.vsix", "publish": "vsce publish", diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index cd9879778f27f..41637c32350ce 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -4,6 +4,8 @@ import { DebugProtocol } from "@vscode/debugprotocol"; import { DebugSessionTracker } from "../debug-session-tracker"; import { DisposableContext } from "../disposable-context"; +import { DAPSymbolType } from ".."; + export class SymbolsProvider extends DisposableContext { constructor( private readonly tracker: DebugSessionTracker, @@ -22,7 +24,7 @@ export class SymbolsProvider extends DisposableContext { static async doesServerSupportSymbolsRequest(session: vscode.DebugSession): Promise { try { const dummyArguments = { _dummy: true }; - const _result = await session.customRequest("dapGetModuleSymbols", dummyArguments); + await session.customRequest("dapGetModuleSymbols", dummyArguments); return true; } catch (_error) { return false; @@ -113,12 +115,11 @@ export class SymbolsProvider extends DisposableContext { -
+
@@ -142,19 +143,6 @@ class ModuleQuickPickItem implements vscode.QuickPickItem { } } -/// The symbol type we get from the lldb-dap server -type DAPSymbolType = { - userId: number; - isDebug: boolean; - isSynthetic: boolean; - isExternal: boolean; - type: string; - fileAddress: number; - loadAddress?: number; - size: number; - name: string; -}; - class DAPSymbol { constructor( public readonly userId: number, diff --git a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts index 9e0da64b95c8b..b5609b6d3292e 100644 --- a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts @@ -1,52 +1,73 @@ import type { CellComponent, ColumnDefinition } from "tabulator-tables"; +import type { DAPSymbolType } from ".." -const TABULATOR_HEXA_FORMATTER = (cell: CellComponent) => { - const val = cell.getValue(); - return val !== undefined ? "0x" + val.toString(16).toUpperCase() : ""; -}; +function get_tabulator_hexa_formatter(padding: number): (cell: CellComponent) => string { + return (cell: CellComponent) => { + const val = cell.getValue(); + return val !== undefined ? "0x" + val.toString(16).toLowerCase().padStart(padding, "0") : ""; + }; +} const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ { title: "User ID", field: "userId", sorter: "number" }, - { title: "Debug", field: "isDebug", sorter: "boolean" }, - { title: "Synthetic", field: "isSynthetic", sorter: "boolean" }, - { title: "External", field: "isExternal", sorter: "boolean" }, + { + title: "Name", + field: "name", + sorter: "string", + widthGrow: 2, + minWidth: 200, + }, + { + title: "DSX", + hozAlign: "center", + formatter: (cell: CellComponent) => { + const rowData = cell.getRow().getData(); + let label = ""; + label += rowData.isDebug ? "D" : ""; + label += rowData.isSynthetic ? "S" : ""; + label += rowData.isExternal ? "X" : ""; + return label; + }, + sorter: (_a, _b, aRow, bRow) => { + const valuesA = [aRow.getData().isDebug, aRow.getData().isSynthetic, aRow.getData().isExternal]; + const valuesB = [bRow.getData().isDebug, bRow.getData().isSynthetic, bRow.getData().isExternal]; + + return valuesA < valuesB ? -1 : valuesA > valuesB ? 1 : 0; + } + }, { title: "Type", field: "type", sorter: "string" }, { title: "File Address", field: "fileAddress", sorter: "number", - formatter: TABULATOR_HEXA_FORMATTER, + formatter: get_tabulator_hexa_formatter(16), }, { title: "Load Address", field: "loadAddress", sorter: "number", - formatter: TABULATOR_HEXA_FORMATTER, + formatter: get_tabulator_hexa_formatter(16), }, - { title: "Size", field: "size", sorter: "number" }, - { - title: "Name", - field: "name", - sorter: "string", - widthGrow: 2, - minWidth: 200 - } + { title: "Size", field: "size", sorter: "number", formatter: get_tabulator_hexa_formatter(8) }, ] declare const Tabulator: any; // HACK: real definition comes from tabulator.min.js -const SYMBOLS_TABLE = new Tabulator("#table", { +const SYMBOLS_TABLE = new Tabulator("#symbols-table", { + height: "100vh", columns: SYMBOL_TABLE_COLUMNS, - layout: "fitData", + layout: "fitColumns", data: [], }); +function updateSymbolsTable(symbols: DAPSymbolType[]) { + SYMBOLS_TABLE.setData(symbols); +} + window.addEventListener("message", (event: MessageEvent) => { - console.log("FUCK1"); const message = event.data; switch (message.command) { case "updateSymbols": - console.log("Received symbols update:", message.symbols); - SYMBOLS_TABLE.setData(message.symbols); + updateSymbolsTable(message.symbols); break; } }); From f16d15bdfac86c9cdae5067f62eefd1e142d0c1b Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 11:25:48 +0200 Subject: [PATCH 11/44] make table data restore after switching tabs --- lldb/tools/lldb-dap/package-lock.json | 8 ++++++++ lldb/tools/lldb-dap/package.json | 1 + lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts | 6 +++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lldb/tools/lldb-dap/package-lock.json b/lldb/tools/lldb-dap/package-lock.json index 38c477d73fa7d..26db1ce6df2fd 100644 --- a/lldb/tools/lldb-dap/package-lock.json +++ b/lldb/tools/lldb-dap/package-lock.json @@ -12,6 +12,7 @@ "@types/node": "^18.19.41", "@types/tabulator-tables": "^6.2.10", "@types/vscode": "1.75.0", + "@types/vscode-webview": "^1.57.5", "@vscode/debugprotocol": "^1.68.0", "@vscode/vsce": "^3.2.2", "esbuild": "^0.25.9", @@ -858,6 +859,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/vscode-webview": { + "version": "1.57.5", + "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.5.tgz", + "integrity": "sha512-iBAUYNYkz+uk1kdsq05fEcoh8gJmwT3lqqFPN7MGyjQ3HVloViMdo7ZJ8DFIP8WOK74PjOEilosqAyxV2iUFUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@vscode/debugprotocol": { "version": "1.68.0", "resolved": "https://registry.npmjs.org/@vscode/debugprotocol/-/debugprotocol-1.68.0.tgz", diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index 76e78281888d0..47d1213d45211 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -31,6 +31,7 @@ "@types/node": "^18.19.41", "@types/tabulator-tables": "^6.2.10", "@types/vscode": "1.75.0", + "@types/vscode-webview": "^1.57.5", "@vscode/debugprotocol": "^1.68.0", "@vscode/vsce": "^3.2.2", "esbuild": "^0.25.9", diff --git a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts index b5609b6d3292e..6c85dc8b52a52 100644 --- a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts @@ -51,12 +51,15 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ { title: "Size", field: "size", sorter: "number", formatter: get_tabulator_hexa_formatter(8) }, ] +const vscode = acquireVsCodeApi(); +const previousState: any = vscode.getState(); + declare const Tabulator: any; // HACK: real definition comes from tabulator.min.js const SYMBOLS_TABLE = new Tabulator("#symbols-table", { height: "100vh", columns: SYMBOL_TABLE_COLUMNS, layout: "fitColumns", - data: [], + data: previousState?.symbols || [], }); function updateSymbolsTable(symbols: DAPSymbolType[]) { @@ -67,6 +70,7 @@ window.addEventListener("message", (event: MessageEvent) => { const message = event.data; switch (message.command) { case "updateSymbols": + vscode.setState({ symbols: message.symbols }); updateSymbolsTable(message.symbols); break; } From 262875c0216881db2ff048879cca3c21bcfa23d6 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 14:36:00 +0200 Subject: [PATCH 12/44] attempt have tabulator with vscode css variables --- lldb/tools/lldb-dap/package.json | 2 +- lldb/tools/lldb-dap/src-ts/index.d.ts | 14 ++++++++ .../lldb-dap/src-ts/ui/symbols-provider.ts | 33 +++++++++++++++++-- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 lldb/tools/lldb-dap/src-ts/index.d.ts diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index 47d1213d45211..a0f144c39ea55 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -47,7 +47,7 @@ "main": "./out/extension", "scripts": { "bundle-symbols-table-view": "npx esbuild src-ts/webview/symbols-table-view.ts --bundle --format=iife --outdir=./out/webview", - "bundle-tabulator": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator.min.css ./out/webview/", + "bundle-tabulator": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_midnight.min.css ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_modern.min.css ./out/webview/", "bundle-webview": "npm run bundle-symbols-table-view && npm run bundle-tabulator", "vscode:prepublish": "npm run bundle-webview && tsc -p ./", "watch": "npm run bundle-webview && tsc -watch -p ./", diff --git a/lldb/tools/lldb-dap/src-ts/index.d.ts b/lldb/tools/lldb-dap/src-ts/index.d.ts new file mode 100644 index 0000000000000..cd5359d039619 --- /dev/null +++ b/lldb/tools/lldb-dap/src-ts/index.d.ts @@ -0,0 +1,14 @@ +export {}; + +/// The symbol type we get from the lldb-dap server +export type DAPSymbolType = { + userId: number; + isDebug: boolean; + isSynthetic: boolean; + isExternal: boolean; + type: string; + fileAddress: number; + loadAddress?: number; + size: number; + name: string; +}; diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 41637c32350ce..5314a4789d6f9 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -100,8 +100,12 @@ export class SymbolsProvider extends DisposableContext { } ); + let tabulatorJsFilename = "tabulator_modern.min.css"; + if (vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.Dark || vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.HighContrast) { + tabulatorJsFilename = "tabulator_midnight.min.css"; + } + const tabulatorCssPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), tabulatorJsFilename)); const tabulatorJsPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.js")); - const tabulatorCssPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.css")); const symbolsTableScriptPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "symbols-table-view.js")); panel.webview.html = this.getHTMLContentForSymbols(tabulatorJsPath, tabulatorCssPath, symbolsTableScriptPath, symbols); @@ -115,7 +119,32 @@ export class SymbolsProvider extends DisposableContext { From e65178e32ee4a13403fc15b14ab57b7c421dc2d9 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 15:05:32 +0200 Subject: [PATCH 13/44] better looking CSS with tabulator --- lldb/tools/lldb-dap/package.json | 2 +- lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index a0f144c39ea55..d894070a512c8 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -47,7 +47,7 @@ "main": "./out/extension", "scripts": { "bundle-symbols-table-view": "npx esbuild src-ts/webview/symbols-table-view.ts --bundle --format=iife --outdir=./out/webview", - "bundle-tabulator": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_midnight.min.css ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_modern.min.css ./out/webview/", + "bundle-tabulator": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_midnight.min.css ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_simple.min.css ./out/webview/", "bundle-webview": "npm run bundle-symbols-table-view && npm run bundle-tabulator", "vscode:prepublish": "npm run bundle-webview && tsc -p ./", "watch": "npm run bundle-webview && tsc -watch -p ./", diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 5314a4789d6f9..55938bc8195c2 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -100,7 +100,7 @@ export class SymbolsProvider extends DisposableContext { } ); - let tabulatorJsFilename = "tabulator_modern.min.css"; + let tabulatorJsFilename = "tabulator_simple.min.css"; if (vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.Dark || vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.HighContrast) { tabulatorJsFilename = "tabulator_midnight.min.css"; } @@ -124,17 +124,19 @@ export class SymbolsProvider extends DisposableContext { color: var(--vscode-editor-foreground); } - .tabulator .tabulator-header { + .tabulator .tabulator-header .tabulator-col { background-color: var(--vscode-editor-background); color: var(--vscode-editor-foreground); } .tabulator-row { background-color: var(--vscode-editor-background); + color: var(--vscode-editor-foreground); } - .tabulator.tabulator-row-even { - background-color: var(--vscode-tree-tableOddRowsBackground); + .tabulator-row.tabulator-row-even { + background-color: var(--vscode-editor-background); + color: var(--vscode-editor-foreground); } .tabulator-row.tabulator-selected { From ae212886e104c6daa2d3635181db31391c05ee7f Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 16:00:33 +0200 Subject: [PATCH 14/44] remove ellipsis if text is long --- lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts | 4 ++++ lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 55938bc8195c2..f8fc3e8910c27 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -144,6 +144,10 @@ export class SymbolsProvider extends DisposableContext { color: var(--vscode-editor-foreground); } + .tabulator-cell { + text-overflow: clip !important; + } + #symbols-table { height: 100vh; } diff --git a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts index 6c85dc8b52a52..c574222fe9b0f 100644 --- a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts @@ -9,7 +9,7 @@ function get_tabulator_hexa_formatter(padding: number): (cell: CellComponent) => } const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ - { title: "User ID", field: "userId", sorter: "number" }, + { title: "User ID", field: "userId", sorter: "number", widthShrink: 2 }, { title: "Name", field: "name", @@ -20,6 +20,7 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ { title: "DSX", hozAlign: "center", + widthShrink: 2, formatter: (cell: CellComponent) => { const rowData = cell.getRow().getData(); let label = ""; @@ -58,7 +59,7 @@ declare const Tabulator: any; // HACK: real definition comes from tabulator.min. const SYMBOLS_TABLE = new Tabulator("#symbols-table", { height: "100vh", columns: SYMBOL_TABLE_COLUMNS, - layout: "fitColumns", + layout: "fitDataFill", data: previousState?.symbols || [], }); From 023c7fa3e8b32ecd93009f64197496ee6a468bcb Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 17:18:11 +0200 Subject: [PATCH 15/44] few fixes --- .../DAPGetModuleSymbolsRequestHandler.cpp | 16 ++- .../lldb-dap/src-ts/ui/symbols-provider.ts | 5 +- .../src-ts/webview/symbols-table-view.ts | 115 +++++++++++------- 3 files changed, 84 insertions(+), 52 deletions(-) diff --git a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp index d502897027993..334ab4f2d9b1e 100644 --- a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp @@ -10,6 +10,7 @@ #include "DAPError.h" #include "Protocol/DAPTypes.h" #include "RequestHandler.h" +#include "lldb/API/SBAddress.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBModule.h" #include "lldb/API/SBModuleSpec.h" @@ -137,11 +138,18 @@ DAPGetModuleSymbolsRequestHandler::Run( dap_symbol.isSynthetic = symbol.IsSynthetic(); dap_symbol.isExternal = symbol.IsExternal(); - dap_symbol.fileAddress = symbol.GetStartAddress().GetFileAddress(); - dap_symbol.loadAddress = - symbol.GetStartAddress().GetLoadAddress(dap.target); - dap_symbol.size = symbol.GetSize(); + lldb::SBAddress start_address = symbol.GetStartAddress(); + if (start_address.IsValid()) { + lldb::addr_t file_address = start_address.GetFileAddress(); + if (file_address != LLDB_INVALID_ADDRESS) + dap_symbol.fileAddress = file_address; + + lldb::addr_t load_address = start_address.GetLoadAddress(dap.target); + if (load_address != LLDB_INVALID_ADDRESS) + dap_symbol.loadAddress = load_address; + } + dap_symbol.size = symbol.GetSize(); dap_symbol.name = symbol.GetName(); symbols.push_back(std::move(dap_symbol)); } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index f8fc3e8910c27..0446e6273fb0e 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -148,8 +148,9 @@ export class SymbolsProvider extends DisposableContext { text-overflow: clip !important; } - #symbols-table { - height: 100vh; + #symbols-table { + width: 100%; + height: 100vh; } diff --git a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts index c574222fe9b0f..fac1e56ca5d94 100644 --- a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts @@ -4,63 +4,86 @@ import type { DAPSymbolType } from ".." function get_tabulator_hexa_formatter(padding: number): (cell: CellComponent) => string { return (cell: CellComponent) => { const val = cell.getValue(); - return val !== undefined ? "0x" + val.toString(16).toLowerCase().padStart(padding, "0") : ""; + if (val === undefined || val === null) { + return ""; + } + + return "0x" + val.toString(16).toLowerCase().padStart(padding, "0"); }; } -const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ - { title: "User ID", field: "userId", sorter: "number", widthShrink: 2 }, - { - title: "Name", - field: "name", - sorter: "string", - widthGrow: 2, - minWidth: 200, - }, - { - title: "DSX", - hozAlign: "center", - widthShrink: 2, - formatter: (cell: CellComponent) => { - const rowData = cell.getRow().getData(); - let label = ""; - label += rowData.isDebug ? "D" : ""; - label += rowData.isSynthetic ? "S" : ""; - label += rowData.isExternal ? "X" : ""; - return label; +const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = + [ + {title : "User ID", field : "userId", sorter : "number", widthGrow : 0.8}, + { + title : "Name", + field : "name", + sorter : "string", + widthGrow : 3, + minWidth : 200, + tooltip : (_event: MouseEvent, cell: CellComponent) => { + const rowData = cell.getRow().getData(); + return rowData.name; + } + }, + { + title : "DSX", + hozAlign : "center", + widthGrow : 0.8, + headerTooltip : "Debug / Synthetic / External", + formatter : (cell: CellComponent) => { + const rowData = cell.getRow().getData(); + let label = ""; + label += rowData.isDebug ? "D" : ""; + label += rowData.isSynthetic ? "S" : ""; + label += rowData.isExternal ? "X" : ""; + return label; }, - sorter: (_a, _b, aRow, bRow) => { - const valuesA = [aRow.getData().isDebug, aRow.getData().isSynthetic, aRow.getData().isExternal]; - const valuesB = [bRow.getData().isDebug, bRow.getData().isSynthetic, bRow.getData().isExternal]; + sorter : (_a, _b, aRow, bRow) => { + const valuesA = [ + aRow.getData().isDebug, aRow.getData().isSynthetic, + aRow.getData().isExternal + ]; + const valuesB = [ + bRow.getData().isDebug, bRow.getData().isSynthetic, + bRow.getData().isExternal + ]; - return valuesA < valuesB ? -1 : valuesA > valuesB ? 1 : 0; + return valuesA < valuesB ? -1 : valuesA > valuesB ? 1 : 0; } - }, - { title: "Type", field: "type", sorter: "string" }, - { - title: "File Address", - field: "fileAddress", - sorter: "number", - formatter: get_tabulator_hexa_formatter(16), - }, - { - title: "Load Address", - field: "loadAddress", - sorter: "number", - formatter: get_tabulator_hexa_formatter(16), - }, - { title: "Size", field: "size", sorter: "number", formatter: get_tabulator_hexa_formatter(8) }, -] + }, + {title : "Type", field : "type", sorter : "string"}, + { + title : "File Address", + field : "fileAddress", + sorter : "number", + widthGrow : 1.25, + formatter : get_tabulator_hexa_formatter(16), + }, + { + title : "Load Address", + field : "loadAddress", + sorter : "number", + widthGrow : 1.25, + formatter : get_tabulator_hexa_formatter(16), + }, + { + title : "Size", + field : "size", + sorter : "number", + formatter : get_tabulator_hexa_formatter(8) + }, + ] -const vscode = acquireVsCodeApi(); + const vscode = acquireVsCodeApi(); const previousState: any = vscode.getState(); declare const Tabulator: any; // HACK: real definition comes from tabulator.min.js const SYMBOLS_TABLE = new Tabulator("#symbols-table", { - height: "100vh", - columns: SYMBOL_TABLE_COLUMNS, - layout: "fitDataFill", - data: previousState?.symbols || [], + height : "100vh", + columns : SYMBOL_TABLE_COLUMNS, + layout : "fitColumns", + data : previousState?.symbols || [], }); function updateSymbolsTable(symbols: DAPSymbolType[]) { From bab7e016aae32188047ad868668cabfb0171cd46 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 17:30:01 +0200 Subject: [PATCH 16/44] revert --- .../src-ts/webview/symbols-table-view.ts | 115 +++++++----------- 1 file changed, 46 insertions(+), 69 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts index fac1e56ca5d94..c574222fe9b0f 100644 --- a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts @@ -4,86 +4,63 @@ import type { DAPSymbolType } from ".." function get_tabulator_hexa_formatter(padding: number): (cell: CellComponent) => string { return (cell: CellComponent) => { const val = cell.getValue(); - if (val === undefined || val === null) { - return ""; - } - - return "0x" + val.toString(16).toLowerCase().padStart(padding, "0"); + return val !== undefined ? "0x" + val.toString(16).toLowerCase().padStart(padding, "0") : ""; }; } -const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = - [ - {title : "User ID", field : "userId", sorter : "number", widthGrow : 0.8}, - { - title : "Name", - field : "name", - sorter : "string", - widthGrow : 3, - minWidth : 200, - tooltip : (_event: MouseEvent, cell: CellComponent) => { - const rowData = cell.getRow().getData(); - return rowData.name; - } - }, - { - title : "DSX", - hozAlign : "center", - widthGrow : 0.8, - headerTooltip : "Debug / Synthetic / External", - formatter : (cell: CellComponent) => { - const rowData = cell.getRow().getData(); - let label = ""; - label += rowData.isDebug ? "D" : ""; - label += rowData.isSynthetic ? "S" : ""; - label += rowData.isExternal ? "X" : ""; - return label; +const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ + { title: "User ID", field: "userId", sorter: "number", widthShrink: 2 }, + { + title: "Name", + field: "name", + sorter: "string", + widthGrow: 2, + minWidth: 200, + }, + { + title: "DSX", + hozAlign: "center", + widthShrink: 2, + formatter: (cell: CellComponent) => { + const rowData = cell.getRow().getData(); + let label = ""; + label += rowData.isDebug ? "D" : ""; + label += rowData.isSynthetic ? "S" : ""; + label += rowData.isExternal ? "X" : ""; + return label; }, - sorter : (_a, _b, aRow, bRow) => { - const valuesA = [ - aRow.getData().isDebug, aRow.getData().isSynthetic, - aRow.getData().isExternal - ]; - const valuesB = [ - bRow.getData().isDebug, bRow.getData().isSynthetic, - bRow.getData().isExternal - ]; + sorter: (_a, _b, aRow, bRow) => { + const valuesA = [aRow.getData().isDebug, aRow.getData().isSynthetic, aRow.getData().isExternal]; + const valuesB = [bRow.getData().isDebug, bRow.getData().isSynthetic, bRow.getData().isExternal]; - return valuesA < valuesB ? -1 : valuesA > valuesB ? 1 : 0; + return valuesA < valuesB ? -1 : valuesA > valuesB ? 1 : 0; } - }, - {title : "Type", field : "type", sorter : "string"}, - { - title : "File Address", - field : "fileAddress", - sorter : "number", - widthGrow : 1.25, - formatter : get_tabulator_hexa_formatter(16), - }, - { - title : "Load Address", - field : "loadAddress", - sorter : "number", - widthGrow : 1.25, - formatter : get_tabulator_hexa_formatter(16), - }, - { - title : "Size", - field : "size", - sorter : "number", - formatter : get_tabulator_hexa_formatter(8) - }, - ] + }, + { title: "Type", field: "type", sorter: "string" }, + { + title: "File Address", + field: "fileAddress", + sorter: "number", + formatter: get_tabulator_hexa_formatter(16), + }, + { + title: "Load Address", + field: "loadAddress", + sorter: "number", + formatter: get_tabulator_hexa_formatter(16), + }, + { title: "Size", field: "size", sorter: "number", formatter: get_tabulator_hexa_formatter(8) }, +] - const vscode = acquireVsCodeApi(); +const vscode = acquireVsCodeApi(); const previousState: any = vscode.getState(); declare const Tabulator: any; // HACK: real definition comes from tabulator.min.js const SYMBOLS_TABLE = new Tabulator("#symbols-table", { - height : "100vh", - columns : SYMBOL_TABLE_COLUMNS, - layout : "fitColumns", - data : previousState?.symbols || [], + height: "100vh", + columns: SYMBOL_TABLE_COLUMNS, + layout: "fitDataFill", + data: previousState?.symbols || [], }); function updateSymbolsTable(symbols: DAPSymbolType[]) { From 2e48fdb6e03a6caebdc992de0db115be5ad1c48d Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 17:33:50 +0200 Subject: [PATCH 17/44] table improvements --- .../src-ts/webview/symbols-table-view.ts | 123 ++++++++++-------- 1 file changed, 67 insertions(+), 56 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts index c574222fe9b0f..de39723497309 100644 --- a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts @@ -2,78 +2,89 @@ import type { CellComponent, ColumnDefinition } from "tabulator-tables"; import type { DAPSymbolType } from ".." function get_tabulator_hexa_formatter(padding: number): (cell: CellComponent) => string { - return (cell: CellComponent) => { - const val = cell.getValue(); - return val !== undefined ? "0x" + val.toString(16).toLowerCase().padStart(padding, "0") : ""; - }; + return (cell: CellComponent) => { + const val = cell.getValue(); + if (val === undefined || val === null) { + return ""; + } + + return val !== undefined ? "0x" + val.toString(16).toLowerCase().padStart(padding, "0") : ""; + }; } const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ - { title: "User ID", field: "userId", sorter: "number", widthShrink: 2 }, - { - title: "Name", - field: "name", - sorter: "string", - widthGrow: 2, - minWidth: 200, + { title: "User ID", field: "userId", sorter: "number", widthGrow: 0.8 }, + { + title: "Name", + field: "name", + sorter: "string", + widthGrow: 3, + minWidth: 200, + tooltip : (_event: MouseEvent, cell: CellComponent) => { + const rowData = cell.getRow().getData(); + return rowData.name; + } + }, + { + title: "DSX", + hozAlign: "center", + widthGrow: 0.8, + headerTooltip : "Debug / Synthetic / External", + formatter: (cell: CellComponent) => { + const rowData = cell.getRow().getData(); + let label = ""; + label += rowData.isDebug ? "D" : ""; + label += rowData.isSynthetic ? "S" : ""; + label += rowData.isExternal ? "X" : ""; + return label; }, - { - title: "DSX", - hozAlign: "center", - widthShrink: 2, - formatter: (cell: CellComponent) => { - const rowData = cell.getRow().getData(); - let label = ""; - label += rowData.isDebug ? "D" : ""; - label += rowData.isSynthetic ? "S" : ""; - label += rowData.isExternal ? "X" : ""; - return label; - }, - sorter: (_a, _b, aRow, bRow) => { - const valuesA = [aRow.getData().isDebug, aRow.getData().isSynthetic, aRow.getData().isExternal]; - const valuesB = [bRow.getData().isDebug, bRow.getData().isSynthetic, bRow.getData().isExternal]; + sorter: (_a, _b, aRow, bRow) => { + const valuesA = [aRow.getData().isDebug, aRow.getData().isSynthetic, aRow.getData().isExternal]; + const valuesB = [bRow.getData().isDebug, bRow.getData().isSynthetic, bRow.getData().isExternal]; - return valuesA < valuesB ? -1 : valuesA > valuesB ? 1 : 0; - } - }, - { title: "Type", field: "type", sorter: "string" }, - { - title: "File Address", - field: "fileAddress", - sorter: "number", - formatter: get_tabulator_hexa_formatter(16), - }, - { - title: "Load Address", - field: "loadAddress", - sorter: "number", - formatter: get_tabulator_hexa_formatter(16), - }, - { title: "Size", field: "size", sorter: "number", formatter: get_tabulator_hexa_formatter(8) }, -] + return valuesA < valuesB ? -1 : valuesA > valuesB ? 1 : 0; + } + }, + { title: "Type", field: "type", sorter: "string" }, + { + title: "File Address", + field: "fileAddress", + sorter: "number", + widthGrow : 1.25, + formatter: get_tabulator_hexa_formatter(16), + }, + { + title: "Load Address", + field: "loadAddress", + sorter: "number", + widthGrow : 1.25, + formatter: get_tabulator_hexa_formatter(16), + }, + { title: "Size", field: "size", sorter: "number", formatter: get_tabulator_hexa_formatter(8) }, +]; const vscode = acquireVsCodeApi(); const previousState: any = vscode.getState(); declare const Tabulator: any; // HACK: real definition comes from tabulator.min.js const SYMBOLS_TABLE = new Tabulator("#symbols-table", { - height: "100vh", - columns: SYMBOL_TABLE_COLUMNS, - layout: "fitDataFill", - data: previousState?.symbols || [], + height: "100vh", + columns: SYMBOL_TABLE_COLUMNS, + layout: "fitColumns", + data: previousState?.symbols || [], }); function updateSymbolsTable(symbols: DAPSymbolType[]) { - SYMBOLS_TABLE.setData(symbols); + SYMBOLS_TABLE.setData(symbols); } window.addEventListener("message", (event: MessageEvent) => { - const message = event.data; - switch (message.command) { - case "updateSymbols": - vscode.setState({ symbols: message.symbols }); - updateSymbolsTable(message.symbols); - break; - } + const message = event.data; + switch (message.command) { + case "updateSymbols": + vscode.setState({ symbols: message.symbols }); + updateSymbolsTable(message.symbols); + break; + } }); From d8f17bc76997bff8dcae3ddac9a07ab7d332d0c4 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 18:59:17 +0200 Subject: [PATCH 18/44] add context menu show symbols for modules --- lldb/tools/lldb-dap/package.json | 14 +++++++++- .../src-ts/ui/modules-data-provider.ts | 1 + .../lldb-dap/src-ts/ui/symbols-provider.ts | 27 ++++++++++++++----- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index d894070a512c8..8cfe0aba15d2d 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -268,9 +268,13 @@ "title": "Copy Value" }, { - "category": "lldb-dap", "command": "lldb-dap.modules.showSymbols", "title": "Show Module Symbols" + }, + { + "category": "lldb-dap", + "command": "lldb-dap.debug.showSymbols", + "title": "Show Symbols of a Module" } ], "menus": { @@ -281,6 +285,10 @@ }, { "command": "lldb-dap.modules.showSymbols", + "when": "false" + }, + { + "command": "lldb-dap.debug.showSymbols", "when": "debuggersAvailable && debugType == 'lldb-dap'" } ], @@ -288,6 +296,10 @@ { "command": "lldb-dap.modules.copyProperty", "when": "view == lldb-dap.modules && viewItem == property" + }, + { + "command": "lldb-dap.modules.showSymbols", + "when": "view == lldb-dap.modules && viewItem == module" } ] }, diff --git a/lldb/tools/lldb-dap/src-ts/ui/modules-data-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/modules-data-provider.ts index d0fb9270c734f..96343cb0a8da6 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/modules-data-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/modules-data-provider.ts @@ -19,6 +19,7 @@ class ModuleItem extends vscode.TreeItem { constructor(module: DebugProtocol.Module) { super(module.name, vscode.TreeItemCollapsibleState.Collapsed); this.description = module.symbolStatus; + this.contextValue = "module"; } static getProperties(module: DebugProtocol.Module): ModuleProperty[] { diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 0446e6273fb0e..0c83cb903f441 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -14,11 +14,22 @@ export class SymbolsProvider extends DisposableContext { super(); this.pushSubscription(vscode.commands.registerCommand( - "lldb-dap.modules.showSymbols", + "lldb-dap.debug.showSymbols", () => { this.SelectModuleAndShowSymbols(); }, )); + + this.pushSubscription(vscode.commands.registerCommand( + "lldb-dap.modules.showSymbols", + (moduleItem: DebugProtocol.Module) => { + const session = vscode.debug.activeDebugSession; + if (!session) { + return; + } + this.showSymbolsForModule(session, moduleItem); + }, + )); } static async doesServerSupportSymbolsRequest(session: vscode.DebugSession): Promise { @@ -55,9 +66,13 @@ export class SymbolsProvider extends DisposableContext { return; } + this.showSymbolsForModule(session, selectedModule.module); + } + + private async showSymbolsForModule(session: vscode.DebugSession, module: DebugProtocol.Module) { try { - const symbols = await this.getSymbolsForModule(session, selectedModule.module.id.toString()); - this.showSymbolsForModule(selectedModule.module.name.toString(), symbols); + const symbols = await this.getSymbolsForModule(session, module.id.toString()); + this.showSymbolsInNewTab(module.name.toString(), symbols); } catch (error) { if (error instanceof Error) { vscode.window.showErrorMessage("Failed to retrieve symbols: " + error.message); @@ -87,7 +102,7 @@ export class SymbolsProvider extends DisposableContext { )) || []; } - private async showSymbolsForModule(moduleName: string, symbols: DAPSymbol[]) { + private async showSymbolsInNewTab(moduleName: string, symbols: DAPSymbol[]) { const panel = vscode.window.createWebviewPanel( "lldb-dap.symbols", `Symbols for ${moduleName}`, @@ -108,11 +123,11 @@ export class SymbolsProvider extends DisposableContext { const tabulatorJsPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.js")); const symbolsTableScriptPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "symbols-table-view.js")); - panel.webview.html = this.getHTMLContentForSymbols(tabulatorJsPath, tabulatorCssPath, symbolsTableScriptPath, symbols); + panel.webview.html = this.getHTMLContentForSymbols(tabulatorJsPath, tabulatorCssPath, symbolsTableScriptPath); panel.webview.postMessage({ command: "updateSymbols", symbols: symbols }); } - private getHTMLContentForSymbols(tabulatorJsPath: vscode.Uri, tabulatorCssPath: vscode.Uri, symbolsTableScriptPath: vscode.Uri, symbols: DAPSymbol[]): string { + private getHTMLContentForSymbols(tabulatorJsPath: vscode.Uri, tabulatorCssPath: vscode.Uri, symbolsTableScriptPath: vscode.Uri): string { return ` From 68281f31467a3c34932db3153538a55797c6fb2d Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 19:01:11 +0200 Subject: [PATCH 19/44] remove unecessary type --- .../lldb-dap/src-ts/ui/symbols-provider.ts | 30 ++----------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 0c83cb903f441..a798fa702c34d 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -84,25 +84,15 @@ export class SymbolsProvider extends DisposableContext { } } - private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { + private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { console.log(`Getting symbols for module: ${moduleId}`); const symbols_response: { symbols: Array } = await session.customRequest("dapGetModuleSymbols", { moduleId }); - return symbols_response?.symbols.map(symbol => new DAPSymbol( - symbol.userId, - symbol.isDebug, - symbol.isSynthetic, - symbol.isExternal, - symbol.type, - symbol.fileAddress, - symbol.loadAddress, - symbol.size, - symbol.name, - )) || []; + return symbols_response?.symbols || []; } - private async showSymbolsInNewTab(moduleName: string, symbols: DAPSymbol[]) { + private async showSymbolsInNewTab(moduleName: string, symbols: DAPSymbolType[]) { const panel = vscode.window.createWebviewPanel( "lldb-dap.symbols", `Symbols for ${moduleName}`, @@ -193,17 +183,3 @@ class ModuleQuickPickItem implements vscode.QuickPickItem { return this.module.id.toString(); } } - -class DAPSymbol { - constructor( - public readonly userId: number, - public readonly isDebug: boolean, - public readonly isSynthetic: boolean, - public readonly isExternal: boolean, - public readonly type: string, - public readonly fileAddress: number, - public readonly loadAddress: number | undefined, - public readonly size: number, - public readonly name: string, - ) {} -} From 1ddd26b5219b796074f691bf6fa4b8917fc790e4 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 15 Aug 2025 19:03:42 +0200 Subject: [PATCH 20/44] format --- .../Handler/DAPGetModuleSymbolsRequestHandler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp index 334ab4f2d9b1e..99199fb2ac9ca 100644 --- a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp @@ -100,12 +100,12 @@ DAPGetModuleSymbolsRequestHandler::Run( lldb::SBModuleSpec module_spec; if (args.moduleId) { llvm::SmallVector uuid_bytes; - if (!lldb_private::UUID::DecodeUUIDBytesFromString(*args.moduleId, uuid_bytes).empty()) + if (!lldb_private::UUID::DecodeUUIDBytesFromString(*args.moduleId, + uuid_bytes) + .empty()) return llvm::make_error("Invalid module ID"); - module_spec.SetUUIDBytes( - uuid_bytes.data(), - uuid_bytes.size()); + module_spec.SetUUIDBytes(uuid_bytes.data(), uuid_bytes.size()); } if (args.moduleName) { From c4993553f49677be43de2b485ab2efcd407e2b51 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 16 Aug 2025 01:28:30 +0200 Subject: [PATCH 21/44] move DAPTypes to a namespace --- lldb/tools/lldb-dap/Breakpoint.cpp | 8 ++++---- .../Handler/DAPGetModuleSymbolsRequestHandler.cpp | 4 ++-- lldb/tools/lldb-dap/Protocol/DAPTypes.cpp | 8 ++++---- lldb/tools/lldb-dap/Protocol/DAPTypes.h | 10 +++++----- lldb/tools/lldb-dap/Protocol/ProtocolRequests.h | 2 +- lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 2 +- lldb/tools/lldb-dap/SourceBreakpoint.cpp | 2 +- lldb/tools/lldb-dap/SourceBreakpoint.h | 2 +- lldb/unittests/DAP/DAPTypesTest.cpp | 9 +++------ 9 files changed, 22 insertions(+), 25 deletions(-) diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp index c8039576b29bd..2f7235c1aabb4 100644 --- a/lldb/tools/lldb-dap/Breakpoint.cpp +++ b/lldb/tools/lldb-dap/Breakpoint.cpp @@ -25,9 +25,9 @@ using namespace lldb_dap; -static std::optional +static std::optional GetPersistenceDataForSymbol(lldb::SBSymbol &symbol) { - protocol::PersistenceData persistence_data; + protocol::dap::PersistenceData persistence_data; lldb::SBModule module = symbol.GetStartAddress().GetModule(); if (!module.IsValid()) return std::nullopt; @@ -105,11 +105,11 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() { // Add persistent data so that the breakpoint can be resolved // in future sessions. - std::optional persistence_data = + std::optional persistence_data = GetPersistenceDataForSymbol(symbol); if (persistence_data) { source->adapterData = - protocol::SourceLLDBData{std::move(persistence_data)}; + protocol::dap::SourceLLDBData{std::move(persistence_data)}; } } } diff --git a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp index 99199fb2ac9ca..a143c814150eb 100644 --- a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp @@ -120,7 +120,7 @@ DAPGetModuleSymbolsRequestHandler::Run( if (!module_spec.IsValid()) return response; - std::vector &symbols = response.symbols; + std::vector &symbols = response.symbols; lldb::SBModule module = dap.target.FindModule(module_spec); if (!module.IsValid()) return llvm::make_error("Module not found"); @@ -131,7 +131,7 @@ DAPGetModuleSymbolsRequestHandler::Run( if (!symbol.IsValid()) continue; - DAPSymbol dap_symbol; + dap::Symbol dap_symbol; dap_symbol.userId = symbol.GetID(); dap_symbol.type = SymbolTypeToString(symbol.GetType()); dap_symbol.isDebug = symbol.IsDebug(); diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp index 212bbd2fe7be6..4d3bc3d0ff834 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp @@ -2,7 +2,7 @@ using namespace llvm; -namespace lldb_dap::protocol { +namespace lldb_dap::protocol::dap { bool fromJSON(const llvm::json::Value &Params, PersistenceData &PD, llvm::json::Path P) { @@ -33,7 +33,7 @@ llvm::json::Value toJSON(const SourceLLDBData &SLD) { return result; } -bool fromJSON(const llvm::json::Value &Params, DAPSymbol &DS, +bool fromJSON(const llvm::json::Value &Params, Symbol &DS, llvm::json::Path P) { json::ObjectMapper O(Params, P); return O && O.map("userId", DS.userId) && O.map("isDebug", DS.isDebug) && @@ -44,7 +44,7 @@ bool fromJSON(const llvm::json::Value &Params, DAPSymbol &DS, O.map("size", DS.size) && O.map("name", DS.name); } -llvm::json::Value toJSON(const DAPSymbol &DS) { +llvm::json::Value toJSON(const Symbol &DS) { json::Object result{ {"userId", DS.userId}, {"isDebug", DS.isDebug}, @@ -60,4 +60,4 @@ llvm::json::Value toJSON(const DAPSymbol &DS) { return result; } -} // namespace lldb_dap::protocol \ No newline at end of file +} // namespace lldb_dap::protocol::dap \ No newline at end of file diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.h b/lldb/tools/lldb-dap/Protocol/DAPTypes.h index 83f9947b1ab57..5933f08a479ce 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.h +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.h @@ -21,7 +21,7 @@ #include #include -namespace lldb_dap::protocol { +namespace lldb_dap::protocol::dap { /// Data used to help lldb-dap resolve breakpoints persistently across different /// sessions. This information is especially useful for assembly breakpoints, @@ -48,7 +48,7 @@ struct SourceLLDBData { bool fromJSON(const llvm::json::Value &, SourceLLDBData &, llvm::json::Path); llvm::json::Value toJSON(const SourceLLDBData &); -struct DAPSymbol { +struct Symbol { /// The symbol uid. uint32_t userId; @@ -77,9 +77,9 @@ struct DAPSymbol { /// The symbol name. std::string name; }; -bool fromJSON(const llvm::json::Value &, DAPSymbol &, llvm::json::Path); -llvm::json::Value toJSON(const DAPSymbol &); +bool fromJSON(const llvm::json::Value &, Symbol &, llvm::json::Path); +llvm::json::Value toJSON(const Symbol &); -} // namespace lldb_dap::protocol +} // namespace lldb_dap::protocol::dap #endif diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index ebf58424f6aa4..0d87f6fac1e18 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -994,7 +994,7 @@ bool fromJSON(const llvm::json::Value &, DAPGetModuleSymbolsArguments &, /// Response to `getModuleSymbols` request. struct DAPGetModuleSymbolsResponseBody { /// The symbols for the specified module. - std::vector symbols; + std::vector symbols; }; llvm::json::Value toJSON(const DAPGetModuleSymbolsResponseBody &); diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h index c4be7911a662b..d3d579da066b0 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h @@ -340,7 +340,7 @@ struct Source { /// Additional data that a debug adapter might want to loop through the /// client. The client should leave the data intact and persist it across /// sessions. The client should not interpret the data. - std::optional adapterData; + std::optional adapterData; // unsupported keys: origin, sources, checksums }; diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp index 843a5eb09c7ae..c4fd23ef87bf1 100644 --- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp +++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp @@ -120,7 +120,7 @@ llvm::Error SourceBreakpoint::CreateAssemblyBreakpointWithSourceReference( } llvm::Error SourceBreakpoint::CreateAssemblyBreakpointWithPersistenceData( - const protocol::PersistenceData &persistence_data) { + const protocol::dap::PersistenceData &persistence_data) { lldb::SBFileSpec file_spec(persistence_data.module_path.c_str()); lldb::SBFileSpecList comp_unit_list; lldb::SBFileSpecList file_spec_list; diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.h b/lldb/tools/lldb-dap/SourceBreakpoint.h index 34054a8dcfd5f..6594e46b8af9a 100644 --- a/lldb/tools/lldb-dap/SourceBreakpoint.h +++ b/lldb/tools/lldb-dap/SourceBreakpoint.h @@ -55,7 +55,7 @@ class SourceBreakpoint : public Breakpoint { llvm::Error CreateAssemblyBreakpointWithSourceReference(int64_t source_reference); llvm::Error CreateAssemblyBreakpointWithPersistenceData( - const protocol::PersistenceData &persistence_data); + const protocol::dap::PersistenceData &persistence_data); // logMessage part can be either a raw text or an expression. struct LogMessagePart { diff --git a/lldb/unittests/DAP/DAPTypesTest.cpp b/lldb/unittests/DAP/DAPTypesTest.cpp index 180917364b0e2..a6f2b6b22b6d5 100644 --- a/lldb/unittests/DAP/DAPTypesTest.cpp +++ b/lldb/unittests/DAP/DAPTypesTest.cpp @@ -8,17 +8,14 @@ #include "Protocol/DAPTypes.h" #include "TestingSupport/TestUtilities.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/JSON.h" #include "llvm/Testing/Support/Error.h" -#include "gmock/gmock.h" #include "gtest/gtest.h" #include using namespace llvm; using namespace lldb; using namespace lldb_dap; -using namespace lldb_dap::protocol; +using namespace lldb_dap::protocol::dap; using lldb_private::roundtripJSON; TEST(DAPTypesTest, SourceLLDBData) { @@ -36,7 +33,7 @@ TEST(DAPTypesTest, SourceLLDBData) { } TEST(DAPTypesTest, DAPSymbol) { - DAPSymbol symbol; + Symbol symbol; symbol.userId = 42; symbol.isDebug = true; symbol.isExternal = false; @@ -47,7 +44,7 @@ TEST(DAPTypesTest, DAPSymbol) { symbol.size = 64; symbol.name = "testSymbol"; - llvm::Expected deserialized_symbol = roundtripJSON(symbol); + llvm::Expected deserialized_symbol = roundtripJSON(symbol); ASSERT_THAT_EXPECTED(deserialized_symbol, llvm::Succeeded()); EXPECT_EQ(symbol.userId, deserialized_symbol->userId); From 0e668d051f07cc02da520c4b82946292693b86d3 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 16 Aug 2025 01:43:32 +0200 Subject: [PATCH 22/44] rename to ModuleSymbolsRequestHandler --- lldb/tools/lldb-dap/CMakeLists.txt | 2 +- lldb/tools/lldb-dap/DAP.cpp | 2 +- ...stHandler.cpp => ModuleSymbolsRequestHandler.cpp} | 12 +++--------- lldb/tools/lldb-dap/Handler/RequestHandler.h | 12 ++++++------ lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp | 6 +++--- lldb/tools/lldb-dap/Protocol/ProtocolRequests.h | 8 ++++---- 6 files changed, 18 insertions(+), 24 deletions(-) rename lldb/tools/lldb-dap/Handler/{DAPGetModuleSymbolsRequestHandler.cpp => ModuleSymbolsRequestHandler.cpp} (91%) diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt index c3ba53754f8ad..7db334ca56bcf 100644 --- a/lldb/tools/lldb-dap/CMakeLists.txt +++ b/lldb/tools/lldb-dap/CMakeLists.txt @@ -36,7 +36,6 @@ add_lldb_library(lldbDAP Handler/CompletionsHandler.cpp Handler/ConfigurationDoneRequestHandler.cpp Handler/ContinueRequestHandler.cpp - Handler/DAPGetModuleSymbolsRequestHandler.cpp Handler/DataBreakpointInfoRequestHandler.cpp Handler/DisassembleRequestHandler.cpp Handler/DisconnectRequestHandler.cpp @@ -46,6 +45,7 @@ add_lldb_library(lldbDAP Handler/LaunchRequestHandler.cpp Handler/LocationsRequestHandler.cpp Handler/ModulesRequestHandler.cpp + Handler/ModuleSymbolsRequestHandler.cpp Handler/NextRequestHandler.cpp Handler/PauseRequestHandler.cpp Handler/ReadMemoryRequestHandler.cpp diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 393d977922346..16280c3535a3b 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -1614,7 +1614,7 @@ void DAP::RegisterRequests() { // Custom requests RegisterRequest(); RegisterRequest(); - RegisterRequest(); + RegisterRequest(); // Testing requests RegisterRequest(); diff --git a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp similarity index 91% rename from lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp rename to lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp index a143c814150eb..87c5737bceb9f 100644 --- a/lldb/tools/lldb-dap/Handler/DAPGetModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp @@ -87,15 +87,9 @@ static std::string SymbolTypeToString(lldb::SymbolType symbol_type) { llvm_unreachable("unhandled symbol type."); } -/// Modules can be retrieved from the debug adapter with this request which can -/// either return all modules or a range of modules to support paging. -/// -/// Clients should only call this request if the corresponding capability -/// `supportsModulesRequest` is true. -llvm::Expected -DAPGetModuleSymbolsRequestHandler::Run( - const DAPGetModuleSymbolsArguments &args) const { - DAPGetModuleSymbolsResponseBody response; +llvm::Expected +ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { + ModuleSymbolsResponseBody response; lldb::SBModuleSpec module_spec; if (args.moduleId) { diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index e605a8bc1b9f1..8e2e408221fed 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -594,15 +594,15 @@ class CancelRequestHandler : public RequestHandler> { + protocol::ModuleSymbolsArguments, + llvm::Expected> { public: using RequestHandler::RequestHandler; - static llvm::StringLiteral GetCommand() { return "dapGetModuleSymbols"; } - llvm::Expected - Run(const protocol::DAPGetModuleSymbolsArguments &args) const override; + static llvm::StringLiteral GetCommand() { return "moduleSymbols"; } + llvm::Expected + Run(const protocol::ModuleSymbolsArguments &args) const override; }; /// A request used in testing to get the details on all breakpoints that are diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp index e0d49a7d03ce5..118791e2c1eea 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp @@ -598,14 +598,14 @@ json::Value toJSON(const WriteMemoryResponseBody &WMR) { return result; } -bool fromJSON(const llvm::json::Value &Params, - DAPGetModuleSymbolsArguments &Args, llvm::json::Path P) { +bool fromJSON(const llvm::json::Value &Params, ModuleSymbolsArguments &Args, + llvm::json::Path P) { json::ObjectMapper O(Params, P); return O && O.mapOptional("moduleId", Args.moduleId) && O.mapOptional("moduleName", Args.moduleName); } -llvm::json::Value toJSON(const DAPGetModuleSymbolsResponseBody &DGMSR) { +llvm::json::Value toJSON(const ModuleSymbolsResponseBody &DGMSR) { json::Object result; result.insert({"symbols", DGMSR.symbols}); return result; diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index 0d87f6fac1e18..13a3715a075a8 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -981,22 +981,22 @@ struct WriteMemoryResponseBody { }; llvm::json::Value toJSON(const WriteMemoryResponseBody &); -struct DAPGetModuleSymbolsArguments { +struct ModuleSymbolsArguments { /// The module UUID for which to retrieve symbols. std::optional moduleId; /// The module path. std::optional moduleName; }; -bool fromJSON(const llvm::json::Value &, DAPGetModuleSymbolsArguments &, +bool fromJSON(const llvm::json::Value &, ModuleSymbolsArguments &, llvm::json::Path); /// Response to `getModuleSymbols` request. -struct DAPGetModuleSymbolsResponseBody { +struct ModuleSymbolsResponseBody { /// The symbols for the specified module. std::vector symbols; }; -llvm::json::Value toJSON(const DAPGetModuleSymbolsResponseBody &); +llvm::json::Value toJSON(const ModuleSymbolsResponseBody &); } // namespace lldb_dap::protocol From b36db9adb7648055d337e2069d0781779764aeeb Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 16 Aug 2025 11:04:49 +0200 Subject: [PATCH 23/44] revert extra dap namespace --- lldb/tools/lldb-dap/Breakpoint.cpp | 8 ++++---- .../lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp | 4 ++-- lldb/tools/lldb-dap/Protocol/DAPTypes.cpp | 4 ++-- lldb/tools/lldb-dap/Protocol/DAPTypes.h | 4 ++-- lldb/tools/lldb-dap/Protocol/ProtocolRequests.h | 2 +- lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 2 +- lldb/tools/lldb-dap/SourceBreakpoint.cpp | 2 +- lldb/tools/lldb-dap/SourceBreakpoint.h | 2 +- lldb/unittests/DAP/DAPTypesTest.cpp | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp index 2f7235c1aabb4..c8039576b29bd 100644 --- a/lldb/tools/lldb-dap/Breakpoint.cpp +++ b/lldb/tools/lldb-dap/Breakpoint.cpp @@ -25,9 +25,9 @@ using namespace lldb_dap; -static std::optional +static std::optional GetPersistenceDataForSymbol(lldb::SBSymbol &symbol) { - protocol::dap::PersistenceData persistence_data; + protocol::PersistenceData persistence_data; lldb::SBModule module = symbol.GetStartAddress().GetModule(); if (!module.IsValid()) return std::nullopt; @@ -105,11 +105,11 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() { // Add persistent data so that the breakpoint can be resolved // in future sessions. - std::optional persistence_data = + std::optional persistence_data = GetPersistenceDataForSymbol(symbol); if (persistence_data) { source->adapterData = - protocol::dap::SourceLLDBData{std::move(persistence_data)}; + protocol::SourceLLDBData{std::move(persistence_data)}; } } } diff --git a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp index 87c5737bceb9f..14d73073a8452 100644 --- a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp @@ -114,7 +114,7 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { if (!module_spec.IsValid()) return response; - std::vector &symbols = response.symbols; + std::vector &symbols = response.symbols; lldb::SBModule module = dap.target.FindModule(module_spec); if (!module.IsValid()) return llvm::make_error("Module not found"); @@ -125,7 +125,7 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { if (!symbol.IsValid()) continue; - dap::Symbol dap_symbol; + Symbol dap_symbol; dap_symbol.userId = symbol.GetID(); dap_symbol.type = SymbolTypeToString(symbol.GetType()); dap_symbol.isDebug = symbol.IsDebug(); diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp index 4d3bc3d0ff834..007fcdd74c6f1 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp @@ -2,7 +2,7 @@ using namespace llvm; -namespace lldb_dap::protocol::dap { +namespace lldb_dap::protocol { bool fromJSON(const llvm::json::Value &Params, PersistenceData &PD, llvm::json::Path P) { @@ -60,4 +60,4 @@ llvm::json::Value toJSON(const Symbol &DS) { return result; } -} // namespace lldb_dap::protocol::dap \ No newline at end of file +} // namespace lldb_dap::protocol \ No newline at end of file diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.h b/lldb/tools/lldb-dap/Protocol/DAPTypes.h index 5933f08a479ce..b633c31c462c9 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.h +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.h @@ -21,7 +21,7 @@ #include #include -namespace lldb_dap::protocol::dap { +namespace lldb_dap::protocol { /// Data used to help lldb-dap resolve breakpoints persistently across different /// sessions. This information is especially useful for assembly breakpoints, @@ -80,6 +80,6 @@ struct Symbol { bool fromJSON(const llvm::json::Value &, Symbol &, llvm::json::Path); llvm::json::Value toJSON(const Symbol &); -} // namespace lldb_dap::protocol::dap +} // namespace lldb_dap::protocol #endif diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index 13a3715a075a8..136064dfc653e 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -994,7 +994,7 @@ bool fromJSON(const llvm::json::Value &, ModuleSymbolsArguments &, /// Response to `getModuleSymbols` request. struct ModuleSymbolsResponseBody { /// The symbols for the specified module. - std::vector symbols; + std::vector symbols; }; llvm::json::Value toJSON(const ModuleSymbolsResponseBody &); diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h index d3d579da066b0..c4be7911a662b 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h @@ -340,7 +340,7 @@ struct Source { /// Additional data that a debug adapter might want to loop through the /// client. The client should leave the data intact and persist it across /// sessions. The client should not interpret the data. - std::optional adapterData; + std::optional adapterData; // unsupported keys: origin, sources, checksums }; diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp index c4fd23ef87bf1..843a5eb09c7ae 100644 --- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp +++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp @@ -120,7 +120,7 @@ llvm::Error SourceBreakpoint::CreateAssemblyBreakpointWithSourceReference( } llvm::Error SourceBreakpoint::CreateAssemblyBreakpointWithPersistenceData( - const protocol::dap::PersistenceData &persistence_data) { + const protocol::PersistenceData &persistence_data) { lldb::SBFileSpec file_spec(persistence_data.module_path.c_str()); lldb::SBFileSpecList comp_unit_list; lldb::SBFileSpecList file_spec_list; diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.h b/lldb/tools/lldb-dap/SourceBreakpoint.h index 6594e46b8af9a..34054a8dcfd5f 100644 --- a/lldb/tools/lldb-dap/SourceBreakpoint.h +++ b/lldb/tools/lldb-dap/SourceBreakpoint.h @@ -55,7 +55,7 @@ class SourceBreakpoint : public Breakpoint { llvm::Error CreateAssemblyBreakpointWithSourceReference(int64_t source_reference); llvm::Error CreateAssemblyBreakpointWithPersistenceData( - const protocol::dap::PersistenceData &persistence_data); + const protocol::PersistenceData &persistence_data); // logMessage part can be either a raw text or an expression. struct LogMessagePart { diff --git a/lldb/unittests/DAP/DAPTypesTest.cpp b/lldb/unittests/DAP/DAPTypesTest.cpp index a6f2b6b22b6d5..54f47444fdd10 100644 --- a/lldb/unittests/DAP/DAPTypesTest.cpp +++ b/lldb/unittests/DAP/DAPTypesTest.cpp @@ -15,7 +15,7 @@ using namespace llvm; using namespace lldb; using namespace lldb_dap; -using namespace lldb_dap::protocol::dap; +using namespace lldb_dap::protocol; using lldb_private::roundtripJSON; TEST(DAPTypesTest, SourceLLDBData) { From de67bac8f4b833a08693732f8ac25f2976185254 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 16 Aug 2025 11:05:10 +0200 Subject: [PATCH 24/44] format --- lldb/tools/lldb-dap/Protocol/DAPTypes.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp index 007fcdd74c6f1..fd884b5f8a81c 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp @@ -33,8 +33,7 @@ llvm::json::Value toJSON(const SourceLLDBData &SLD) { return result; } -bool fromJSON(const llvm::json::Value &Params, Symbol &DS, - llvm::json::Path P) { +bool fromJSON(const llvm::json::Value &Params, Symbol &DS, llvm::json::Path P) { json::ObjectMapper O(Params, P); return O && O.map("userId", DS.userId) && O.map("isDebug", DS.isDebug) && O.map("isSynthetic", DS.isSynthetic) && From b6f67667b96cb18a101cce44de3b905e7bdbf442 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 16 Aug 2025 11:21:33 +0200 Subject: [PATCH 25/44] rename --- lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index a798fa702c34d..d3be932f740b4 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -35,7 +35,7 @@ export class SymbolsProvider extends DisposableContext { static async doesServerSupportSymbolsRequest(session: vscode.DebugSession): Promise { try { const dummyArguments = { _dummy: true }; - await session.customRequest("dapGetModuleSymbols", dummyArguments); + await session.customRequest("moduleSymbols", dummyArguments); return true; } catch (_error) { return false; @@ -86,7 +86,7 @@ export class SymbolsProvider extends DisposableContext { private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { console.log(`Getting symbols for module: ${moduleId}`); - const symbols_response: { symbols: Array } = await session.customRequest("dapGetModuleSymbols", { moduleId }); + const symbols_response: { symbols: Array } = await session.customRequest("moduleSymbols", { moduleId }); return symbols_response?.symbols || []; From 7c7f4770bed5c55c73b45c8a41d23a7605112997 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 16 Aug 2025 13:29:40 +0200 Subject: [PATCH 26/44] use symbol type as enum --- .../Handler/ModuleSymbolsRequestHandler.cpp | 68 +--------- lldb/tools/lldb-dap/Protocol/DAPTypes.cpp | 120 +++++++++++++++++- lldb/tools/lldb-dap/Protocol/DAPTypes.h | 2 +- lldb/unittests/DAP/DAPTypesTest.cpp | 3 +- 4 files changed, 117 insertions(+), 76 deletions(-) diff --git a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp index 14d73073a8452..ad7278b3ac4fc 100644 --- a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp @@ -15,78 +15,12 @@ #include "lldb/API/SBModule.h" #include "lldb/API/SBModuleSpec.h" #include "lldb/Utility/UUID.h" -#include "lldb/lldb-enumerations.h" #include "llvm/Support/Error.h" #include using namespace lldb_dap::protocol; namespace lldb_dap { -static std::string SymbolTypeToString(lldb::SymbolType symbol_type) { - switch (symbol_type) { - case lldb::eSymbolTypeInvalid: - return "Invalid"; - case lldb::eSymbolTypeAbsolute: - return "Absolute"; - case lldb::eSymbolTypeCode: - return "Code"; - case lldb::eSymbolTypeResolver: - return "Resolver"; - case lldb::eSymbolTypeData: - return "Data"; - case lldb::eSymbolTypeTrampoline: - return "Trampoline"; - case lldb::eSymbolTypeRuntime: - return "Runtime"; - case lldb::eSymbolTypeException: - return "Exception"; - case lldb::eSymbolTypeSourceFile: - return "SourceFile"; - case lldb::eSymbolTypeHeaderFile: - return "HeaderFile"; - case lldb::eSymbolTypeObjectFile: - return "ObjectFile"; - case lldb::eSymbolTypeCommonBlock: - return "CommonBlock"; - case lldb::eSymbolTypeBlock: - return "Block"; - case lldb::eSymbolTypeLocal: - return "Local"; - case lldb::eSymbolTypeParam: - return "Param"; - case lldb::eSymbolTypeVariable: - return "Variable"; - case lldb::eSymbolTypeVariableType: - return "VariableType"; - case lldb::eSymbolTypeLineEntry: - return "LineEntry"; - case lldb::eSymbolTypeLineHeader: - return "LineHeader"; - case lldb::eSymbolTypeScopeBegin: - return "ScopeBegin"; - case lldb::eSymbolTypeScopeEnd: - return "ScopeEnd"; - case lldb::eSymbolTypeAdditional: - return "Additional"; - case lldb::eSymbolTypeCompiler: - return "Compiler"; - case lldb::eSymbolTypeInstrumentation: - return "Instrumentation"; - case lldb::eSymbolTypeUndefined: - return "Undefined"; - case lldb::eSymbolTypeObjCClass: - return "ObjCClass"; - case lldb::eSymbolTypeObjCMetaClass: - return "ObjCMetaClass"; - case lldb::eSymbolTypeObjCIVar: - return "ObjCIVar"; - case lldb::eSymbolTypeReExported: - return "ReExported"; - } - - llvm_unreachable("unhandled symbol type."); -} - llvm::Expected ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { ModuleSymbolsResponseBody response; @@ -127,7 +61,7 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { Symbol dap_symbol; dap_symbol.userId = symbol.GetID(); - dap_symbol.type = SymbolTypeToString(symbol.GetType()); + dap_symbol.type = symbol.GetType(); dap_symbol.isDebug = symbol.IsDebug(); dap_symbol.isSynthetic = symbol.IsSynthetic(); dap_symbol.isExternal = symbol.IsExternal(); diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp index fd884b5f8a81c..54108872573c6 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp @@ -1,9 +1,110 @@ #include "Protocol/DAPTypes.h" +#include "lldb/lldb-enumerations.h" using namespace llvm; namespace lldb_dap::protocol { +static std::string SymbolTypeToString(lldb::SymbolType symbol_type) { + switch (symbol_type) { + case lldb::eSymbolTypeInvalid: + return "Invalid"; + case lldb::eSymbolTypeAbsolute: + return "Absolute"; + case lldb::eSymbolTypeCode: + return "Code"; + case lldb::eSymbolTypeResolver: + return "Resolver"; + case lldb::eSymbolTypeData: + return "Data"; + case lldb::eSymbolTypeTrampoline: + return "Trampoline"; + case lldb::eSymbolTypeRuntime: + return "Runtime"; + case lldb::eSymbolTypeException: + return "Exception"; + case lldb::eSymbolTypeSourceFile: + return "SourceFile"; + case lldb::eSymbolTypeHeaderFile: + return "HeaderFile"; + case lldb::eSymbolTypeObjectFile: + return "ObjectFile"; + case lldb::eSymbolTypeCommonBlock: + return "CommonBlock"; + case lldb::eSymbolTypeBlock: + return "Block"; + case lldb::eSymbolTypeLocal: + return "Local"; + case lldb::eSymbolTypeParam: + return "Param"; + case lldb::eSymbolTypeVariable: + return "Variable"; + case lldb::eSymbolTypeVariableType: + return "VariableType"; + case lldb::eSymbolTypeLineEntry: + return "LineEntry"; + case lldb::eSymbolTypeLineHeader: + return "LineHeader"; + case lldb::eSymbolTypeScopeBegin: + return "ScopeBegin"; + case lldb::eSymbolTypeScopeEnd: + return "ScopeEnd"; + case lldb::eSymbolTypeAdditional: + return "Additional"; + case lldb::eSymbolTypeCompiler: + return "Compiler"; + case lldb::eSymbolTypeInstrumentation: + return "Instrumentation"; + case lldb::eSymbolTypeUndefined: + return "Undefined"; + case lldb::eSymbolTypeObjCClass: + return "ObjCClass"; + case lldb::eSymbolTypeObjCMetaClass: + return "ObjCMetaClass"; + case lldb::eSymbolTypeObjCIVar: + return "ObjCIVar"; + case lldb::eSymbolTypeReExported: + return "ReExported"; + } + + llvm_unreachable("unhandled symbol type."); +} + +static lldb::SymbolType StringToSymbolType(const std::string &symbol_type) { + return llvm::StringSwitch(symbol_type) + .Case("Invalid", lldb::eSymbolTypeInvalid) + .Case("Absolute", lldb::eSymbolTypeAbsolute) + .Case("Code", lldb::eSymbolTypeCode) + .Case("Resolver", lldb::eSymbolTypeResolver) + .Case("Data", lldb::eSymbolTypeData) + .Case("Trampoline", lldb::eSymbolTypeTrampoline) + .Case("Runtime", lldb::eSymbolTypeRuntime) + .Case("Exception", lldb::eSymbolTypeException) + .Case("SourceFile", lldb::eSymbolTypeSourceFile) + .Case("HeaderFile", lldb::eSymbolTypeHeaderFile) + .Case("ObjectFile", lldb::eSymbolTypeObjectFile) + .Case("CommonBlock", lldb::eSymbolTypeCommonBlock) + .Case("Block", lldb::eSymbolTypeBlock) + .Case("Local", lldb::eSymbolTypeLocal) + .Case("Param", lldb::eSymbolTypeParam) + .Case("Variable", lldb::eSymbolTypeVariable) + .Case("VariableType", lldb::eSymbolTypeVariableType) + .Case("LineEntry", lldb::eSymbolTypeLineEntry) + .Case("LineHeader", lldb::eSymbolTypeLineHeader) + .Case("ScopeBegin", lldb::eSymbolTypeScopeBegin) + .Case("ScopeEnd", lldb::eSymbolTypeScopeEnd) + .Case("Additional", lldb::eSymbolTypeAdditional) + .Case("Compiler", lldb::eSymbolTypeCompiler) + .Case("Instrumentation", lldb::eSymbolTypeInstrumentation) + .Case("Undefined", lldb::eSymbolTypeUndefined) + .Case("ObjCClass", lldb::eSymbolTypeObjCClass) + .Case("ObjCMetaClass", lldb::eSymbolTypeObjCMetaClass) + .Case("ObjCIVar", lldb::eSymbolTypeObjCIVar) + .Case("ReExported", lldb::eSymbolTypeReExported) + + .Default(lldb::eSymbolTypeInvalid); +} + bool fromJSON(const llvm::json::Value &Params, PersistenceData &PD, llvm::json::Path P) { json::ObjectMapper O(Params, P); @@ -35,12 +136,17 @@ llvm::json::Value toJSON(const SourceLLDBData &SLD) { bool fromJSON(const llvm::json::Value &Params, Symbol &DS, llvm::json::Path P) { json::ObjectMapper O(Params, P); - return O && O.map("userId", DS.userId) && O.map("isDebug", DS.isDebug) && - O.map("isSynthetic", DS.isSynthetic) && - O.map("isExternal", DS.isExternal) && O.map("type", DS.type) && - O.map("fileAddress", DS.fileAddress) && - O.mapOptional("loadAddress", DS.loadAddress) && - O.map("size", DS.size) && O.map("name", DS.name); + std::string type_str; + if (!(O && O.map("userId", DS.userId) && O.map("isDebug", DS.isDebug) && + O.map("isSynthetic", DS.isSynthetic) && + O.map("isExternal", DS.isExternal) && O.map("type", type_str) && + O.map("fileAddress", DS.fileAddress) && + O.mapOptional("loadAddress", DS.loadAddress) && + O.map("size", DS.size) && O.map("name", DS.name))) + return false; + + DS.type = StringToSymbolType(type_str); + return true; } llvm::json::Value toJSON(const Symbol &DS) { @@ -49,7 +155,7 @@ llvm::json::Value toJSON(const Symbol &DS) { {"isDebug", DS.isDebug}, {"isSynthetic", DS.isSynthetic}, {"isExternal", DS.isExternal}, - {"type", DS.type}, + {"type", SymbolTypeToString(DS.type)}, {"fileAddress", DS.fileAddress}, {"loadAddress", DS.loadAddress}, {"size", DS.size}, diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.h b/lldb/tools/lldb-dap/Protocol/DAPTypes.h index b633c31c462c9..9e7354e912485 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.h +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.h @@ -63,7 +63,7 @@ struct Symbol { bool isExternal; /// The symbol type. - std::string type; + lldb::SymbolType type; /// The symbol file address. lldb::addr_t fileAddress; diff --git a/lldb/unittests/DAP/DAPTypesTest.cpp b/lldb/unittests/DAP/DAPTypesTest.cpp index 54f47444fdd10..b2721aaebbb20 100644 --- a/lldb/unittests/DAP/DAPTypesTest.cpp +++ b/lldb/unittests/DAP/DAPTypesTest.cpp @@ -8,6 +8,7 @@ #include "Protocol/DAPTypes.h" #include "TestingSupport/TestUtilities.h" +#include "lldb/lldb-enumerations.h" #include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" #include @@ -38,7 +39,7 @@ TEST(DAPTypesTest, DAPSymbol) { symbol.isDebug = true; symbol.isExternal = false; symbol.isSynthetic = true; - symbol.type = "Trampoline"; + symbol.type = lldb::eSymbolTypeTrampoline; symbol.fileAddress = 0x12345678; symbol.loadAddress = 0x87654321; symbol.size = 64; From 7c0ad878c34ce49830de2ed31087317ee55a06b2 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 16 Aug 2025 14:51:26 +0200 Subject: [PATCH 27/44] identifying lldb-dap version and using it in command context to enable symbols request --- .../Handler/ModuleSymbolsRequestHandler.cpp | 10 ++- .../lldb-dap/Protocol/ProtocolRequests.h | 4 +- lldb/tools/lldb-dap/package.json | 4 +- .../src-ts/debug-configuration-provider.ts | 4 ++ .../lldb-dap/src-ts/debug-session-tracker.ts | 15 +++++ .../lldb-dap/src-ts/ui/symbols-provider.ts | 62 +++++++++++-------- 6 files changed, 63 insertions(+), 36 deletions(-) diff --git a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp index ad7278b3ac4fc..71743192302ee 100644 --- a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp @@ -26,9 +26,9 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { ModuleSymbolsResponseBody response; lldb::SBModuleSpec module_spec; - if (args.moduleId) { + if (!args.moduleId.empty()) { llvm::SmallVector uuid_bytes; - if (!lldb_private::UUID::DecodeUUIDBytesFromString(*args.moduleId, + if (!lldb_private::UUID::DecodeUUIDBytesFromString(args.moduleId, uuid_bytes) .empty()) return llvm::make_error("Invalid module ID"); @@ -36,15 +36,13 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { module_spec.SetUUIDBytes(uuid_bytes.data(), uuid_bytes.size()); } - if (args.moduleName) { + if (!args.moduleName.empty()) { lldb::SBFileSpec file_spec; - file_spec.SetFilename(args.moduleName->c_str()); + file_spec.SetFilename(args.moduleName.c_str()); module_spec.SetFileSpec(file_spec); } // Empty request, return empty response. - // We use it in the client to check if the lldb-dap server supports this - // request. if (!module_spec.IsValid()) return response; diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index 136064dfc653e..08b74ebf2d585 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -983,10 +983,10 @@ llvm::json::Value toJSON(const WriteMemoryResponseBody &); struct ModuleSymbolsArguments { /// The module UUID for which to retrieve symbols. - std::optional moduleId; + std::string moduleId; /// The module path. - std::optional moduleName; + std::string moduleName; }; bool fromJSON(const llvm::json::Value &, ModuleSymbolsArguments &, llvm::json::Path); diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index 8cfe0aba15d2d..fbf4d547723b3 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -289,7 +289,7 @@ }, { "command": "lldb-dap.debug.showSymbols", - "when": "debuggersAvailable && debugType == 'lldb-dap'" + "when": "debuggersAvailable && debugType == 'lldb-dap' && lldb-dap.supportsModuleSymbolsRequest" } ], "view/item/context": [ @@ -299,7 +299,7 @@ }, { "command": "lldb-dap.modules.showSymbols", - "when": "view == lldb-dap.modules && viewItem == module" + "when": "view == lldb-dap.modules && viewItem == module && lldb-dap.supportsModuleSymbolsRequest" } ] }, diff --git a/lldb/tools/lldb-dap/src-ts/debug-configuration-provider.ts b/lldb/tools/lldb-dap/src-ts/debug-configuration-provider.ts index 1e16dac031125..1ae87116141f1 100644 --- a/lldb/tools/lldb-dap/src-ts/debug-configuration-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/debug-configuration-provider.ts @@ -69,6 +69,10 @@ const configurations: Record = { terminateCommands: { type: "stringArray", default: [] }, }; +export function getDefaultConfigKey(key: string): string | number | boolean | string[] | undefined { + return configurations[key]?.default; +} + export class LLDBDapConfigurationProvider implements vscode.DebugConfigurationProvider { diff --git a/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts b/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts index 7d7f73dbff92d..21c3201b0cbdb 100644 --- a/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts +++ b/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts @@ -6,6 +6,7 @@ import * as vscode from "vscode"; interface EventMap { "module": DebugProtocol.ModuleEvent; "exited": DebugProtocol.ExitedEvent; + "initialized": DebugProtocol.InitializedEvent; } /** A type assertion to check if a ProtocolMessage is an event or if it is a specific event. */ @@ -39,6 +40,8 @@ export class DebugSessionTracker private modulesChanged = new vscode.EventEmitter< vscode.DebugSession | undefined >(); + private sessionInitialized = new vscode.EventEmitter(); + private sessionExited = new vscode.EventEmitter(); /** * Fired when modules are changed for any active debug session. @@ -48,6 +51,14 @@ export class DebugSessionTracker onDidChangeModules: vscode.Event = this.modulesChanged.event; + /** Fired when a debug session is initialized. */ + onDidInitializeSession: vscode.Event = + this.sessionInitialized.event; + + /** Fired when a debug session is exiting. */ + onDidExitSession: vscode.Event = + this.sessionExited.event; + constructor(private logger: vscode.LogOutputChannel) { this.onDidChangeModules(this.moduleChangedListener, this); vscode.debug.onDidChangeActiveDebugSession((session) => @@ -146,6 +157,10 @@ export class DebugSessionTracker this.logger.info( `Session "${session.name}" exited with code ${exitCode}`, ); + + this.sessionExited.fire(session); + } else if (isEvent(message, "initialized")) { + this.sessionInitialized.fire(session); } } } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index d3be932f740b4..f09fd14254528 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -5,6 +5,7 @@ import { DebugSessionTracker } from "../debug-session-tracker"; import { DisposableContext } from "../disposable-context"; import { DAPSymbolType } from ".."; +import { getDefaultConfigKey } from "../debug-configuration-provider"; export class SymbolsProvider extends DisposableContext { constructor( @@ -16,7 +17,10 @@ export class SymbolsProvider extends DisposableContext { this.pushSubscription(vscode.commands.registerCommand( "lldb-dap.debug.showSymbols", () => { - this.SelectModuleAndShowSymbols(); + const session = vscode.debug.activeDebugSession; + if (!session) return; + + this.SelectModuleAndShowSymbols(session); }, )); @@ -24,38 +28,45 @@ export class SymbolsProvider extends DisposableContext { "lldb-dap.modules.showSymbols", (moduleItem: DebugProtocol.Module) => { const session = vscode.debug.activeDebugSession; - if (!session) { - return; - } + if (!session) return; + this.showSymbolsForModule(session, moduleItem); }, )); - } - static async doesServerSupportSymbolsRequest(session: vscode.DebugSession): Promise { - try { - const dummyArguments = { _dummy: true }; - await session.customRequest("moduleSymbols", dummyArguments); - return true; - } catch (_error) { - return false; - } + this.tracker.onDidInitializeSession((session) => { + this.GetLLDBServerVersion(session).then((version) => { + if (version !== undefined) { + if (version[0] >= 23) { + vscode.commands.executeCommand("setContext", "lldb-dap.supportsModuleSymbolsRequest", true); + } + } + }); + }); + + this.tracker.onDidExitSession((session) => { + vscode.commands.executeCommand("setContext", "lldb-dap.supportsModuleSymbolsRequest", false); + }); } - private async SelectModuleAndShowSymbols() { - const session = vscode.debug.activeDebugSession; - if (!session) { - return; - } + private async GetLLDBServerVersion(session: vscode.DebugSession): Promise<[number, number, number] | undefined> { + const commandEscapePrefix = session.configuration.commandEscapePrefix || getDefaultConfigKey("commandEscapePrefix"); + const response = await session.customRequest("evaluate", { expression: commandEscapePrefix + "version", context: "repl" }); - if (!await SymbolsProvider.doesServerSupportSymbolsRequest(session)) { - vscode.window.showErrorMessage("The debug adapter does not support symbol requests."); - return; - } + const versionLine = response.result?.split("\n")[0]; + if (!versionLine) return undefined; + + const versionMatch = versionLine.match(/(\d+)\.(\d+)\.(\d+)/); + if (!versionMatch) return undefined; + const [major, minor, patch] = versionMatch.slice(1, 4).map(Number); + return [major, minor, patch]; + } + + private async SelectModuleAndShowSymbols(session: vscode.DebugSession) { const modules = this.tracker.debugSessionModules(session); if (!modules || modules.length === 0) { - return; + return; } // Let the user select a module to show symbols for @@ -63,7 +74,7 @@ export class SymbolsProvider extends DisposableContext { placeHolder: "Select a module to show symbols for" }); if (!selectedModule) { - return; + return; } this.showSymbolsForModule(session, selectedModule.module); @@ -86,8 +97,7 @@ export class SymbolsProvider extends DisposableContext { private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { console.log(`Getting symbols for module: ${moduleId}`); - const symbols_response: { symbols: Array } = await session.customRequest("moduleSymbols", { moduleId }); - + const symbols_response: { symbols: Array } = await session.customRequest("moduleSymbols", { moduleId, moduleName: '' }); return symbols_response?.symbols || []; } From 6581b34e768afbaf8f552b31ca9c1c1c5c225637 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 16 Aug 2025 14:56:16 +0200 Subject: [PATCH 28/44] fix --- lldb/tools/lldb-dap/src-ts/index.d.ts | 4 ++-- lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/index.d.ts b/lldb/tools/lldb-dap/src-ts/index.d.ts index cd5359d039619..ec9dd09cfabb4 100644 --- a/lldb/tools/lldb-dap/src-ts/index.d.ts +++ b/lldb/tools/lldb-dap/src-ts/index.d.ts @@ -1,7 +1,7 @@ export {}; /// The symbol type we get from the lldb-dap server -export type DAPSymbolType = { +export declare interface DAPSymbolType { userId: number; isDebug: boolean; isSynthetic: boolean; @@ -11,4 +11,4 @@ export type DAPSymbolType = { loadAddress?: number; size: number; name: string; -}; +} diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index f09fd14254528..fbcba45da4565 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -37,7 +37,7 @@ export class SymbolsProvider extends DisposableContext { this.tracker.onDidInitializeSession((session) => { this.GetLLDBServerVersion(session).then((version) => { if (version !== undefined) { - if (version[0] >= 23) { + if (version[0] >= 22) { vscode.commands.executeCommand("setContext", "lldb-dap.supportsModuleSymbolsRequest", true); } } From 1f168a7570788835a65cc15d21be88a27b4fc2f1 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sat, 16 Aug 2025 19:05:10 +0200 Subject: [PATCH 29/44] add index and count to the moduleSymbols request --- lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp | 6 ++++-- lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp | 6 ++++-- lldb/tools/lldb-dap/Protocol/ProtocolRequests.h | 6 ++++++ lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp index 71743192302ee..04c82da886dfa 100644 --- a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp @@ -51,8 +51,10 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { if (!module.IsValid()) return llvm::make_error("Module not found"); - size_t num_symbols = module.GetNumSymbols(); - for (size_t i = 0; i < num_symbols; ++i) { + const size_t num_symbols = module.GetNumSymbols(); + const size_t start_index = args.startIndex.value_or(0); + const size_t end_index = std::min(start_index + args.count.value_or(num_symbols), num_symbols); + for (size_t i = start_index; i < end_index; ++i) { lldb::SBSymbol symbol = module.GetSymbolAtIndex(i); if (!symbol.IsValid()) continue; diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp index 118791e2c1eea..9c06699c2320c 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp @@ -601,8 +601,10 @@ json::Value toJSON(const WriteMemoryResponseBody &WMR) { bool fromJSON(const llvm::json::Value &Params, ModuleSymbolsArguments &Args, llvm::json::Path P) { json::ObjectMapper O(Params, P); - return O && O.mapOptional("moduleId", Args.moduleId) && - O.mapOptional("moduleName", Args.moduleName); + return O && O.map("moduleId", Args.moduleId) && + O.map("moduleName", Args.moduleName) && + O.mapOptional("startIndex", Args.startIndex) && + O.mapOptional("count", Args.count); } llvm::json::Value toJSON(const ModuleSymbolsResponseBody &DGMSR) { diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index 08b74ebf2d585..a027db1edb51e 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -987,6 +987,12 @@ struct ModuleSymbolsArguments { /// The module path. std::string moduleName; + + /// The index of the first symbol to return; if omitted, start at the beginning. + std::optional startIndex; + + /// The number of symbols to return; if omitted, all symbols are returned. + std::optional count; }; bool fromJSON(const llvm::json::Value &, ModuleSymbolsArguments &, llvm::json::Path); diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index fbcba45da4565..273120800ff3a 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -44,7 +44,7 @@ export class SymbolsProvider extends DisposableContext { }); }); - this.tracker.onDidExitSession((session) => { + this.tracker.onDidExitSession((_session) => { vscode.commands.executeCommand("setContext", "lldb-dap.supportsModuleSymbolsRequest", false); }); } From 693e29c621f0918b576cc6721d657fd1865ed6f5 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sun, 17 Aug 2025 00:50:35 +0200 Subject: [PATCH 30/44] adding simple test for the moduleSymbols request --- .../test/tools/lldb-dap/dap_server.py | 13 +++++++ .../API/tools/lldb-dap/moduleSymbols/Makefile | 3 ++ .../moduleSymbols/TestDAP_moduleSymbols.py | 35 +++++++++++++++++++ .../API/tools/lldb-dap/moduleSymbols/main.c | 13 +++++++ 4 files changed, 64 insertions(+) create mode 100644 lldb/test/API/tools/lldb-dap/moduleSymbols/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py create mode 100644 lldb/test/API/tools/lldb-dap/moduleSymbols/main.c diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 939be9941a49d..0f28f90867b9c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -1199,6 +1199,19 @@ def request_modules(self, startModule: int, moduleCount: int): } ) + def request_moduleSymbols(self, moduleId: str = "", moduleName: str = "", startIndex: int = 0, count: int = 0): + command_dict = { + "command": "moduleSymbols", + "type": "request", + "arguments": { + "moduleId": moduleId, + "moduleName": moduleName, + "startIndex": startIndex, + "count": count, + }, + } + return self.send_recv(command_dict) + def request_stackTrace( self, threadId=None, startFrame=None, levels=None, format=None, dump=False ): diff --git a/lldb/test/API/tools/lldb-dap/moduleSymbols/Makefile b/lldb/test/API/tools/lldb-dap/moduleSymbols/Makefile new file mode 100644 index 0000000000000..10495940055b6 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/moduleSymbols/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py b/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py new file mode 100644 index 0000000000000..2a091a659e22d --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py @@ -0,0 +1,35 @@ +""" +Test lldb-dap moduleSymbols request +""" + +import lldbdap_testcase + + +class TestDAP_moduleSymbols(lldbdap_testcase.DAPTestCaseBase): + def test_moduleSymbols(self): + """ + Test that the stack frame without a module still has assembly source. + """ + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + + symbol_names = [] + i = 0 + while True: + next_symbol = self.dap_server.request_moduleSymbols(moduleName="a.out", startIndex=i, count=1) + self.assertIn("symbols", next_symbol["body"]) + result_symbols = next_symbol["body"]["symbols"] + self.assertLessEqual(len(result_symbols), 1) + if len(result_symbols) == 0: + break + + self.assertIn("name", result_symbols[0]) + symbol_names.append(result_symbols[0]["name"]) + i += 1 + if i >= 1000: + break + + self.assertGreater(len(symbol_names), 0) + self.assertIn("main", symbol_names) + self.assertIn("func1", symbol_names) + self.assertIn("func2", symbol_names) diff --git a/lldb/test/API/tools/lldb-dap/moduleSymbols/main.c b/lldb/test/API/tools/lldb-dap/moduleSymbols/main.c new file mode 100644 index 0000000000000..bd4475fb29469 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/moduleSymbols/main.c @@ -0,0 +1,13 @@ +int func1() { + return 42; +} + +int func2() { + return 84; +} + +int main() { + func1(); + func2(); + return 0; +} From f8da9f1a62742601a2dd5805e005ac6b2e4a3cd8 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sun, 17 Aug 2025 00:55:20 +0200 Subject: [PATCH 31/44] format --- lldb/test/API/tools/lldb-dap/moduleSymbols/main.c | 8 ++------ .../lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp | 3 ++- lldb/tools/lldb-dap/Protocol/ProtocolRequests.h | 3 ++- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/moduleSymbols/main.c b/lldb/test/API/tools/lldb-dap/moduleSymbols/main.c index bd4475fb29469..b038b10480b80 100644 --- a/lldb/test/API/tools/lldb-dap/moduleSymbols/main.c +++ b/lldb/test/API/tools/lldb-dap/moduleSymbols/main.c @@ -1,10 +1,6 @@ -int func1() { - return 42; -} +int func1() { return 42; } -int func2() { - return 84; -} +int func2() { return 84; } int main() { func1(); diff --git a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp index 04c82da886dfa..213e4d1e7fd2f 100644 --- a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp @@ -53,7 +53,8 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { const size_t num_symbols = module.GetNumSymbols(); const size_t start_index = args.startIndex.value_or(0); - const size_t end_index = std::min(start_index + args.count.value_or(num_symbols), num_symbols); + const size_t end_index = + std::min(start_index + args.count.value_or(num_symbols), num_symbols); for (size_t i = start_index; i < end_index; ++i) { lldb::SBSymbol symbol = module.GetSymbolAtIndex(i); if (!symbol.IsValid()) diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index a027db1edb51e..8104616cac798 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -988,7 +988,8 @@ struct ModuleSymbolsArguments { /// The module path. std::string moduleName; - /// The index of the first symbol to return; if omitted, start at the beginning. + /// The index of the first symbol to return; if omitted, start at the + /// beginning. std::optional startIndex; /// The number of symbols to return; if omitted, all symbols are returned. From 626ba0cbfc37ea94185923293bd06cc928150a0b Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sun, 17 Aug 2025 01:15:28 +0200 Subject: [PATCH 32/44] split DSX to Debug Synthetic External columns --- .../src-ts/webview/symbols-table-view.ts | 55 +++++++++++++------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts index de39723497309..c052b6e2ac58f 100644 --- a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts @@ -13,12 +13,13 @@ function get_tabulator_hexa_formatter(padding: number): (cell: CellComponent) => } const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ - { title: "User ID", field: "userId", sorter: "number", widthGrow: 0.8 }, + { title: "User ID", field: "userId", headerTooltip: true, sorter: "number", widthGrow: 0.8 }, { title: "Name", field: "name", + headerTooltip: true, sorter: "string", - widthGrow: 3, + widthGrow: 2.5, minWidth: 200, tooltip : (_event: MouseEvent, cell: CellComponent) => { const rowData = cell.getRow().getData(); @@ -26,29 +27,46 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ } }, { - title: "DSX", + title: "Debug", + field: "isDebug", + headerTooltip: true, hozAlign: "center", widthGrow: 0.8, - headerTooltip : "Debug / Synthetic / External", - formatter: (cell: CellComponent) => { - const rowData = cell.getRow().getData(); - let label = ""; - label += rowData.isDebug ? "D" : ""; - label += rowData.isSynthetic ? "S" : ""; - label += rowData.isExternal ? "X" : ""; - return label; - }, - sorter: (_a, _b, aRow, bRow) => { - const valuesA = [aRow.getData().isDebug, aRow.getData().isSynthetic, aRow.getData().isExternal]; - const valuesB = [bRow.getData().isDebug, bRow.getData().isSynthetic, bRow.getData().isExternal]; - - return valuesA < valuesB ? -1 : valuesA > valuesB ? 1 : 0; + formatter: "tickCross", + formatterParams: { + tickElement: "✔", + crossElement: false, + } + }, + { + title: "Synthetic", + field: "isSynthetic", + headerTooltip: true, + hozAlign: "center", + widthGrow: 0.8, + formatter: "tickCross", + formatterParams: { + tickElement: "✔", + crossElement: false, + } + }, + { + title: "External", + field: "isExternal", + headerTooltip: true, + hozAlign: "center", + widthGrow: 0.8, + formatter: "tickCross", + formatterParams: { + tickElement: "✔", + crossElement: false, } }, { title: "Type", field: "type", sorter: "string" }, { title: "File Address", field: "fileAddress", + headerTooltip: true, sorter: "number", widthGrow : 1.25, formatter: get_tabulator_hexa_formatter(16), @@ -56,11 +74,12 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ { title: "Load Address", field: "loadAddress", + headerTooltip: true, sorter: "number", widthGrow : 1.25, formatter: get_tabulator_hexa_formatter(16), }, - { title: "Size", field: "size", sorter: "number", formatter: get_tabulator_hexa_formatter(8) }, + { title: "Size", field: "size", headerTooltip: true, sorter: "number", formatter: get_tabulator_hexa_formatter(8) }, ]; const vscode = acquireVsCodeApi(); From c4f59e4abf61e686ef460853890a203527ed0067 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sun, 17 Aug 2025 01:17:04 +0200 Subject: [PATCH 33/44] format --- .../API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py b/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py index 2a091a659e22d..c359cb449d3b2 100644 --- a/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py +++ b/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py @@ -16,7 +16,9 @@ def test_moduleSymbols(self): symbol_names = [] i = 0 while True: - next_symbol = self.dap_server.request_moduleSymbols(moduleName="a.out", startIndex=i, count=1) + next_symbol = self.dap_server.request_moduleSymbols( + moduleName="a.out", startIndex=i, count=1 + ) self.assertIn("symbols", next_symbol["body"]) result_symbols = next_symbol["body"]["symbols"] self.assertLessEqual(len(result_symbols), 1) From 012076ca8b46de660a46507ba2a2b20fcce2871b Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sun, 17 Aug 2025 01:20:29 +0200 Subject: [PATCH 34/44] remove console.log --- lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 273120800ff3a..6a1860ef5f475 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -96,9 +96,7 @@ export class SymbolsProvider extends DisposableContext { } private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { - console.log(`Getting symbols for module: ${moduleId}`); const symbols_response: { symbols: Array } = await session.customRequest("moduleSymbols", { moduleId, moduleName: '' }); - return symbols_response?.symbols || []; } From 024b566e5eb9dee74aeca4f1a10228cef82ca2d3 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Sun, 17 Aug 2025 01:24:58 +0200 Subject: [PATCH 35/44] format --- .../Python/lldbsuite/test/tools/lldb-dap/dap_server.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 0f28f90867b9c..6b4d8204447e9 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -1199,7 +1199,13 @@ def request_modules(self, startModule: int, moduleCount: int): } ) - def request_moduleSymbols(self, moduleId: str = "", moduleName: str = "", startIndex: int = 0, count: int = 0): + def request_moduleSymbols( + self, + moduleId: str = "", + moduleName: str = "", + startIndex: int = 0, + count: int = 0, + ): command_dict = { "command": "moduleSymbols", "type": "request", From 6fccbaa0ebe76e204ab47ced8280e05ecc460755 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Mon, 18 Aug 2025 22:30:22 +0200 Subject: [PATCH 36/44] add docs, organize and change userId -> id --- lldb/include/lldb/API/SBSymbol.h | 4 ++ lldb/include/lldb/API/SBTarget.h | 8 +++ .../Handler/ModuleSymbolsRequestHandler.cpp | 4 +- lldb/tools/lldb-dap/Protocol/DAPTypes.cpp | 6 +- lldb/tools/lldb-dap/Protocol/DAPTypes.h | 4 +- lldb/tools/lldb-dap/package.json | 2 +- lldb/tools/lldb-dap/src-ts/index.d.ts | 4 +- .../lldb-dap/src-ts/ui/symbols-provider.ts | 61 ++----------------- .../src-ts/ui/symbols-webview-html.ts | 51 ++++++++++++++++ .../src-ts/webview/symbols-table-view.ts | 14 ++--- .../lldb-dap/src-ts/webview/tsconfig.json | 15 +++++ lldb/unittests/DAP/DAPTypesTest.cpp | 4 +- 12 files changed, 103 insertions(+), 74 deletions(-) create mode 100644 lldb/tools/lldb-dap/src-ts/ui/symbols-webview-html.ts create mode 100644 lldb/tools/lldb-dap/src-ts/webview/tsconfig.json diff --git a/lldb/include/lldb/API/SBSymbol.h b/lldb/include/lldb/API/SBSymbol.h index 6777494bad1d2..fa75ba862c1f0 100644 --- a/lldb/include/lldb/API/SBSymbol.h +++ b/lldb/include/lldb/API/SBSymbol.h @@ -85,6 +85,10 @@ class LLDB_API SBSymbol { SymbolType GetType(); + /// Get the ID of this symbol, usually the original symbol table index. . + /// + /// \returns + /// Returns the ID of this symbol. uint32_t GetID(); bool operator==(const lldb::SBSymbol &rhs) const; diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 90fada3aea4ec..62cdd342a05e4 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -324,6 +324,14 @@ class LLDB_API SBTarget { lldb::SBModule FindModule(const lldb::SBFileSpec &file_spec); + /// Find a module with the given module specification. + /// + /// \param[in] module_spec + /// A lldb::SBModuleSpec object that contains module specification. + /// + /// \return + /// A lldb::SBModule object that represents the found module, or an + /// invalid SBModule object if no module was found. lldb::SBModule FindModule(const lldb::SBModuleSpec &module_spec); /// Find compile units related to *this target and passed source diff --git a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp index 213e4d1e7fd2f..98ec6f83f0d65 100644 --- a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp @@ -1,4 +1,4 @@ -//===-- DAPGetModuleSymbolsRequestHandler.cpp -----------------------------===// +//===-- ModuleSymbolsRequestHandler.cpp -----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -61,7 +61,7 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { continue; Symbol dap_symbol; - dap_symbol.userId = symbol.GetID(); + dap_symbol.id = symbol.GetID(); dap_symbol.type = symbol.GetType(); dap_symbol.isDebug = symbol.IsDebug(); dap_symbol.isSynthetic = symbol.IsSynthetic(); diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp index 54108872573c6..1d26bcea70d51 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp @@ -137,7 +137,7 @@ llvm::json::Value toJSON(const SourceLLDBData &SLD) { bool fromJSON(const llvm::json::Value &Params, Symbol &DS, llvm::json::Path P) { json::ObjectMapper O(Params, P); std::string type_str; - if (!(O && O.map("userId", DS.userId) && O.map("isDebug", DS.isDebug) && + if (!(O && O.map("id", DS.id) && O.map("isDebug", DS.isDebug) && O.map("isSynthetic", DS.isSynthetic) && O.map("isExternal", DS.isExternal) && O.map("type", type_str) && O.map("fileAddress", DS.fileAddress) && @@ -151,7 +151,7 @@ bool fromJSON(const llvm::json::Value &Params, Symbol &DS, llvm::json::Path P) { llvm::json::Value toJSON(const Symbol &DS) { json::Object result{ - {"userId", DS.userId}, + {"id", DS.id}, {"isDebug", DS.isDebug}, {"isSynthetic", DS.isSynthetic}, {"isExternal", DS.isExternal}, @@ -165,4 +165,4 @@ llvm::json::Value toJSON(const Symbol &DS) { return result; } -} // namespace lldb_dap::protocol \ No newline at end of file +} // namespace lldb_dap::protocol diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.h b/lldb/tools/lldb-dap/Protocol/DAPTypes.h index 9e7354e912485..7fccf1359a737 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.h +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.h @@ -49,8 +49,8 @@ bool fromJSON(const llvm::json::Value &, SourceLLDBData &, llvm::json::Path); llvm::json::Value toJSON(const SourceLLDBData &); struct Symbol { - /// The symbol uid. - uint32_t userId; + /// The symbol id, usually the original symbol table index. + uint32_t id; /// True if this symbol is debug information in a symbol. bool isDebug; diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json index fbf4d547723b3..f11b64aa72ae4 100644 --- a/lldb/tools/lldb-dap/package.json +++ b/lldb/tools/lldb-dap/package.json @@ -46,7 +46,7 @@ ], "main": "./out/extension", "scripts": { - "bundle-symbols-table-view": "npx esbuild src-ts/webview/symbols-table-view.ts --bundle --format=iife --outdir=./out/webview", + "bundle-symbols-table-view": "npx tsc -p src-ts/webview --noEmit && npx esbuild src-ts/webview/symbols-table-view.ts --bundle --format=iife --outdir=./out/webview", "bundle-tabulator": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_midnight.min.css ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_simple.min.css ./out/webview/", "bundle-webview": "npm run bundle-symbols-table-view && npm run bundle-tabulator", "vscode:prepublish": "npm run bundle-webview && tsc -p ./", diff --git a/lldb/tools/lldb-dap/src-ts/index.d.ts b/lldb/tools/lldb-dap/src-ts/index.d.ts index ec9dd09cfabb4..d4618f44dee7b 100644 --- a/lldb/tools/lldb-dap/src-ts/index.d.ts +++ b/lldb/tools/lldb-dap/src-ts/index.d.ts @@ -1,8 +1,8 @@ export {}; /// The symbol type we get from the lldb-dap server -export declare interface DAPSymbolType { - userId: number; +export declare interface SymbolType { + id: number; isDebug: boolean; isSynthetic: boolean; isExternal: boolean; diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 6a1860ef5f475..56ed630fb1963 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -4,7 +4,8 @@ import { DebugProtocol } from "@vscode/debugprotocol"; import { DebugSessionTracker } from "../debug-session-tracker"; import { DisposableContext } from "../disposable-context"; -import { DAPSymbolType } from ".."; +import { SymbolType } from ".."; +import { getSymbolsTableHTMLContent } from "./symbols-webview-html"; import { getDefaultConfigKey } from "../debug-configuration-provider"; export class SymbolsProvider extends DisposableContext { @@ -95,12 +96,12 @@ export class SymbolsProvider extends DisposableContext { } } - private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { - const symbols_response: { symbols: Array } = await session.customRequest("moduleSymbols", { moduleId, moduleName: '' }); + private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { + const symbols_response: { symbols: Array } = await session.customRequest("moduleSymbols", { moduleId, moduleName: '' }); return symbols_response?.symbols || []; } - private async showSymbolsInNewTab(moduleName: string, symbols: DAPSymbolType[]) { + private async showSymbolsInNewTab(moduleName: string, symbols: SymbolType[]) { const panel = vscode.window.createWebviewPanel( "lldb-dap.symbols", `Symbols for ${moduleName}`, @@ -121,60 +122,10 @@ export class SymbolsProvider extends DisposableContext { const tabulatorJsPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.js")); const symbolsTableScriptPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "symbols-table-view.js")); - panel.webview.html = this.getHTMLContentForSymbols(tabulatorJsPath, tabulatorCssPath, symbolsTableScriptPath); + panel.webview.html = getSymbolsTableHTMLContent(tabulatorJsPath, tabulatorCssPath, symbolsTableScriptPath); panel.webview.postMessage({ command: "updateSymbols", symbols: symbols }); } - private getHTMLContentForSymbols(tabulatorJsPath: vscode.Uri, tabulatorCssPath: vscode.Uri, symbolsTableScriptPath: vscode.Uri): string { - return ` - - - - - - - -
- - - -`; - } - private getExtensionResourcePath(): vscode.Uri { return vscode.Uri.joinPath(this.extensionContext.extensionUri, "out", "webview"); } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-webview-html.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-webview-html.ts new file mode 100644 index 0000000000000..88e24f3108787 --- /dev/null +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-webview-html.ts @@ -0,0 +1,51 @@ +import * as vscode from "vscode"; + +export function getSymbolsTableHTMLContent(tabulatorJsPath: vscode.Uri, tabulatorCssPath: vscode.Uri, symbolsTableScriptPath: vscode.Uri): string { + return ` + + + + + + + +
+ + + +`; +} \ No newline at end of file diff --git a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts index c052b6e2ac58f..b472b2643399c 100644 --- a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts @@ -1,7 +1,7 @@ import type { CellComponent, ColumnDefinition } from "tabulator-tables"; -import type { DAPSymbolType } from ".." +import type { SymbolType } from ".." -function get_tabulator_hexa_formatter(padding: number): (cell: CellComponent) => string { +function getTabulatorHexaFormatter(padding: number): (cell: CellComponent) => string { return (cell: CellComponent) => { const val = cell.getValue(); if (val === undefined || val === null) { @@ -13,7 +13,7 @@ function get_tabulator_hexa_formatter(padding: number): (cell: CellComponent) => } const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ - { title: "User ID", field: "userId", headerTooltip: true, sorter: "number", widthGrow: 0.8 }, + { title: "ID", field: "id", headerTooltip: true, sorter: "number", widthGrow: 0.6 }, { title: "Name", field: "name", @@ -69,7 +69,7 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ headerTooltip: true, sorter: "number", widthGrow : 1.25, - formatter: get_tabulator_hexa_formatter(16), + formatter: getTabulatorHexaFormatter(16), }, { title: "Load Address", @@ -77,9 +77,9 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ headerTooltip: true, sorter: "number", widthGrow : 1.25, - formatter: get_tabulator_hexa_formatter(16), + formatter: getTabulatorHexaFormatter(16), }, - { title: "Size", field: "size", headerTooltip: true, sorter: "number", formatter: get_tabulator_hexa_formatter(8) }, + { title: "Size", field: "size", headerTooltip: true, sorter: "number", formatter: getTabulatorHexaFormatter(8) }, ]; const vscode = acquireVsCodeApi(); @@ -93,7 +93,7 @@ const SYMBOLS_TABLE = new Tabulator("#symbols-table", { data: previousState?.symbols || [], }); -function updateSymbolsTable(symbols: DAPSymbolType[]) { +function updateSymbolsTable(symbols: SymbolType[]) { SYMBOLS_TABLE.setData(symbols); } diff --git a/lldb/tools/lldb-dap/src-ts/webview/tsconfig.json b/lldb/tools/lldb-dap/src-ts/webview/tsconfig.json new file mode 100644 index 0000000000000..cfe64fc4b989f --- /dev/null +++ b/lldb/tools/lldb-dap/src-ts/webview/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "module": "esnext", + "outDir": "out", + "rootDir": ".", + "sourceMap": true, + "strict": true, + "noEmit": true, + "target": "es2017" + }, + "include": [ + "./" + ], +} diff --git a/lldb/unittests/DAP/DAPTypesTest.cpp b/lldb/unittests/DAP/DAPTypesTest.cpp index b2721aaebbb20..f398c54b724a0 100644 --- a/lldb/unittests/DAP/DAPTypesTest.cpp +++ b/lldb/unittests/DAP/DAPTypesTest.cpp @@ -35,7 +35,7 @@ TEST(DAPTypesTest, SourceLLDBData) { TEST(DAPTypesTest, DAPSymbol) { Symbol symbol; - symbol.userId = 42; + symbol.id = 42; symbol.isDebug = true; symbol.isExternal = false; symbol.isSynthetic = true; @@ -48,7 +48,7 @@ TEST(DAPTypesTest, DAPSymbol) { llvm::Expected deserialized_symbol = roundtripJSON(symbol); ASSERT_THAT_EXPECTED(deserialized_symbol, llvm::Succeeded()); - EXPECT_EQ(symbol.userId, deserialized_symbol->userId); + EXPECT_EQ(symbol.id, deserialized_symbol->id); EXPECT_EQ(symbol.isDebug, deserialized_symbol->isDebug); EXPECT_EQ(symbol.isExternal, deserialized_symbol->isExternal); EXPECT_EQ(symbol.isSynthetic, deserialized_symbol->isSynthetic); From d61715ee547a3d2e413d14ff3316d4aff68add53 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Mon, 18 Aug 2025 23:21:06 +0200 Subject: [PATCH 37/44] use capabilities event to determine SupportsModuleSymbolsRequest instead of lldb version --- lldb/tools/lldb-dap/DAP.cpp | 21 +++++++++++++++ lldb/tools/lldb-dap/DAP.h | 3 +++ lldb/tools/lldb-dap/EventHelper.cpp | 8 ++++++ lldb/tools/lldb-dap/EventHelper.h | 3 +++ .../ConfigurationDoneRequestHandler.cpp | 4 +++ lldb/tools/lldb-dap/Handler/RequestHandler.h | 3 +++ .../tools/lldb-dap/Protocol/ProtocolTypes.cpp | 4 +++ lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 5 +++- .../lldb-dap/src-ts/debug-session-tracker.ts | 19 ++++++++----- .../lldb-dap/src-ts/ui/symbols-provider.ts | 27 ++++--------------- 10 files changed, 68 insertions(+), 29 deletions(-) diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 16280c3535a3b..0673043357d81 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -1258,6 +1258,27 @@ protocol::Capabilities DAP::GetCapabilities() { return capabilities; } +protocol::Capabilities DAP::GetCustomCapabilities() { + protocol::Capabilities capabilities; + + // Add all custom capabilities here. + const llvm::DenseSet all_custom_features = { + protocol::eAdapterFeatureSupportsModuleSymbolsRequest, + }; + + for (auto &kv : request_handlers) { + llvm::SmallDenseSet features = + kv.second->GetSupportedFeatures(); + + for (auto &feature : features) { + if (all_custom_features.contains(feature)) + capabilities.supportedFeatures.insert(feature); + } + } + + return capabilities; +} + void DAP::StartEventThread() { event_thread = std::thread(&DAP::EventThread, this); } diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h index 0b6373fb80381..04f70f76a09cd 100644 --- a/lldb/tools/lldb-dap/DAP.h +++ b/lldb/tools/lldb-dap/DAP.h @@ -367,6 +367,9 @@ struct DAP final : private DAPTransport::MessageHandler { /// The set of capabilities supported by this adapter. protocol::Capabilities GetCapabilities(); + /// The set of custom capabilities supported by this adapter. + protocol::Capabilities GetCustomCapabilities(); + /// Debuggee will continue from stopped state. void WillContinue() { variables.Clear(); } diff --git a/lldb/tools/lldb-dap/EventHelper.cpp b/lldb/tools/lldb-dap/EventHelper.cpp index 364cc7ab4ef8c..3017af1c717a5 100644 --- a/lldb/tools/lldb-dap/EventHelper.cpp +++ b/lldb/tools/lldb-dap/EventHelper.cpp @@ -59,6 +59,14 @@ void SendTargetBasedCapabilities(DAP &dap) { dap.Send(protocol::Event{"capabilities", body}); } +void SendCustomCapabilities(DAP &dap) { + protocol::CapabilitiesEventBody body; + body.capabilities = dap.GetCustomCapabilities(); + + // Notify the client about the custom capabilities. + dap.Send(protocol::Event{"capabilities", body}); +} + // "ProcessEvent": { // "allOf": [ // { "$ref": "#/definitions/Event" }, diff --git a/lldb/tools/lldb-dap/EventHelper.h b/lldb/tools/lldb-dap/EventHelper.h index 72ad5308a2b0c..a79e16209e1d2 100644 --- a/lldb/tools/lldb-dap/EventHelper.h +++ b/lldb/tools/lldb-dap/EventHelper.h @@ -20,6 +20,9 @@ enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch }; /// Update capabilities based on the configured target. void SendTargetBasedCapabilities(DAP &dap); +/// Send lldb-dap custom capabilities. +void SendCustomCapabilities(DAP &dap); + void SendProcessEvent(DAP &dap, LaunchMethod launch_method); llvm::Error SendThreadStoppedEvent(DAP &dap, bool on_entry = false); diff --git a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp index e7735a705d0aa..8fc54661d82a3 100644 --- a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp @@ -46,6 +46,10 @@ ConfigurationDoneRequestHandler::Run(const ConfigurationDoneArguments &) const { // may have different capabilities than the final target. SendTargetBasedCapabilities(dap); + /// Send custom capabilities to the client. + /// This is consumed by the lldb-dap specific editor extension. + SendCustomCapabilities(dap); + // Clients can request a baseline of currently existing threads after // we acknowledge the configurationDone request. // Client requests the baseline of currently existing threads after diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index 8e2e408221fed..cc5c87c9bddf9 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -601,6 +601,9 @@ class ModuleSymbolsRequestHandler public: using RequestHandler::RequestHandler; static llvm::StringLiteral GetCommand() { return "moduleSymbols"; } + FeatureSet GetSupportedFeatures() const override { + return {protocol::eAdapterFeatureSupportsModuleSymbolsRequest}; + } llvm::Expected Run(const protocol::ModuleSymbolsArguments &args) const override; }; diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp index 369858c3a5f4b..60d272b3bfcf8 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp @@ -335,6 +335,8 @@ static llvm::StringLiteral ToString(AdapterFeature feature) { return "supportsWriteMemoryRequest"; case eAdapterFeatureTerminateDebuggee: return "supportTerminateDebuggee"; + case eAdapterFeatureSupportsModuleSymbolsRequest: + return "supportsModuleSymbolsRequest"; } llvm_unreachable("unhandled adapter feature."); } @@ -406,6 +408,8 @@ bool fromJSON(const llvm::json::Value &Params, AdapterFeature &feature, eAdapterFeatureValueFormattingOptions) .Case("supportsWriteMemoryRequest", eAdapterFeatureWriteMemoryRequest) .Case("supportTerminateDebuggee", eAdapterFeatureTerminateDebuggee) + .Case("supportsModuleSymbolsRequest", + eAdapterFeatureSupportsModuleSymbolsRequest) .Default(std::nullopt); if (!parsedFeature) { diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h index c4be7911a662b..8043a99ee0d80 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h @@ -242,8 +242,11 @@ enum AdapterFeature : unsigned { /// The debug adapter supports the `terminateDebuggee` attribute on the /// `disconnect` request. eAdapterFeatureTerminateDebuggee, + /// The debug adapter supports the `supportsModuleSymbols` request. + /// This request is a custom request of lldb-dap. + eAdapterFeatureSupportsModuleSymbolsRequest, eAdapterFeatureFirst = eAdapterFeatureANSIStyling, - eAdapterFeatureLast = eAdapterFeatureTerminateDebuggee, + eAdapterFeatureLast = eAdapterFeatureSupportsModuleSymbolsRequest, }; bool fromJSON(const llvm::json::Value &, AdapterFeature &, llvm::json::Path); llvm::json::Value toJSON(const AdapterFeature &); diff --git a/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts b/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts index 21c3201b0cbdb..ab0fd078606f5 100644 --- a/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts +++ b/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts @@ -1,12 +1,17 @@ import { DebugProtocol } from "@vscode/debugprotocol"; import * as vscode from "vscode"; +export interface LLDBDapCapabilities extends DebugProtocol.Capabilities { + /** The debug adapter supports the `moduleSymbols` request. */ + supportsModuleSymbolsRequest?: boolean; +} + /** A helper type for mapping event types to their corresponding data type. */ // prettier-ignore interface EventMap { "module": DebugProtocol.ModuleEvent; "exited": DebugProtocol.ExitedEvent; - "initialized": DebugProtocol.InitializedEvent; + "capabilities": DebugProtocol.CapabilitiesEvent; } /** A type assertion to check if a ProtocolMessage is an event or if it is a specific event. */ @@ -40,7 +45,8 @@ export class DebugSessionTracker private modulesChanged = new vscode.EventEmitter< vscode.DebugSession | undefined >(); - private sessionInitialized = new vscode.EventEmitter(); + private sessionGotCapabilities = + new vscode.EventEmitter<[ vscode.DebugSession, LLDBDapCapabilities ]>(); private sessionExited = new vscode.EventEmitter(); /** @@ -52,8 +58,9 @@ export class DebugSessionTracker this.modulesChanged.event; /** Fired when a debug session is initialized. */ - onDidInitializeSession: vscode.Event = - this.sessionInitialized.event; + onDidGetSessionCapabilities: + vscode.Event<[ vscode.DebugSession, LLDBDapCapabilities ]> = + this.sessionGotCapabilities.event; /** Fired when a debug session is exiting. */ onDidExitSession: vscode.Event = @@ -159,8 +166,8 @@ export class DebugSessionTracker ); this.sessionExited.fire(session); - } else if (isEvent(message, "initialized")) { - this.sessionInitialized.fire(session); + } else if (isEvent(message, "capabilities")) { + this.sessionGotCapabilities.fire([ session, message.body.capabilities ]); } } } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 56ed630fb1963..5e5fb0b4c237f 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -35,14 +35,11 @@ export class SymbolsProvider extends DisposableContext { }, )); - this.tracker.onDidInitializeSession((session) => { - this.GetLLDBServerVersion(session).then((version) => { - if (version !== undefined) { - if (version[0] >= 22) { - vscode.commands.executeCommand("setContext", "lldb-dap.supportsModuleSymbolsRequest", true); - } - } - }); + this.tracker.onDidGetSessionCapabilities(([ _session, capabilities ]) => { + if (capabilities.supportsModuleSymbolsRequest) { + vscode.commands.executeCommand( + "setContext", "lldb-dap.supportsModuleSymbolsRequest", true); + } }); this.tracker.onDidExitSession((_session) => { @@ -50,20 +47,6 @@ export class SymbolsProvider extends DisposableContext { }); } - private async GetLLDBServerVersion(session: vscode.DebugSession): Promise<[number, number, number] | undefined> { - const commandEscapePrefix = session.configuration.commandEscapePrefix || getDefaultConfigKey("commandEscapePrefix"); - const response = await session.customRequest("evaluate", { expression: commandEscapePrefix + "version", context: "repl" }); - - const versionLine = response.result?.split("\n")[0]; - if (!versionLine) return undefined; - - const versionMatch = versionLine.match(/(\d+)\.(\d+)\.(\d+)/); - if (!versionMatch) return undefined; - - const [major, minor, patch] = versionMatch.slice(1, 4).map(Number); - return [major, minor, patch]; - } - private async SelectModuleAndShowSymbols(session: vscode.DebugSession) { const modules = this.tracker.debugSessionModules(session); if (!modules || modules.length === 0) { From f0fc40c711046edfa276d007a3b443283ca992b9 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Tue, 19 Aug 2025 10:05:51 +0200 Subject: [PATCH 38/44] using better tick element from tabulator --- .../lldb-dap/src-ts/webview/symbols-table-view.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts index b472b2643399c..8454378abef16 100644 --- a/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts +++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts @@ -1,6 +1,11 @@ import type { CellComponent, ColumnDefinition } from "tabulator-tables"; import type { SymbolType } from ".." +/// SVG from https://github.com/olifolkerd/tabulator/blob/master/src/js/modules/Format/defaults/formatters/tickCross.js +/// but with the default font color. +/// hopefully in the future we can set the color as parameter: https://github.com/olifolkerd/tabulator/pull/4791 +const TICK_ELEMENT = ``; + function getTabulatorHexaFormatter(padding: number): (cell: CellComponent) => string { return (cell: CellComponent) => { const val = cell.getValue(); @@ -34,7 +39,7 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ widthGrow: 0.8, formatter: "tickCross", formatterParams: { - tickElement: "✔", + tickElement: TICK_ELEMENT, crossElement: false, } }, @@ -46,7 +51,7 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ widthGrow: 0.8, formatter: "tickCross", formatterParams: { - tickElement: "✔", + tickElement: TICK_ELEMENT, crossElement: false, } }, @@ -58,7 +63,7 @@ const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [ widthGrow: 0.8, formatter: "tickCross", formatterParams: { - tickElement: "✔", + tickElement: TICK_ELEMENT, crossElement: false, } }, From 3aea6b666fdfd44e6b70d10b62d0ffe104a44b67 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Tue, 19 Aug 2025 10:25:05 +0200 Subject: [PATCH 39/44] Sending extra capabilities event together --- lldb/include/lldb/API/SBSymbol.h | 2 +- .../moduleSymbols/TestDAP_moduleSymbols.py | 2 +- lldb/tools/lldb-dap/EventHelper.cpp | 34 +++++++++++-------- lldb/tools/lldb-dap/EventHelper.h | 7 ++-- .../ConfigurationDoneRequestHandler.cpp | 8 ++--- .../Handler/ModuleSymbolsRequestHandler.cpp | 2 +- 6 files changed, 28 insertions(+), 27 deletions(-) diff --git a/lldb/include/lldb/API/SBSymbol.h b/lldb/include/lldb/API/SBSymbol.h index fa75ba862c1f0..606baba7bb464 100644 --- a/lldb/include/lldb/API/SBSymbol.h +++ b/lldb/include/lldb/API/SBSymbol.h @@ -85,7 +85,7 @@ class LLDB_API SBSymbol { SymbolType GetType(); - /// Get the ID of this symbol, usually the original symbol table index. . + /// Get the ID of this symbol, usually the original symbol table index. /// /// \returns /// Returns the ID of this symbol. diff --git a/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py b/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py index c359cb449d3b2..b99edf369a7fd 100644 --- a/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py +++ b/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py @@ -8,7 +8,7 @@ class TestDAP_moduleSymbols(lldbdap_testcase.DAPTestCaseBase): def test_moduleSymbols(self): """ - Test that the stack frame without a module still has assembly source. + Test that the moduleSymbols request returns correct symbols from the module. """ program = self.getBuildArtifact("a.out") self.build_and_launch(program) diff --git a/lldb/tools/lldb-dap/EventHelper.cpp b/lldb/tools/lldb-dap/EventHelper.cpp index 3017af1c717a5..bfb05a387d04d 100644 --- a/lldb/tools/lldb-dap/EventHelper.cpp +++ b/lldb/tools/lldb-dap/EventHelper.cpp @@ -38,33 +38,37 @@ static void SendThreadExitedEvent(DAP &dap, lldb::tid_t tid) { dap.SendJSON(llvm::json::Value(std::move(event))); } -void SendTargetBasedCapabilities(DAP &dap) { +/// Get capabilities based on the configured target. +static llvm::DenseSet GetTargetBasedCapabilities(DAP &dap) { + llvm::DenseSet capabilities; if (!dap.target.IsValid()) - return; - - protocol::CapabilitiesEventBody body; + return capabilities; const llvm::StringRef target_triple = dap.target.GetTriple(); if (target_triple.starts_with("x86")) - body.capabilities.supportedFeatures.insert( - protocol::eAdapterFeatureStepInTargetsRequest); + capabilities.insert(protocol::eAdapterFeatureStepInTargetsRequest); // We only support restarting launch requests not attach requests. if (dap.last_launch_request) - body.capabilities.supportedFeatures.insert( - protocol::eAdapterFeatureRestartRequest); + capabilities.insert(protocol::eAdapterFeatureRestartRequest); - // Only notify the client if supportedFeatures changed. - if (!body.capabilities.supportedFeatures.empty()) - dap.Send(protocol::Event{"capabilities", body}); + return capabilities; } -void SendCustomCapabilities(DAP &dap) { +void SendExtraCapabilities(DAP &dap) { + protocol::Capabilities capabilities = dap.GetCustomCapabilities(); + llvm::DenseSet target_capabilities = + GetTargetBasedCapabilities(dap); + + capabilities.supportedFeatures.insert(target_capabilities.begin(), + target_capabilities.end()); + protocol::CapabilitiesEventBody body; - body.capabilities = dap.GetCustomCapabilities(); + body.capabilities = std::move(capabilities); - // Notify the client about the custom capabilities. - dap.Send(protocol::Event{"capabilities", body}); + // Only notify the client if supportedFeatures changed. + if (!body.capabilities.supportedFeatures.empty()) + dap.Send(protocol::Event{"capabilities", std::move(body)}); } // "ProcessEvent": { diff --git a/lldb/tools/lldb-dap/EventHelper.h b/lldb/tools/lldb-dap/EventHelper.h index a79e16209e1d2..592c1b81c46af 100644 --- a/lldb/tools/lldb-dap/EventHelper.h +++ b/lldb/tools/lldb-dap/EventHelper.h @@ -17,11 +17,8 @@ struct DAP; enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch }; -/// Update capabilities based on the configured target. -void SendTargetBasedCapabilities(DAP &dap); - -/// Send lldb-dap custom capabilities. -void SendCustomCapabilities(DAP &dap); +/// Sends target based capabilities and lldb-dap custom capabilities. +void SendExtraCapabilities(DAP &dap); void SendProcessEvent(DAP &dap, LaunchMethod launch_method); diff --git a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp index 8fc54661d82a3..1bfe7b7f6ef5c 100644 --- a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp @@ -9,6 +9,7 @@ #include "DAP.h" #include "EventHelper.h" #include "LLDBUtils.h" +#include "Protocol/ProtocolEvents.h" #include "Protocol/ProtocolRequests.h" #include "ProtocolUtils.h" #include "RequestHandler.h" @@ -44,11 +45,10 @@ ConfigurationDoneRequestHandler::Run(const ConfigurationDoneArguments &) const { // Waiting until 'configurationDone' to send target based capabilities in case // the launch or attach scripts adjust the target. The initial dummy target // may have different capabilities than the final target. - SendTargetBasedCapabilities(dap); - /// Send custom capabilities to the client. - /// This is consumed by the lldb-dap specific editor extension. - SendCustomCapabilities(dap); + /// Also send here custom capabilities to the client, which is consumed by the + /// lldb-dap specific editor extension. + SendExtraCapabilities(dap); // Clients can request a baseline of currently existing threads after // we acknowledge the configurationDone request. diff --git a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp index 98ec6f83f0d65..f5bfbe53b8e67 100644 --- a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp @@ -1,4 +1,4 @@ -//===-- ModuleSymbolsRequestHandler.cpp -----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. From 1f3ae2161dfcb170e2f07bde6207a057022d51b6 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Tue, 19 Aug 2025 10:30:34 +0200 Subject: [PATCH 40/44] rename js --- lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts | 8 ++++---- lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts b/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts index ab0fd078606f5..6e89d441bbcf0 100644 --- a/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts +++ b/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts @@ -45,7 +45,7 @@ export class DebugSessionTracker private modulesChanged = new vscode.EventEmitter< vscode.DebugSession | undefined >(); - private sessionGotCapabilities = + private sessionReceivedCapabilities = new vscode.EventEmitter<[ vscode.DebugSession, LLDBDapCapabilities ]>(); private sessionExited = new vscode.EventEmitter(); @@ -58,9 +58,9 @@ export class DebugSessionTracker this.modulesChanged.event; /** Fired when a debug session is initialized. */ - onDidGetSessionCapabilities: + onDidReceiveSessionCapabilities: vscode.Event<[ vscode.DebugSession, LLDBDapCapabilities ]> = - this.sessionGotCapabilities.event; + this.sessionReceivedCapabilities.event; /** Fired when a debug session is exiting. */ onDidExitSession: vscode.Event = @@ -167,7 +167,7 @@ export class DebugSessionTracker this.sessionExited.fire(session); } else if (isEvent(message, "capabilities")) { - this.sessionGotCapabilities.fire([ session, message.body.capabilities ]); + this.sessionReceivedCapabilities.fire([ session, message.body.capabilities ]); } } } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 5e5fb0b4c237f..9a2d60bf2d6b1 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -35,7 +35,7 @@ export class SymbolsProvider extends DisposableContext { }, )); - this.tracker.onDidGetSessionCapabilities(([ _session, capabilities ]) => { + this.tracker.onDidReceiveSessionCapabilities(([ _session, capabilities ]) => { if (capabilities.supportsModuleSymbolsRequest) { vscode.commands.executeCommand( "setContext", "lldb-dap.supportsModuleSymbolsRequest", true); From 15fd62b171b63b5cf7fd997c26163c7d8747800d Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Tue, 19 Aug 2025 21:56:35 +0200 Subject: [PATCH 41/44] add __lldb_ prefix --- lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp | 4 ++-- lldb/tools/lldb-dap/Handler/RequestHandler.h | 2 +- lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp index f5bfbe53b8e67..6e50ee122c41f 100644 --- a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp @@ -31,7 +31,7 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { if (!lldb_private::UUID::DecodeUUIDBytesFromString(args.moduleId, uuid_bytes) .empty()) - return llvm::make_error("Invalid module ID"); + return llvm::make_error("invalid module ID"); module_spec.SetUUIDBytes(uuid_bytes.data(), uuid_bytes.size()); } @@ -49,7 +49,7 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const { std::vector &symbols = response.symbols; lldb::SBModule module = dap.target.FindModule(module_spec); if (!module.IsValid()) - return llvm::make_error("Module not found"); + return llvm::make_error("module not found"); const size_t num_symbols = module.GetNumSymbols(); const size_t start_index = args.startIndex.value_or(0); diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index cc5c87c9bddf9..473085cafaad4 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -600,7 +600,7 @@ class ModuleSymbolsRequestHandler llvm::Expected> { public: using RequestHandler::RequestHandler; - static llvm::StringLiteral GetCommand() { return "moduleSymbols"; } + static llvm::StringLiteral GetCommand() { return "__lldb_moduleSymbols"; } FeatureSet GetSupportedFeatures() const override { return {protocol::eAdapterFeatureSupportsModuleSymbolsRequest}; } diff --git a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts index 9a2d60bf2d6b1..84b9387ffe49f 100644 --- a/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts +++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts @@ -80,7 +80,7 @@ export class SymbolsProvider extends DisposableContext { } private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise { - const symbols_response: { symbols: Array } = await session.customRequest("moduleSymbols", { moduleId, moduleName: '' }); + const symbols_response: { symbols: Array } = await session.customRequest("__lldb_moduleSymbols", { moduleId, moduleName: '' }); return symbols_response?.symbols || []; } From ca40bc1ea0bf86d684101eaf2f5e23978d5bf545 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Wed, 20 Aug 2025 02:38:36 +0200 Subject: [PATCH 42/44] add __lldb_ prefix in test --- .../packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index 6b4d8204447e9..7acb9c89b8b7d 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -1207,7 +1207,7 @@ def request_moduleSymbols( count: int = 0, ): command_dict = { - "command": "moduleSymbols", + "command": "__lldb_moduleSymbols", "type": "request", "arguments": { "moduleId": moduleId, From 300819c1bd55ed307e34b76acc29f071b6c426d8 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Wed, 20 Aug 2025 23:47:53 +0200 Subject: [PATCH 43/44] export Symbol::GetTypeAsString and Symbol::GetTypeFromString --- lldb/include/lldb/API/SBSymbol.h | 6 + lldb/include/lldb/Symbol/Symbol.h | 5 + lldb/source/API/SBSymbol.cpp | 8 ++ lldb/source/Symbol/Symbol.cpp | 144 ++++++++++++---------- lldb/tools/lldb-dap/Protocol/DAPTypes.cpp | 105 +--------------- 5 files changed, 98 insertions(+), 170 deletions(-) diff --git a/lldb/include/lldb/API/SBSymbol.h b/lldb/include/lldb/API/SBSymbol.h index 606baba7bb464..a93bc7a7ae074 100644 --- a/lldb/include/lldb/API/SBSymbol.h +++ b/lldb/include/lldb/API/SBSymbol.h @@ -108,6 +108,12 @@ class LLDB_API SBSymbol { /// Returns true if the symbol is a debug symbol. bool IsDebug(); + /// Get the string representation of a symbol type. + static const char *GetTypeAsString(lldb::SymbolType symbol_type); + + /// Get the symbol type from a string representation. + static lldb::SymbolType GetTypeFromString(const char *str); + protected: lldb_private::Symbol *get(); diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h index 0674e56ef43f5..b994c34e46493 100644 --- a/lldb/include/lldb/Symbol/Symbol.h +++ b/lldb/include/lldb/Symbol/Symbol.h @@ -15,6 +15,7 @@ #include "lldb/Symbol/SymbolContextScope.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/UserID.h" +#include "lldb/lldb-enumerations.h" #include "lldb/lldb-private.h" #include "llvm/Support/JSON.h" @@ -301,6 +302,10 @@ class Symbol : public SymbolContextScope { bool operator==(const Symbol &rhs) const; + static const char *GetTypeAsString(lldb::SymbolType symbol_type); + + static lldb::SymbolType GetTypeFromString(const char *str); + protected: // This is the internal guts of ResolveReExportedSymbol, it assumes // reexport_name is not null, and that module_spec is valid. We track the diff --git a/lldb/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp index 7bcc7f99079c4..e51927146b057 100644 --- a/lldb/source/API/SBSymbol.cpp +++ b/lldb/source/API/SBSymbol.cpp @@ -224,3 +224,11 @@ bool SBSymbol::IsDebug() { return m_opaque_ptr->IsDebug(); return false; } + +const char *SBSymbol::GetTypeAsString(lldb::SymbolType symbol_type) { + return Symbol::GetTypeAsString(symbol_type); +} + +lldb::SymbolType SBSymbol::GetTypeFromString(const char *str) { + return Symbol::GetTypeFromString(str); +} diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp index d6689a647062a..40497dbccc5c3 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -392,45 +392,8 @@ bool Symbol::Compare(ConstString name, SymbolType type) const { return false; } -#define ENUM_TO_CSTRING(x) \ - case eSymbolType##x: \ - return #x; - const char *Symbol::GetTypeAsString() const { - switch (m_type) { - ENUM_TO_CSTRING(Invalid); - ENUM_TO_CSTRING(Absolute); - ENUM_TO_CSTRING(Code); - ENUM_TO_CSTRING(Resolver); - ENUM_TO_CSTRING(Data); - ENUM_TO_CSTRING(Trampoline); - ENUM_TO_CSTRING(Runtime); - ENUM_TO_CSTRING(Exception); - ENUM_TO_CSTRING(SourceFile); - ENUM_TO_CSTRING(HeaderFile); - ENUM_TO_CSTRING(ObjectFile); - ENUM_TO_CSTRING(CommonBlock); - ENUM_TO_CSTRING(Block); - ENUM_TO_CSTRING(Local); - ENUM_TO_CSTRING(Param); - ENUM_TO_CSTRING(Variable); - ENUM_TO_CSTRING(VariableType); - ENUM_TO_CSTRING(LineEntry); - ENUM_TO_CSTRING(LineHeader); - ENUM_TO_CSTRING(ScopeBegin); - ENUM_TO_CSTRING(ScopeEnd); - ENUM_TO_CSTRING(Additional); - ENUM_TO_CSTRING(Compiler); - ENUM_TO_CSTRING(Instrumentation); - ENUM_TO_CSTRING(Undefined); - ENUM_TO_CSTRING(ObjCClass); - ENUM_TO_CSTRING(ObjCMetaClass); - ENUM_TO_CSTRING(ObjCIVar); - ENUM_TO_CSTRING(ReExported); - default: - break; - } - return ""; + return GetTypeAsString(static_cast(m_type)); } void Symbol::CalculateSymbolContext(SymbolContext *sc) { @@ -774,6 +737,79 @@ bool Symbol::operator==(const Symbol &rhs) const { return true; } +#define ENUM_TO_CSTRING(x) \ + case eSymbolType##x: \ + return #x; + +const char *Symbol::GetTypeAsString(lldb::SymbolType symbol_type) { + switch (symbol_type) { + ENUM_TO_CSTRING(Invalid); + ENUM_TO_CSTRING(Absolute); + ENUM_TO_CSTRING(Code); + ENUM_TO_CSTRING(Resolver); + ENUM_TO_CSTRING(Data); + ENUM_TO_CSTRING(Trampoline); + ENUM_TO_CSTRING(Runtime); + ENUM_TO_CSTRING(Exception); + ENUM_TO_CSTRING(SourceFile); + ENUM_TO_CSTRING(HeaderFile); + ENUM_TO_CSTRING(ObjectFile); + ENUM_TO_CSTRING(CommonBlock); + ENUM_TO_CSTRING(Block); + ENUM_TO_CSTRING(Local); + ENUM_TO_CSTRING(Param); + ENUM_TO_CSTRING(Variable); + ENUM_TO_CSTRING(VariableType); + ENUM_TO_CSTRING(LineEntry); + ENUM_TO_CSTRING(LineHeader); + ENUM_TO_CSTRING(ScopeBegin); + ENUM_TO_CSTRING(ScopeEnd); + ENUM_TO_CSTRING(Additional); + ENUM_TO_CSTRING(Compiler); + ENUM_TO_CSTRING(Instrumentation); + ENUM_TO_CSTRING(Undefined); + ENUM_TO_CSTRING(ObjCClass); + ENUM_TO_CSTRING(ObjCMetaClass); + ENUM_TO_CSTRING(ObjCIVar); + ENUM_TO_CSTRING(ReExported); + } + return ""; +} + +lldb::SymbolType Symbol::GetTypeFromString(const char *str) { + std::string str_lower = llvm::StringRef(str).lower(); + return llvm::StringSwitch(str_lower) + .Case("absolute", eSymbolTypeAbsolute) + .Case("code", eSymbolTypeCode) + .Case("resolver", eSymbolTypeResolver) + .Case("data", eSymbolTypeData) + .Case("trampoline", eSymbolTypeTrampoline) + .Case("runtime", eSymbolTypeRuntime) + .Case("exception", eSymbolTypeException) + .Case("sourcefile", eSymbolTypeSourceFile) + .Case("headerfile", eSymbolTypeHeaderFile) + .Case("objectfile", eSymbolTypeObjectFile) + .Case("commonblock", eSymbolTypeCommonBlock) + .Case("block", eSymbolTypeBlock) + .Case("local", eSymbolTypeLocal) + .Case("param", eSymbolTypeParam) + .Case("variable", eSymbolTypeVariable) + .Case("variableType", eSymbolTypeVariableType) + .Case("lineentry", eSymbolTypeLineEntry) + .Case("lineheader", eSymbolTypeLineHeader) + .Case("scopebegin", eSymbolTypeScopeBegin) + .Case("scopeend", eSymbolTypeScopeEnd) + .Case("additional,", eSymbolTypeAdditional) + .Case("compiler", eSymbolTypeCompiler) + .Case("instrumentation", eSymbolTypeInstrumentation) + .Case("undefined", eSymbolTypeUndefined) + .Case("objcclass", eSymbolTypeObjCClass) + .Case("objcmetaclass", eSymbolTypeObjCMetaClass) + .Case("objcivar", eSymbolTypeObjCIVar) + .Case("reexported", eSymbolTypeReExported) + .Default(eSymbolTypeInvalid); +} + namespace llvm { namespace json { @@ -804,36 +840,8 @@ bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol, bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type, llvm::json::Path path) { if (auto str = value.getAsString()) { - type = llvm::StringSwitch(*str) - .Case("absolute", eSymbolTypeAbsolute) - .Case("code", eSymbolTypeCode) - .Case("resolver", eSymbolTypeResolver) - .Case("data", eSymbolTypeData) - .Case("trampoline", eSymbolTypeTrampoline) - .Case("runtime", eSymbolTypeRuntime) - .Case("exception", eSymbolTypeException) - .Case("sourcefile", eSymbolTypeSourceFile) - .Case("headerfile", eSymbolTypeHeaderFile) - .Case("objectfile", eSymbolTypeObjectFile) - .Case("commonblock", eSymbolTypeCommonBlock) - .Case("block", eSymbolTypeBlock) - .Case("local", eSymbolTypeLocal) - .Case("param", eSymbolTypeParam) - .Case("variable", eSymbolTypeVariable) - .Case("variableType", eSymbolTypeVariableType) - .Case("lineentry", eSymbolTypeLineEntry) - .Case("lineheader", eSymbolTypeLineHeader) - .Case("scopebegin", eSymbolTypeScopeBegin) - .Case("scopeend", eSymbolTypeScopeEnd) - .Case("additional,", eSymbolTypeAdditional) - .Case("compiler", eSymbolTypeCompiler) - .Case("instrumentation", eSymbolTypeInstrumentation) - .Case("undefined", eSymbolTypeUndefined) - .Case("objcclass", eSymbolTypeObjCClass) - .Case("objcmetaClass", eSymbolTypeObjCMetaClass) - .Case("objcivar", eSymbolTypeObjCIVar) - .Case("reexporte", eSymbolTypeReExported) - .Default(eSymbolTypeInvalid); + llvm::StringRef str_ref = str.value_or(""); + type = Symbol::GetTypeFromString(str_ref.data()); if (type == eSymbolTypeInvalid) { path.report("invalid symbol type"); diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp index 1d26bcea70d51..a14ed9e521f48 100644 --- a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp @@ -1,110 +1,11 @@ #include "Protocol/DAPTypes.h" +#include "lldb/API/SBSymbol.h" #include "lldb/lldb-enumerations.h" using namespace llvm; namespace lldb_dap::protocol { -static std::string SymbolTypeToString(lldb::SymbolType symbol_type) { - switch (symbol_type) { - case lldb::eSymbolTypeInvalid: - return "Invalid"; - case lldb::eSymbolTypeAbsolute: - return "Absolute"; - case lldb::eSymbolTypeCode: - return "Code"; - case lldb::eSymbolTypeResolver: - return "Resolver"; - case lldb::eSymbolTypeData: - return "Data"; - case lldb::eSymbolTypeTrampoline: - return "Trampoline"; - case lldb::eSymbolTypeRuntime: - return "Runtime"; - case lldb::eSymbolTypeException: - return "Exception"; - case lldb::eSymbolTypeSourceFile: - return "SourceFile"; - case lldb::eSymbolTypeHeaderFile: - return "HeaderFile"; - case lldb::eSymbolTypeObjectFile: - return "ObjectFile"; - case lldb::eSymbolTypeCommonBlock: - return "CommonBlock"; - case lldb::eSymbolTypeBlock: - return "Block"; - case lldb::eSymbolTypeLocal: - return "Local"; - case lldb::eSymbolTypeParam: - return "Param"; - case lldb::eSymbolTypeVariable: - return "Variable"; - case lldb::eSymbolTypeVariableType: - return "VariableType"; - case lldb::eSymbolTypeLineEntry: - return "LineEntry"; - case lldb::eSymbolTypeLineHeader: - return "LineHeader"; - case lldb::eSymbolTypeScopeBegin: - return "ScopeBegin"; - case lldb::eSymbolTypeScopeEnd: - return "ScopeEnd"; - case lldb::eSymbolTypeAdditional: - return "Additional"; - case lldb::eSymbolTypeCompiler: - return "Compiler"; - case lldb::eSymbolTypeInstrumentation: - return "Instrumentation"; - case lldb::eSymbolTypeUndefined: - return "Undefined"; - case lldb::eSymbolTypeObjCClass: - return "ObjCClass"; - case lldb::eSymbolTypeObjCMetaClass: - return "ObjCMetaClass"; - case lldb::eSymbolTypeObjCIVar: - return "ObjCIVar"; - case lldb::eSymbolTypeReExported: - return "ReExported"; - } - - llvm_unreachable("unhandled symbol type."); -} - -static lldb::SymbolType StringToSymbolType(const std::string &symbol_type) { - return llvm::StringSwitch(symbol_type) - .Case("Invalid", lldb::eSymbolTypeInvalid) - .Case("Absolute", lldb::eSymbolTypeAbsolute) - .Case("Code", lldb::eSymbolTypeCode) - .Case("Resolver", lldb::eSymbolTypeResolver) - .Case("Data", lldb::eSymbolTypeData) - .Case("Trampoline", lldb::eSymbolTypeTrampoline) - .Case("Runtime", lldb::eSymbolTypeRuntime) - .Case("Exception", lldb::eSymbolTypeException) - .Case("SourceFile", lldb::eSymbolTypeSourceFile) - .Case("HeaderFile", lldb::eSymbolTypeHeaderFile) - .Case("ObjectFile", lldb::eSymbolTypeObjectFile) - .Case("CommonBlock", lldb::eSymbolTypeCommonBlock) - .Case("Block", lldb::eSymbolTypeBlock) - .Case("Local", lldb::eSymbolTypeLocal) - .Case("Param", lldb::eSymbolTypeParam) - .Case("Variable", lldb::eSymbolTypeVariable) - .Case("VariableType", lldb::eSymbolTypeVariableType) - .Case("LineEntry", lldb::eSymbolTypeLineEntry) - .Case("LineHeader", lldb::eSymbolTypeLineHeader) - .Case("ScopeBegin", lldb::eSymbolTypeScopeBegin) - .Case("ScopeEnd", lldb::eSymbolTypeScopeEnd) - .Case("Additional", lldb::eSymbolTypeAdditional) - .Case("Compiler", lldb::eSymbolTypeCompiler) - .Case("Instrumentation", lldb::eSymbolTypeInstrumentation) - .Case("Undefined", lldb::eSymbolTypeUndefined) - .Case("ObjCClass", lldb::eSymbolTypeObjCClass) - .Case("ObjCMetaClass", lldb::eSymbolTypeObjCMetaClass) - .Case("ObjCIVar", lldb::eSymbolTypeObjCIVar) - .Case("ReExported", lldb::eSymbolTypeReExported) - - .Default(lldb::eSymbolTypeInvalid); -} - bool fromJSON(const llvm::json::Value &Params, PersistenceData &PD, llvm::json::Path P) { json::ObjectMapper O(Params, P); @@ -145,7 +46,7 @@ bool fromJSON(const llvm::json::Value &Params, Symbol &DS, llvm::json::Path P) { O.map("size", DS.size) && O.map("name", DS.name))) return false; - DS.type = StringToSymbolType(type_str); + DS.type = lldb::SBSymbol::GetTypeFromString(type_str.c_str()); return true; } @@ -155,7 +56,7 @@ llvm::json::Value toJSON(const Symbol &DS) { {"isDebug", DS.isDebug}, {"isSynthetic", DS.isSynthetic}, {"isExternal", DS.isExternal}, - {"type", SymbolTypeToString(DS.type)}, + {"type", lldb::SBSymbol::GetTypeAsString(DS.type)}, {"fileAddress", DS.fileAddress}, {"loadAddress", DS.loadAddress}, {"size", DS.size}, From 30601fa77197389b47c8a70bf693fd28e7b94e8a Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Thu, 21 Aug 2025 00:20:46 +0200 Subject: [PATCH 44/44] fix docs --- lldb/source/API/SBSymbol.cpp | 4 ++++ lldb/source/API/SBTarget.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lldb/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp index e51927146b057..3b59119494f37 100644 --- a/lldb/source/API/SBSymbol.cpp +++ b/lldb/source/API/SBSymbol.cpp @@ -226,9 +226,13 @@ bool SBSymbol::IsDebug() { } const char *SBSymbol::GetTypeAsString(lldb::SymbolType symbol_type) { + LLDB_INSTRUMENT_VA(symbol_type); + return Symbol::GetTypeAsString(symbol_type); } lldb::SymbolType SBSymbol::GetTypeFromString(const char *str) { + LLDB_INSTRUMENT_VA(str); + return Symbol::GetTypeFromString(str); } diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index c761b96135a86..eb56337de3c44 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -1575,7 +1575,7 @@ SBModule SBTarget::FindModule(const SBModuleSpec &sb_module_spec) { SBModule sb_module; if (TargetSP target_sp = GetSP(); target_sp && sb_module_spec.IsValid()) { - // The module list is thread safe, no need to lock + // The module list is thread safe, no need to lock. sb_module.SetSP( target_sp->GetImages().FindFirstModule(*sb_module_spec.m_opaque_up)); }