[Lldb-commits] [lldb] [lldb-dap] Add module symbol table viewer to VS Code extension #140626 (PR #153836)

Ely Ronnen via lldb-commits lldb-commits at lists.llvm.org
Tue Aug 19 12:57:08 PDT 2025


https://github.com/eronnen updated https://github.com/llvm/llvm-project/pull/153836

>From b70f3ca3b6f0c7dd9784b3a8d4685a26c1d462b9 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 9 Aug 2025 15:40:53 +0200
Subject: [PATCH 01/41] 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<protocol::CancelArguments,
   llvm::Error Run(const protocol::CancelArguments &args) const override;
 };
 
+class DAPGetModuleSymbolsRequestHandler
+    : public RequestHandler<protocol::DAPGetModuleSymbolsArguments,
+                            llvm::Expected<protocol::DAPGetModuleSymbolsResponseBody>> {
+public:
+  using RequestHandler::RequestHandler;
+  static llvm::StringLiteral GetCommand() { return "dapGetModuleSymbols"; }
+  llvm::Expected<protocol::DAPGetModuleSymbolsResponseBody>
+  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<lldb::addr_t> 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<DAPSymbol> 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 <optional>
+
+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<SourceLLDBData> 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 92d84da4c3bc3bea6d8b4cb9d761812f15e8d341 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 9 Aug 2025 19:12:09 +0200
Subject: [PATCH 02/41] 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 ce910b1f60b85..08d50c9b93a7e 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1566,6 +1566,7 @@ void DAP::RegisterRequests() {
   // Custom requests
   RegisterRequest<CompileUnitsRequestHandler>();
   RegisterRequest<ModulesRequestHandler>();
+  RegisterRequest<DAPGetModuleSymbolsRequestHandler>();
 
   // Testing requests
   RegisterRequest<TestGetTargetBreakpointsRequestHandler>();
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 <cstddef>
+
+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<DAPGetModuleSymbolsResponseBody>
+DAPGetModuleSymbolsRequestHandler::Run(
+    const DAPGetModuleSymbolsArguments &args) const {
+  DAPGetModuleSymbolsResponseBody response;
+
+  lldb::SBModuleSpec module_spec;
+  if (args.moduleId)
+    module_spec.SetUUIDBytes(
+        reinterpret_cast<const uint8_t *>(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<DAPSymbol> &symbols = response.symbols;
+  lldb::SBModule module = dap.target.FindModule(module_spec);
+  if (!module.IsValid())
+    return llvm::make_error<DAPError>("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<protocol::CancelArguments,
 };
 
 class DAPGetModuleSymbolsRequestHandler
-    : public RequestHandler<protocol::DAPGetModuleSymbolsArguments,
-                            llvm::Expected<protocol::DAPGetModuleSymbolsResponseBody>> {
+    : public RequestHandler<
+          protocol::DAPGetModuleSymbolsArguments,
+          llvm::Expected<protocol::DAPGetModuleSymbolsResponseBody>> {
 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<std::string> moduleId;
+
+  /// The module path.
+  std::optional<std::string> 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<SourceLLDBData> 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<DAPSymbol> 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 ef36ed550574d902b188d3b7edcc6608dafc3817 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Mon, 11 Aug 2025 01:25:15 +0200
Subject: [PATCH 03/41] 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 <cstddef>
@@ -96,10 +97,15 @@ DAPGetModuleSymbolsRequestHandler::Run(
   DAPGetModuleSymbolsResponseBody response;
 
   lldb::SBModuleSpec module_spec;
-  if (args.moduleId)
+  if (args.moduleId) {
+    llvm::SmallVector<uint8_t, 20> uuid_bytes;
+    if (!lldb_private::UUID::DecodeUUIDBytesFromString(*args.moduleId, uuid_bytes).empty())
+      return llvm::make_error<DAPError>("Invalid module ID");
+
     module_spec.SetUUIDBytes(
-        reinterpret_cast<const uint8_t *>(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<boolean> {
+    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<DAPSymbol[]> {
+    console.log(`Getting symbols for module: ${moduleId}`);
+    const symbols_response: { symbols: Array<DAPSymbolType> } = 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 df3d8ddc1afe3f2fdf3c6f08de2af380eafed706 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Mon, 11 Aug 2025 01:34:58 +0200
Subject: [PATCH 04/41] 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<DAPSymbol[]> {
@@ -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 2ae745df17aa4dff3c21836bf95c4b4c91ac7d36 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Tue, 12 Aug 2025 00:56:52 +0200
Subject: [PATCH 05/41] 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 `<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <link href="${tabulatorCssPath}" rel="stylesheet">
+    <style>
+      body { font-family: sans-serif; margin: 0; padding: 0; }
+      #table { height: 100vh; }
+    </style>
+</head>
+<body>
+    <div id="table"></div>
+    <script src="${tabulatorJsPath}"></script>
+    <script>
+        const tableData = ${dataJson};
+        new Tabulator("#table", {
+            data: tableData,
+            layout: "fitColumns",
+            columns: [
+                {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"},
+                {title: "Load Address", field: "loadAddress", sorter: "number"},
+                {title: "Size", field: "size", sorter: "number"},
+                {title: "Name", field: "name", sorter: "string"},
+            ]
+        });
+    </script>
+</body>
+</html>`;
   }
 
-  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 c6345937d324ee75506a0999c00460985394b5dc Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 13 Aug 2025 09:55:15 +0200
Subject: [PATCH 06/41] 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<any>) => {
+    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 `<!DOCTYPE html>
 <html>
 <head>
@@ -119,30 +120,13 @@ export class SymbolsProvider extends DisposableContext {
 <body>
     <div id="table"></div>
     <script src="${tabulatorJsPath}"></script>
-    <script>
-        const tableData = ${dataJson};
-        new Tabulator("#table", {
-            data: tableData,
-            layout: "fitColumns",
-            columns: [
-                {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"},
-                {title: "Load Address", field: "loadAddress", sorter: "number"},
-                {title: "Size", field: "size", sorter: "number"},
-                {title: "Name", field: "name", sorter: "string"},
-            ]
-        });
-    </script>
+    <script src="${symbolsTableScriptPath}"></script>
 </body>
 </html>`;
   }
 
   private getExtensionResourcePath(): vscode.Uri {
-    return vscode.Uri.joinPath(this.extensionContext.extensionUri, "out");
+    return vscode.Uri.joinPath(this.extensionContext.extensionUri, "out", "webview");
   }
 }
 

>From 2ea7136470c71760491a2f727faef0d8ba996849 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Thu, 14 Aug 2025 22:59:10 +0200
Subject: [PATCH 07/41] 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<any>) => {
+    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 bebaeb82b748ae722161d6f5502d95c47cc2e9e8 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 00:13:12 +0200
Subject: [PATCH 08/41] 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 e56ffd0cef1e1ec9eb09748a8acd8a3ae540f65f Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 00:17:47 +0200
Subject: [PATCH 09/41] 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 616eb431638ec8b5c66a683a465330044d3bea1c Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 11:09:27 +0200
Subject: [PATCH 10/41] 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<boolean> {
     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 {
     <meta charset="UTF-8">
     <link href="${tabulatorCssPath}" rel="stylesheet">
     <style>
-      body { font-family: sans-serif; margin: 0; padding: 0; }
-      #table { height: 100vh; }
+      #symbols-table { height: 100vh; }
     </style>
 </head>
 <body>
-    <div id="table"></div>
+    <div id="symbols-table"></div>
     <script src="${tabulatorJsPath}"></script>
     <script src="${symbolsTableScriptPath}"></script>
 </body>
@@ -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<any>) => {
-    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 04cc82f5af866d05bf43fe2ec2edfa9890a713bc Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 11:25:48 +0200
Subject: [PATCH 11/41] 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<any>) => {
     const message = event.data;
     switch (message.command) {
         case "updateSymbols":
+            vscode.setState({ symbols: message.symbols });
             updateSymbolsTable(message.symbols);
             break;
     }

>From 1a73294b25a1785addf7f4293549d9e86117ef36 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 14:36:00 +0200
Subject: [PATCH 12/41] 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 {
     <meta charset="UTF-8">
     <link href="${tabulatorCssPath}" rel="stylesheet">
     <style>
-      #symbols-table { height: 100vh; }
+      .tabulator {
+        background-color: var(--vscode-editor-background);
+        color: var(--vscode-editor-foreground);
+      }
+
+      .tabulator .tabulator-header {
+        background-color: var(--vscode-editor-background);
+        color: var(--vscode-editor-foreground);
+      }
+
+      .tabulator-row {
+        background-color: var(--vscode-editor-background);
+      }
+
+      .tabulator.tabulator-row-even {
+        background-color: var(--vscode-tree-tableOddRowsBackground);
+      }
+
+      .tabulator-row.tabulator-selected {
+        background-color: var(--vscode-editor-background);
+        color: var(--vscode-editor-foreground);
+      }
+
+      #symbols-table { 
+        height: 100vh; 
+      }
     </style>
 </head>
 <body>

>From 75e41f48daca4fbd92bbc9c25575425c2f2b6598 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 15:05:32 +0200
Subject: [PATCH 13/41] 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 2a4cab848a43e24508086a8f0aa1e971f7c893f4 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 16:00:33 +0200
Subject: [PATCH 14/41] 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 c0262e2cd463e640feaf18444ec5239c9356eb93 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 17:18:11 +0200
Subject: [PATCH 15/41] 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;
       }
     </style>
 </head>
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 c8a6f334a81dc922df18fbc2ea48ce16a85fc8cd Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 17:30:01 +0200
Subject: [PATCH 16/41] 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 c55d64936de938bf03a8d40ca04f13bd63415647 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 17:33:50 +0200
Subject: [PATCH 17/41] 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<any>) => {
-    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 0814cf205da527c1a027d8ee250da3a0d2ccc71e Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 18:59:17 +0200
Subject: [PATCH 18/41] 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<boolean> {
@@ -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 `<!DOCTYPE html>
 <html>
 <head>

>From 4543bccfe4c8e1e61628ac80dbe4a4163e3d233a Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 19:01:11 +0200
Subject: [PATCH 19/41] 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<DAPSymbol[]> {
+  private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise<DAPSymbolType[]> {
     console.log(`Getting symbols for module: ${moduleId}`);
     const symbols_response: { symbols: Array<DAPSymbolType> } = 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 6e8da77bd3aef03bae7da03d61e2ceb43c24baaa Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Fri, 15 Aug 2025 19:03:42 +0200
Subject: [PATCH 20/41] 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<uint8_t, 20> 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<DAPError>("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 6e1a19f752ea5409bb8ca5094e638821f341ed75 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 16 Aug 2025 01:28:30 +0200
Subject: [PATCH 21/41] 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<protocol::PersistenceData>
+static std::optional<protocol::dap::PersistenceData>
 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<protocol::PersistenceData> persistence_data =
+        std::optional<protocol::dap::PersistenceData> 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<DAPSymbol> &symbols = response.symbols;
+  std::vector<dap::Symbol> &symbols = response.symbols;
   lldb::SBModule module = dap.target.FindModule(module_spec);
   if (!module.IsValid())
     return llvm::make_error<DAPError>("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 <optional>
 #include <string>
 
-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<DAPSymbol> symbols;
+  std::vector<dap::Symbol> 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<SourceLLDBData> adapterData;
+  std::optional<dap::SourceLLDBData> 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 <optional>
 
 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<DAPSymbol> deserialized_symbol = roundtripJSON(symbol);
+  llvm::Expected<Symbol> deserialized_symbol = roundtripJSON(symbol);
   ASSERT_THAT_EXPECTED(deserialized_symbol, llvm::Succeeded());
 
   EXPECT_EQ(symbol.userId, deserialized_symbol->userId);

>From 0e3ef866c9a1251afed9a64f1af44b24e46ea049 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 16 Aug 2025 01:43:32 +0200
Subject: [PATCH 22/41] 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 08d50c9b93a7e..9896ed03a29f2 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1566,7 +1566,7 @@ void DAP::RegisterRequests() {
   // Custom requests
   RegisterRequest<CompileUnitsRequestHandler>();
   RegisterRequest<ModulesRequestHandler>();
-  RegisterRequest<DAPGetModuleSymbolsRequestHandler>();
+  RegisterRequest<ModuleSymbolsRequestHandler>();
 
   // Testing requests
   RegisterRequest<TestGetTargetBreakpointsRequestHandler>();
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<DAPGetModuleSymbolsResponseBody>
-DAPGetModuleSymbolsRequestHandler::Run(
-    const DAPGetModuleSymbolsArguments &args) const {
-  DAPGetModuleSymbolsResponseBody response;
+llvm::Expected<ModuleSymbolsResponseBody>
+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::CancelArguments,
   llvm::Error Run(const protocol::CancelArguments &args) const override;
 };
 
-class DAPGetModuleSymbolsRequestHandler
+class ModuleSymbolsRequestHandler
     : public RequestHandler<
-          protocol::DAPGetModuleSymbolsArguments,
-          llvm::Expected<protocol::DAPGetModuleSymbolsResponseBody>> {
+          protocol::ModuleSymbolsArguments,
+          llvm::Expected<protocol::ModuleSymbolsResponseBody>> {
 public:
   using RequestHandler::RequestHandler;
-  static llvm::StringLiteral GetCommand() { return "dapGetModuleSymbols"; }
-  llvm::Expected<protocol::DAPGetModuleSymbolsResponseBody>
-  Run(const protocol::DAPGetModuleSymbolsArguments &args) const override;
+  static llvm::StringLiteral GetCommand() { return "moduleSymbols"; }
+  llvm::Expected<protocol::ModuleSymbolsResponseBody>
+  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<std::string> moduleId;
 
   /// The module path.
   std::optional<std::string> 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<dap::Symbol> symbols;
 };
-llvm::json::Value toJSON(const DAPGetModuleSymbolsResponseBody &);
+llvm::json::Value toJSON(const ModuleSymbolsResponseBody &);
 
 } // namespace lldb_dap::protocol
 

>From 7dfb60bee2cb980a9019cf9b998ea5a04733f6a0 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 16 Aug 2025 11:04:49 +0200
Subject: [PATCH 23/41] 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<protocol::dap::PersistenceData>
+static std::optional<protocol::PersistenceData>
 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<protocol::dap::PersistenceData> persistence_data =
+        std::optional<protocol::PersistenceData> 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<dap::Symbol> &symbols = response.symbols;
+  std::vector<Symbol> &symbols = response.symbols;
   lldb::SBModule module = dap.target.FindModule(module_spec);
   if (!module.IsValid())
     return llvm::make_error<DAPError>("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 <optional>
 #include <string>
 
-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<dap::Symbol> symbols;
+  std::vector<Symbol> 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<dap::SourceLLDBData> adapterData;
+  std::optional<SourceLLDBData> 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 5b75cfd4be9529729a92af31a5bd69cac07590bf Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 16 Aug 2025 11:05:10 +0200
Subject: [PATCH 24/41] 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 d47d6674603e8965ae91a1fe504497a4bda9260e Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 16 Aug 2025 11:21:33 +0200
Subject: [PATCH 25/41] 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<boolean> {
     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<DAPSymbolType[]> {
     console.log(`Getting symbols for module: ${moduleId}`);
-    const symbols_response: { symbols: Array<DAPSymbolType> } = await session.customRequest("dapGetModuleSymbols", { moduleId });
+    const symbols_response: { symbols: Array<DAPSymbolType> } = await session.customRequest("moduleSymbols", { moduleId });
 
 
     return symbols_response?.symbols || [];

>From 36a2fbc64f4eb0e82239b2ba7f53fd5a58ab1b97 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 16 Aug 2025 13:29:40 +0200
Subject: [PATCH 26/41] 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 <cstddef>
 
 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<ModuleSymbolsResponseBody>
 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<lldb::SymbolType>(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 <optional>
@@ -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 db62a6b95cb89b827b73c9446c3ae8e7b0294ad2 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 16 Aug 2025 14:51:26 +0200
Subject: [PATCH 27/41] 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<uint8_t, 20> uuid_bytes;
-    if (!lldb_private::UUID::DecodeUUIDBytesFromString(*args.moduleId,
+    if (!lldb_private::UUID::DecodeUUIDBytesFromString(args.moduleId,
                                                        uuid_bytes)
              .empty())
       return llvm::make_error<DAPError>("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<std::string> moduleId;
+  std::string moduleId;
 
   /// The module path.
-  std::optional<std::string> 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<string, DefaultConfig> = {
   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<vscode.DebugSession>();
+  private sessionExited = new vscode.EventEmitter<vscode.DebugSession>();
 
   /**
    * Fired when modules are changed for any active debug session.
@@ -48,6 +51,14 @@ export class DebugSessionTracker
   onDidChangeModules: vscode.Event<vscode.DebugSession | undefined> =
     this.modulesChanged.event;
 
+  /** Fired when a debug session is initialized. */
+  onDidInitializeSession: vscode.Event<vscode.DebugSession> =
+    this.sessionInitialized.event;
+
+  /** Fired when a debug session is exiting. */
+  onDidExitSession: vscode.Event<vscode.DebugSession> =
+    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<boolean> {
-    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<DAPSymbolType[]> {
     console.log(`Getting symbols for module: ${moduleId}`);
-    const symbols_response: { symbols: Array<DAPSymbolType> } = await session.customRequest("moduleSymbols", { moduleId });
-
+    const symbols_response: { symbols: Array<DAPSymbolType> } = await session.customRequest("moduleSymbols", { moduleId, moduleName: '' });
 
     return symbols_response?.symbols || [];
   }

>From 17310bec7f479f149f5efe69144e7aa4cf143678 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 16 Aug 2025 14:56:16 +0200
Subject: [PATCH 28/41] 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 972e24eab40bbd49b33cb265900976075c6c9aa1 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 16 Aug 2025 19:05:10 +0200
Subject: [PATCH 29/41] 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<DAPError>("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<uint32_t> startIndex;
+
+  /// The number of symbols to return; if omitted, all symbols are returned.
+  std::optional<uint32_t> 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 d37dc80e49b75524715a801ac178f2e875dcce54 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 17 Aug 2025 00:50:35 +0200
Subject: [PATCH 30/41] 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 407021cb3fc29c7c8c23098300ee6e8a4eee1850 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 17 Aug 2025 00:55:20 +0200
Subject: [PATCH 31/41] 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<uint32_t> startIndex;
 
   /// The number of symbols to return; if omitted, all symbols are returned.

>From 7ac9021ffb69ccf1617871ef1b26a9f9f509fad4 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 17 Aug 2025 01:15:28 +0200
Subject: [PATCH 32/41] 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 04921d3bda6a47b15efaee9bd25b0c77b7a4fdd0 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 17 Aug 2025 01:17:04 +0200
Subject: [PATCH 33/41] 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 ef8e742d003381ae9c75dd1156e9998d45e95a69 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 17 Aug 2025 01:20:29 +0200
Subject: [PATCH 34/41] 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<DAPSymbolType[]> {
-    console.log(`Getting symbols for module: ${moduleId}`);
     const symbols_response: { symbols: Array<DAPSymbolType> } = await session.customRequest("moduleSymbols", { moduleId, moduleName: '' });
-
     return symbols_response?.symbols || [];
   }
 

>From ec95b495ab995a327effb8dcdbfc1537a3dd7d8b Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 17 Aug 2025 01:24:58 +0200
Subject: [PATCH 35/41] 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 f110c57a4b6606d137c304ba363e204f05d2812c Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Mon, 18 Aug 2025 22:30:22 +0200
Subject: [PATCH 36/41] 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<DAPSymbolType[]> {
-    const symbols_response: { symbols: Array<DAPSymbolType> } = await session.customRequest("moduleSymbols", { moduleId, moduleName: '' });
+  private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise<SymbolType[]> {
+    const symbols_response: { symbols: Array<SymbolType> } = 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 `<!DOCTYPE html>
-<html>
-<head>
-    <meta charset="UTF-8">
-    <link href="${tabulatorCssPath}" rel="stylesheet">
-    <style>
-      .tabulator {
-        background-color: var(--vscode-editor-background);
-        color: var(--vscode-editor-foreground);
-      }
-
-      .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-row.tabulator-row-even {
-        background-color: var(--vscode-editor-background);
-        color: var(--vscode-editor-foreground);
-      }
-
-      .tabulator-row.tabulator-selected {
-        background-color: var(--vscode-editor-background);
-        color: var(--vscode-editor-foreground);
-      }
-
-      .tabulator-cell {
-        text-overflow: clip !important;
-      }
-
-      #symbols-table {
-        width: 100%;
-        height: 100vh;
-      }
-    </style>
-</head>
-<body>
-    <div id="symbols-table"></div>
-    <script src="${tabulatorJsPath}"></script>
-    <script src="${symbolsTableScriptPath}"></script>
-</body>
-</html>`;
-  }
-
   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 `<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <link href="${tabulatorCssPath}" rel="stylesheet">
+    <style>
+      .tabulator {
+        background-color: var(--vscode-editor-background);
+        color: var(--vscode-editor-foreground);
+      }
+
+      .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-row.tabulator-row-even {
+        background-color: var(--vscode-editor-background);
+        color: var(--vscode-editor-foreground);
+      }
+
+      .tabulator-row.tabulator-selected {
+        background-color: var(--vscode-editor-background);
+        color: var(--vscode-editor-foreground);
+      }
+
+      .tabulator-cell {
+        text-overflow: clip !important;
+      }
+
+      #symbols-table {
+        width: 100%;
+        height: 100vh;
+      }
+    </style>
+</head>
+<body>
+    <div id="symbols-table"></div>
+    <script src="${tabulatorJsPath}"></script>
+    <script src="${symbolsTableScriptPath}"></script>
+</body>
+</html>`;
+}
\ 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<Symbol> 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 2a078f2b1ccccbb297a83b1e9af9daa32a51d008 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Mon, 18 Aug 2025 23:21:06 +0200
Subject: [PATCH 37/41] 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 9896ed03a29f2..e8411f2ea3d1c 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1210,6 +1210,27 @@ protocol::Capabilities DAP::GetCapabilities() {
   return capabilities;
 }
 
+protocol::Capabilities DAP::GetCustomCapabilities() {
+  protocol::Capabilities capabilities;
+
+  // Add all custom capabilities here.
+  const llvm::DenseSet<AdapterFeature> all_custom_features = {
+      protocol::eAdapterFeatureSupportsModuleSymbolsRequest,
+  };
+
+  for (auto &kv : request_handlers) {
+    llvm::SmallDenseSet<AdapterFeature, 1> 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 b0e9fa9c16b75..1f9322924a0de 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -361,6 +361,9 @@ struct DAP {
   /// 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<protocol::ModuleSymbolsResponseBody>
   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<vscode.DebugSession>();
+  private sessionGotCapabilities =
+      new vscode.EventEmitter<[ vscode.DebugSession, LLDBDapCapabilities ]>();
   private sessionExited = new vscode.EventEmitter<vscode.DebugSession>();
 
   /**
@@ -52,8 +58,9 @@ export class DebugSessionTracker
     this.modulesChanged.event;
 
   /** Fired when a debug session is initialized. */
-  onDidInitializeSession: vscode.Event<vscode.DebugSession> =
-    this.sessionInitialized.event;
+  onDidGetSessionCapabilities:
+      vscode.Event<[ vscode.DebugSession, LLDBDapCapabilities ]> =
+      this.sessionGotCapabilities.event;
 
   /** Fired when a debug session is exiting. */
   onDidExitSession: vscode.Event<vscode.DebugSession> =
@@ -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 0d545c4487ca7d6c2db133f81b06e41d76c79810 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Tue, 19 Aug 2025 10:05:51 +0200
Subject: [PATCH 38/41] 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 = `<svg enable-background="new 0 0 24 24" height="14" width="14" viewBox="0 0 24 24" xml:space="preserve" ><path fill="var(--vscode-editor-foreground)" clip-rule="evenodd" d="M21.652,3.211c-0.293-0.295-0.77-0.295-1.061,0L9.41,14.34  c-0.293,0.297-0.771,0.297-1.062,0L3.449,9.351C3.304,9.203,3.114,9.13,2.923,9.129C2.73,9.128,2.534,9.201,2.387,9.351  l-2.165,1.946C0.078,11.445,0,11.63,0,11.823c0,0.194,0.078,0.397,0.223,0.544l4.94,5.184c0.292,0.296,0.771,0.776,1.062,1.07  l2.124,2.141c0.292,0.293,0.769,0.293,1.062,0l14.366-14.34c0.293-0.294,0.293-0.777,0-1.071L21.652,3.211z" fill-rule="evenodd"/></svg>`;
+
 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 8b3275393ad11e0ad8a5275f0550025309538c9b Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Tue, 19 Aug 2025 10:25:05 +0200
Subject: [PATCH 39/41] 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<AdapterFeature> GetTargetBasedCapabilities(DAP &dap) {
+  llvm::DenseSet<AdapterFeature> 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<AdapterFeature> 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 4ace386b395360eba2cf0476e8f5eceb84f8511a Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Tue, 19 Aug 2025 10:30:34 +0200
Subject: [PATCH 40/41] 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<vscode.DebugSession>();
 
@@ -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<vscode.DebugSession> =
@@ -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 d059b047e5dce5300fdf7d2d10386f6390b337bc Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Tue, 19 Aug 2025 21:56:35 +0200
Subject: [PATCH 41/41] 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<DAPError>("Invalid module ID");
+      return llvm::make_error<DAPError>("invalid module ID");
 
     module_spec.SetUUIDBytes(uuid_bytes.data(), uuid_bytes.size());
   }
@@ -49,7 +49,7 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const {
   std::vector<Symbol> &symbols = response.symbols;
   lldb::SBModule module = dap.target.FindModule(module_spec);
   if (!module.IsValid())
-    return llvm::make_error<DAPError>("Module not found");
+    return llvm::make_error<DAPError>("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<protocol::ModuleSymbolsResponseBody>> {
 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<SymbolType[]> {
-    const symbols_response: { symbols: Array<SymbolType> } = await session.customRequest("moduleSymbols", { moduleId, moduleName: '' });
+    const symbols_response: { symbols: Array<SymbolType> } = await session.customRequest("__lldb_moduleSymbols", { moduleId, moduleName: '' });
     return symbols_response?.symbols || [];
   }
 



More information about the lldb-commits mailing list