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

>From 894e70274cd2ea71af854df6fc5f3c7575c15408 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyron...@gmail.com>
Date: Fri, 22 Aug 2025 21:31:04 +0200
Subject: [PATCH 1/3] Reapply "[lldb-dap] Add module symbol table viewer to VS
 Code extension #140626 (#153836)"

This reverts commit 2b8e80694263fb404d1d0b816f33df731e617625.
---
 lldb/include/lldb/API/SBSymbol.h              |  15 +
 lldb/include/lldb/API/SBTarget.h              |  10 +
 lldb/include/lldb/Symbol/Symbol.h             |   5 +
 .../test/tools/lldb-dap/dap_server.py         |  19 +
 lldb/source/API/SBSymbol.cpp                  |  28 +
 lldb/source/API/SBTarget.cpp                  |  12 +
 lldb/source/Symbol/Symbol.cpp                 | 144 ++---
 .../API/tools/lldb-dap/moduleSymbols/Makefile |   3 +
 .../moduleSymbols/TestDAP_moduleSymbols.py    |  37 ++
 .../API/tools/lldb-dap/moduleSymbols/main.c   |   9 +
 lldb/tools/lldb-dap/CMakeLists.txt            |   1 +
 lldb/tools/lldb-dap/DAP.cpp                   |  22 +
 lldb/tools/lldb-dap/DAP.h                     |   3 +
 lldb/tools/lldb-dap/EventHelper.cpp           |  30 +-
 lldb/tools/lldb-dap/EventHelper.h             |   4 +-
 .../ConfigurationDoneRequestHandler.cpp       |   6 +-
 .../Handler/ModuleSymbolsRequestHandler.cpp   |  89 +++
 lldb/tools/lldb-dap/Handler/RequestHandler.h  |  14 +
 lldb/tools/lldb-dap/Protocol/DAPTypes.cpp     |  35 +-
 lldb/tools/lldb-dap/Protocol/DAPTypes.h       |  32 ++
 .../lldb-dap/Protocol/ProtocolRequests.cpp    |  15 +
 .../lldb-dap/Protocol/ProtocolRequests.h      |  24 +
 .../tools/lldb-dap/Protocol/ProtocolTypes.cpp |   4 +
 lldb/tools/lldb-dap/Protocol/ProtocolTypes.h  |   5 +-
 lldb/tools/lldb-dap/package-lock.json         | 513 +++++++++++++++++-
 lldb/tools/lldb-dap/package.json              |  32 +-
 .../src-ts/debug-configuration-provider.ts    |   4 +
 .../lldb-dap/src-ts/debug-session-tracker.ts  |  22 +
 lldb/tools/lldb-dap/src-ts/extension.ts       |  10 +-
 lldb/tools/lldb-dap/src-ts/index.d.ts         |  14 +
 .../src-ts/ui/modules-data-provider.ts        |   1 +
 .../lldb-dap/src-ts/ui/symbols-provider.ts    | 127 +++++
 .../src-ts/ui/symbols-webview-html.ts         |  51 ++
 .../src-ts/webview/symbols-table-view.ts      | 114 ++++
 .../lldb-dap/src-ts/webview/tsconfig.json     |  15 +
 lldb/tools/lldb-dap/tsconfig.json             |   2 +
 lldb/unittests/DAP/CMakeLists.txt             |   1 +
 lldb/unittests/DAP/DAPTypesTest.cpp           |  60 ++
 38 files changed, 1443 insertions(+), 89 deletions(-)
 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
 create mode 100644 lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp
 create mode 100644 lldb/tools/lldb-dap/src-ts/index.d.ts
 create mode 100644 lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts
 create mode 100644 lldb/tools/lldb-dap/src-ts/ui/symbols-webview-html.ts
 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
 create mode 100644 lldb/unittests/DAP/DAPTypesTest.cpp

diff --git a/lldb/include/lldb/API/SBSymbol.h b/lldb/include/lldb/API/SBSymbol.h
index 94521881f82f9..a93bc7a7ae074 100644
--- a/lldb/include/lldb/API/SBSymbol.h
+++ b/lldb/include/lldb/API/SBSymbol.h
@@ -85,6 +85,12 @@ 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;
 
   bool operator!=(const lldb::SBSymbol &rhs) const;
@@ -99,6 +105,15 @@ 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();
+
+  /// Get the string representation of a symbol type.
+  static const char *GetTypeAsString(lldb::SymbolType symbol_type);
+
+  /// Get the symbol type from a string representation.
+  static lldb::SymbolType GetTypeFromString(const char *str);
+
 protected:
   lldb_private::Symbol *get();
 
diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h
index 22b6c63ed5b97..62cdd342a05e4 100644
--- a/lldb/include/lldb/API/SBTarget.h
+++ b/lldb/include/lldb/API/SBTarget.h
@@ -324,6 +324,16 @@ 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
   /// file.
   ///
diff --git a/lldb/include/lldb/Symbol/Symbol.h 
b/lldb/include/lldb/Symbol/Symbol.h
index 0674e56ef43f5..b994c34e46493 100644
--- a/lldb/include/lldb/Symbol/Symbol.h
+++ b/lldb/include/lldb/Symbol/Symbol.h
@@ -15,6 +15,7 @@
 #include "lldb/Symbol/SymbolContextScope.h"
 #include "lldb/Utility/Stream.h"
 #include "lldb/Utility/UserID.h"
+#include "lldb/lldb-enumerations.h"
 #include "lldb/lldb-private.h"
 #include "llvm/Support/JSON.h"
 
@@ -301,6 +302,10 @@ class Symbol : public SymbolContextScope {
 
   bool operator==(const Symbol &rhs) const;
 
+  static const char *GetTypeAsString(lldb::SymbolType symbol_type);
+
+  static lldb::SymbolType GetTypeFromString(const char *str);
+
 protected:
   // This is the internal guts of ResolveReExportedSymbol, it assumes
   // reexport_name is not null, and that module_spec is valid.  We track the
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py 
b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 311c9f089f86e..0608ac3fd83be 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
@@ -1299,6 +1299,25 @@ def request_modules(
             {"command": "modules", "type": "request", "arguments": args_dict}
         )
 
+    def request_moduleSymbols(
+        self,
+        moduleId: str = "",
+        moduleName: str = "",
+        startIndex: int = 0,
+        count: int = 0,
+    ):
+        command_dict = {
+            "command": "__lldb_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/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp
index 79477dd3a70fc..3b59119494f37 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,23 @@ 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;
+}
+
+const char *SBSymbol::GetTypeAsString(lldb::SymbolType symbol_type) {
+  LLDB_INSTRUMENT_VA(symbol_type);
+
+  return Symbol::GetTypeAsString(symbol_type);
+}
+
+lldb::SymbolType SBSymbol::GetTypeFromString(const char *str) {
+  LLDB_INSTRUMENT_VA(str);
+
+  return Symbol::GetTypeFromString(str);
+}
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 6aa41c52f3731..eb56337de3c44 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/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index d6689a647062a..40497dbccc5c3 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -392,45 +392,8 @@ bool Symbol::Compare(ConstString name, SymbolType type) 
const {
   return false;
 }
 
-#define ENUM_TO_CSTRING(x)                                                     
\
-  case eSymbolType##x:                                                         
\
-    return #x;
-
 const char *Symbol::GetTypeAsString() const {
-  switch (m_type) {
-    ENUM_TO_CSTRING(Invalid);
-    ENUM_TO_CSTRING(Absolute);
-    ENUM_TO_CSTRING(Code);
-    ENUM_TO_CSTRING(Resolver);
-    ENUM_TO_CSTRING(Data);
-    ENUM_TO_CSTRING(Trampoline);
-    ENUM_TO_CSTRING(Runtime);
-    ENUM_TO_CSTRING(Exception);
-    ENUM_TO_CSTRING(SourceFile);
-    ENUM_TO_CSTRING(HeaderFile);
-    ENUM_TO_CSTRING(ObjectFile);
-    ENUM_TO_CSTRING(CommonBlock);
-    ENUM_TO_CSTRING(Block);
-    ENUM_TO_CSTRING(Local);
-    ENUM_TO_CSTRING(Param);
-    ENUM_TO_CSTRING(Variable);
-    ENUM_TO_CSTRING(VariableType);
-    ENUM_TO_CSTRING(LineEntry);
-    ENUM_TO_CSTRING(LineHeader);
-    ENUM_TO_CSTRING(ScopeBegin);
-    ENUM_TO_CSTRING(ScopeEnd);
-    ENUM_TO_CSTRING(Additional);
-    ENUM_TO_CSTRING(Compiler);
-    ENUM_TO_CSTRING(Instrumentation);
-    ENUM_TO_CSTRING(Undefined);
-    ENUM_TO_CSTRING(ObjCClass);
-    ENUM_TO_CSTRING(ObjCMetaClass);
-    ENUM_TO_CSTRING(ObjCIVar);
-    ENUM_TO_CSTRING(ReExported);
-  default:
-    break;
-  }
-  return "<unknown SymbolType>";
+  return GetTypeAsString(static_cast<lldb::SymbolType>(m_type));
 }
 
 void Symbol::CalculateSymbolContext(SymbolContext *sc) {
@@ -774,6 +737,79 @@ bool Symbol::operator==(const Symbol &rhs) const {
   return true;
 }
 
+#define ENUM_TO_CSTRING(x)                                                     
\
+  case eSymbolType##x:                                                         
\
+    return #x;
+
+const char *Symbol::GetTypeAsString(lldb::SymbolType symbol_type) {
+  switch (symbol_type) {
+    ENUM_TO_CSTRING(Invalid);
+    ENUM_TO_CSTRING(Absolute);
+    ENUM_TO_CSTRING(Code);
+    ENUM_TO_CSTRING(Resolver);
+    ENUM_TO_CSTRING(Data);
+    ENUM_TO_CSTRING(Trampoline);
+    ENUM_TO_CSTRING(Runtime);
+    ENUM_TO_CSTRING(Exception);
+    ENUM_TO_CSTRING(SourceFile);
+    ENUM_TO_CSTRING(HeaderFile);
+    ENUM_TO_CSTRING(ObjectFile);
+    ENUM_TO_CSTRING(CommonBlock);
+    ENUM_TO_CSTRING(Block);
+    ENUM_TO_CSTRING(Local);
+    ENUM_TO_CSTRING(Param);
+    ENUM_TO_CSTRING(Variable);
+    ENUM_TO_CSTRING(VariableType);
+    ENUM_TO_CSTRING(LineEntry);
+    ENUM_TO_CSTRING(LineHeader);
+    ENUM_TO_CSTRING(ScopeBegin);
+    ENUM_TO_CSTRING(ScopeEnd);
+    ENUM_TO_CSTRING(Additional);
+    ENUM_TO_CSTRING(Compiler);
+    ENUM_TO_CSTRING(Instrumentation);
+    ENUM_TO_CSTRING(Undefined);
+    ENUM_TO_CSTRING(ObjCClass);
+    ENUM_TO_CSTRING(ObjCMetaClass);
+    ENUM_TO_CSTRING(ObjCIVar);
+    ENUM_TO_CSTRING(ReExported);
+  }
+  return "<unknown SymbolType>";
+}
+
+lldb::SymbolType Symbol::GetTypeFromString(const char *str) {
+  std::string str_lower = llvm::StringRef(str).lower();
+  return llvm::StringSwitch<lldb::SymbolType>(str_lower)
+      .Case("absolute", eSymbolTypeAbsolute)
+      .Case("code", eSymbolTypeCode)
+      .Case("resolver", eSymbolTypeResolver)
+      .Case("data", eSymbolTypeData)
+      .Case("trampoline", eSymbolTypeTrampoline)
+      .Case("runtime", eSymbolTypeRuntime)
+      .Case("exception", eSymbolTypeException)
+      .Case("sourcefile", eSymbolTypeSourceFile)
+      .Case("headerfile", eSymbolTypeHeaderFile)
+      .Case("objectfile", eSymbolTypeObjectFile)
+      .Case("commonblock", eSymbolTypeCommonBlock)
+      .Case("block", eSymbolTypeBlock)
+      .Case("local", eSymbolTypeLocal)
+      .Case("param", eSymbolTypeParam)
+      .Case("variable", eSymbolTypeVariable)
+      .Case("variableType", eSymbolTypeVariableType)
+      .Case("lineentry", eSymbolTypeLineEntry)
+      .Case("lineheader", eSymbolTypeLineHeader)
+      .Case("scopebegin", eSymbolTypeScopeBegin)
+      .Case("scopeend", eSymbolTypeScopeEnd)
+      .Case("additional,", eSymbolTypeAdditional)
+      .Case("compiler", eSymbolTypeCompiler)
+      .Case("instrumentation", eSymbolTypeInstrumentation)
+      .Case("undefined", eSymbolTypeUndefined)
+      .Case("objcclass", eSymbolTypeObjCClass)
+      .Case("objcmetaclass", eSymbolTypeObjCMetaClass)
+      .Case("objcivar", eSymbolTypeObjCIVar)
+      .Case("reexported", eSymbolTypeReExported)
+      .Default(eSymbolTypeInvalid);
+}
+
 namespace llvm {
 namespace json {
 
@@ -804,36 +840,8 @@ bool fromJSON(const llvm::json::Value &value, 
lldb_private::JSONSymbol &symbol,
 bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
               llvm::json::Path path) {
   if (auto str = value.getAsString()) {
-    type = llvm::StringSwitch<lldb::SymbolType>(*str)
-               .Case("absolute", eSymbolTypeAbsolute)
-               .Case("code", eSymbolTypeCode)
-               .Case("resolver", eSymbolTypeResolver)
-               .Case("data", eSymbolTypeData)
-               .Case("trampoline", eSymbolTypeTrampoline)
-               .Case("runtime", eSymbolTypeRuntime)
-               .Case("exception", eSymbolTypeException)
-               .Case("sourcefile", eSymbolTypeSourceFile)
-               .Case("headerfile", eSymbolTypeHeaderFile)
-               .Case("objectfile", eSymbolTypeObjectFile)
-               .Case("commonblock", eSymbolTypeCommonBlock)
-               .Case("block", eSymbolTypeBlock)
-               .Case("local", eSymbolTypeLocal)
-               .Case("param", eSymbolTypeParam)
-               .Case("variable", eSymbolTypeVariable)
-               .Case("variableType", eSymbolTypeVariableType)
-               .Case("lineentry", eSymbolTypeLineEntry)
-               .Case("lineheader", eSymbolTypeLineHeader)
-               .Case("scopebegin", eSymbolTypeScopeBegin)
-               .Case("scopeend", eSymbolTypeScopeEnd)
-               .Case("additional,", eSymbolTypeAdditional)
-               .Case("compiler", eSymbolTypeCompiler)
-               .Case("instrumentation", eSymbolTypeInstrumentation)
-               .Case("undefined", eSymbolTypeUndefined)
-               .Case("objcclass", eSymbolTypeObjCClass)
-               .Case("objcmetaClass", eSymbolTypeObjCMetaClass)
-               .Case("objcivar", eSymbolTypeObjCIVar)
-               .Case("reexporte", eSymbolTypeReExported)
-               .Default(eSymbolTypeInvalid);
+    llvm::StringRef str_ref = str.value_or("");
+    type = Symbol::GetTypeFromString(str_ref.data());
 
     if (type == eSymbolTypeInvalid) {
       path.report("invalid symbol type");
diff --git a/lldb/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..b99edf369a7fd
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py
@@ -0,0 +1,37 @@
+"""
+Test lldb-dap moduleSymbols request
+"""
+
+import lldbdap_testcase
+
+
+class TestDAP_moduleSymbols(lldbdap_testcase.DAPTestCaseBase):
+    def test_moduleSymbols(self):
+        """
+        Test that the moduleSymbols request returns correct symbols from the 
module.
+        """
+        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..b038b10480b80
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/moduleSymbols/main.c
@@ -0,0 +1,9 @@
+int func1() { return 42; }
+
+int func2() { return 84; }
+
+int main() {
+  func1();
+  func2();
+  return 0;
+}
diff --git a/lldb/tools/lldb-dap/CMakeLists.txt 
b/lldb/tools/lldb-dap/CMakeLists.txt
index 5e0ad53b82f89..7db334ca56bcf 100644
--- a/lldb/tools/lldb-dap/CMakeLists.txt
+++ b/lldb/tools/lldb-dap/CMakeLists.txt
@@ -45,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 0ecd5f05c73bb..b1ad38d983893 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1261,6 +1261,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);
 }
@@ -1617,6 +1638,7 @@ void DAP::RegisterRequests() {
   // Custom requests
   RegisterRequest<CompileUnitsRequestHandler>();
   RegisterRequest<ModulesRequestHandler>();
+  RegisterRequest<ModuleSymbolsRequestHandler>();
 
   // Testing requests
   RegisterRequest<TestGetTargetBreakpointsRequestHandler>();
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 0b6373fb80381..04f70f76a09cd 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -367,6 +367,9 @@ struct DAP final : private DAPTransport::MessageHandler {
   /// The set of capabilities supported by this adapter.
   protocol::Capabilities GetCapabilities();
 
+  /// The set of custom capabilities supported by this adapter.
+  protocol::Capabilities GetCustomCapabilities();
+
   /// Debuggee will continue from stopped state.
   void WillContinue() { variables.Clear(); }
 
diff --git a/lldb/tools/lldb-dap/EventHelper.cpp 
b/lldb/tools/lldb-dap/EventHelper.cpp
index 364cc7ab4ef8c..bfb05a387d04d 100644
--- a/lldb/tools/lldb-dap/EventHelper.cpp
+++ b/lldb/tools/lldb-dap/EventHelper.cpp
@@ -38,25 +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);
+
+  return capabilities;
+}
+
+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 = std::move(capabilities);
 
   // Only notify the client if supportedFeatures changed.
   if (!body.capabilities.supportedFeatures.empty())
-    dap.Send(protocol::Event{"capabilities", body});
+    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 72ad5308a2b0c..592c1b81c46af 100644
--- a/lldb/tools/lldb-dap/EventHelper.h
+++ b/lldb/tools/lldb-dap/EventHelper.h
@@ -17,8 +17,8 @@ struct DAP;
 
 enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
 
-/// Update capabilities based on the configured target.
-void SendTargetBasedCapabilities(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 e7735a705d0aa..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,7 +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);
+
+  /// 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
new file mode 100644
index 0000000000000..6e50ee122c41f
--- /dev/null
+++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp
@@ -0,0 +1,89 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/SBAddress.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBModule.h"
+#include "lldb/API/SBModuleSpec.h"
+#include "lldb/Utility/UUID.h"
+#include "llvm/Support/Error.h"
+#include <cstddef>
+
+using namespace lldb_dap::protocol;
+namespace lldb_dap {
+
+llvm::Expected<ModuleSymbolsResponseBody>
+ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const {
+  ModuleSymbolsResponseBody response;
+
+  lldb::SBModuleSpec module_spec;
+  if (!args.moduleId.empty()) {
+    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(uuid_bytes.data(), uuid_bytes.size());
+  }
+
+  if (!args.moduleName.empty()) {
+    lldb::SBFileSpec file_spec;
+    file_spec.SetFilename(args.moduleName.c_str());
+    module_spec.SetFileSpec(file_spec);
+  }
+
+  // Empty request, return empty response.
+  if (!module_spec.IsValid())
+    return response;
+
+  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");
+
+  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;
+
+    Symbol dap_symbol;
+    dap_symbol.id = symbol.GetID();
+    dap_symbol.type = symbol.GetType();
+    dap_symbol.isDebug = symbol.IsDebug();
+    dap_symbol.isSynthetic = symbol.IsSynthetic();
+    dap_symbol.isExternal = symbol.IsExternal();
+
+    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));
+  }
+
+  return response;
+}
+
+} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h 
b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 5469cfbfa0321..977a247996750 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -597,6 +597,20 @@ class CancelRequestHandler : public 
RequestHandler<protocol::CancelArguments,
   llvm::Error Run(const protocol::CancelArguments &args) const override;
 };
 
+class ModuleSymbolsRequestHandler
+    : public RequestHandler<
+          protocol::ModuleSymbolsArguments,
+          llvm::Expected<protocol::ModuleSymbolsResponseBody>> {
+public:
+  using RequestHandler::RequestHandler;
+  static llvm::StringLiteral GetCommand() { return "__lldb_moduleSymbols"; }
+  FeatureSet GetSupportedFeatures() const override {
+    return {protocol::eAdapterFeatureSupportsModuleSymbolsRequest};
+  }
+  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
 /// 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..a14ed9e521f48 100644
--- a/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.cpp
@@ -1,4 +1,6 @@
 #include "Protocol/DAPTypes.h"
+#include "lldb/API/SBSymbol.h"
+#include "lldb/lldb-enumerations.h"
 
 using namespace llvm;
 
@@ -33,4 +35,35 @@ llvm::json::Value toJSON(const SourceLLDBData &SLD) {
   return result;
 }
 
-} // namespace lldb_dap::protocol
\ No newline at end of file
+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("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) &&
+        O.mapOptional("loadAddress", DS.loadAddress) &&
+        O.map("size", DS.size) && O.map("name", DS.name)))
+    return false;
+
+  DS.type = lldb::SBSymbol::GetTypeFromString(type_str.c_str());
+  return true;
+}
+
+llvm::json::Value toJSON(const Symbol &DS) {
+  json::Object result{
+      {"id", DS.id},
+      {"isDebug", DS.isDebug},
+      {"isSynthetic", DS.isSynthetic},
+      {"isExternal", DS.isExternal},
+      {"type", lldb::SBSymbol::GetTypeAsString(DS.type)},
+      {"fileAddress", DS.fileAddress},
+      {"loadAddress", DS.loadAddress},
+      {"size", DS.size},
+      {"name", DS.name},
+  };
+
+  return result;
+}
+
+} // namespace lldb_dap::protocol
diff --git a/lldb/tools/lldb-dap/Protocol/DAPTypes.h 
b/lldb/tools/lldb-dap/Protocol/DAPTypes.h
index 716d8b491b258..7fccf1359a737 100644
--- a/lldb/tools/lldb-dap/Protocol/DAPTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/DAPTypes.h
@@ -48,6 +48,38 @@ struct SourceLLDBData {
 bool fromJSON(const llvm::json::Value &, SourceLLDBData &, llvm::json::Path);
 llvm::json::Value toJSON(const SourceLLDBData &);
 
+struct Symbol {
+  /// The symbol id, usually the original symbol table index.
+  uint32_t id;
+
+  /// 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 isSynthetic;
+
+  /// True if this symbol is globally visible.
+  bool isExternal;
+
+  /// The symbol type.
+  lldb::SymbolType 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 &, Symbol &, llvm::json::Path);
+llvm::json::Value toJSON(const Symbol &);
+
 } // namespace lldb_dap::protocol
 
 #endif
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index 40634d52a66fd..eab7211e18973 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -609,4 +609,19 @@ json::Value toJSON(const WriteMemoryResponseBody &WMR) {
   return result;
 }
 
+bool fromJSON(const llvm::json::Value &Params, ModuleSymbolsArguments &Args,
+              llvm::json::Path P) {
+  json::ObjectMapper O(Params, P);
+  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) {
+  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 7c08a8887c081..0848ee53b4410 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -1012,6 +1012,30 @@ struct WriteMemoryResponseBody {
 };
 llvm::json::Value toJSON(const WriteMemoryResponseBody &);
 
+struct ModuleSymbolsArguments {
+  /// The module UUID for which to retrieve symbols.
+  std::string moduleId;
+
+  /// 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);
+
+/// Response to `getModuleSymbols` request.
+struct ModuleSymbolsResponseBody {
+  /// The symbols for the specified module.
+  std::vector<Symbol> symbols;
+};
+llvm::json::Value toJSON(const ModuleSymbolsResponseBody &);
+
 } // namespace lldb_dap::protocol
 
 #endif
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index 0708901d9ca05..dc8edaadcd9bb 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -452,6 +452,8 @@ static llvm::StringLiteral ToString(AdapterFeature feature) 
{
     return "supportsWriteMemoryRequest";
   case eAdapterFeatureTerminateDebuggee:
     return "supportTerminateDebuggee";
+  case eAdapterFeatureSupportsModuleSymbolsRequest:
+    return "supportsModuleSymbolsRequest";
   }
   llvm_unreachable("unhandled adapter feature.");
 }
@@ -523,6 +525,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 7a7609797c104..7077df90a85b5 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -320,8 +320,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/package-lock.json 
b/lldb/tools/lldb-dap/package-lock.json
index 1969b196accc6..26db1ce6df2fd 100644
--- a/lldb/tools/lldb-dap/package-lock.json
+++ b/lldb/tools/lldb-dap/package-lock.json
@@ -1,20 +1,24 @@
 {
   "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",
+        "@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",
         "prettier": "^3.4.2",
         "prettier-plugin-curly": "^0.3.1",
+        "tabulator-tables": "^6.3.1",
         "typescript": "^5.7.3"
       },
       "engines": {
@@ -318,6 +322,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";,
@@ -399,6 +845,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";,
@@ -406,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";,
@@ -1169,6 +1629,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";,
@@ -2557,6 +3059,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 d677a81cc7974..f11b64aa72ae4 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -29,11 +29,15 @@
   ],
   "devDependencies": {
     "@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",
     "prettier": "^3.4.2",
     "prettier-plugin-curly": "^0.3.1",
+    "tabulator-tables": "^6.3.1",
     "typescript": "^5.7.3"
   },
   "activationEvents": [
@@ -42,8 +46,11 @@
   ],
   "main": "./out/extension",
   "scripts": {
-    "vscode:prepublish": "tsc -p ./",
-    "watch": "tsc -watch -p ./",
+    "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 ./",
+    "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",
@@ -259,6 +266,15 @@
       {
         "command": "lldb-dap.modules.copyProperty",
         "title": "Copy Value"
+      },
+      {
+        "command": "lldb-dap.modules.showSymbols",
+        "title": "Show Module Symbols"
+      },
+      {
+        "category": "lldb-dap",
+        "command": "lldb-dap.debug.showSymbols",
+        "title": "Show Symbols of a Module"
       }
     ],
     "menus": {
@@ -266,12 +282,24 @@
         {
           "command": "lldb-dap.modules.copyProperty",
           "when": "false"
+        },
+        {
+          "command": "lldb-dap.modules.showSymbols",
+          "when": "false"
+        },
+        {
+          "command": "lldb-dap.debug.showSymbols",
+          "when": "debuggersAvailable && debugType == 'lldb-dap' && 
lldb-dap.supportsModuleSymbolsRequest"
         }
       ],
       "view/item/context": [
         {
           "command": "lldb-dap.modules.copyProperty",
           "when": "view == lldb-dap.modules && viewItem == property"
+        },
+        {
+          "command": "lldb-dap.modules.showSymbols",
+          "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..6e89d441bbcf0 100644
--- a/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts
+++ b/lldb/tools/lldb-dap/src-ts/debug-session-tracker.ts
@@ -1,11 +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;
+  "capabilities": DebugProtocol.CapabilitiesEvent;
 }
 
 /** A type assertion to check if a ProtocolMessage is an event or if it is a 
specific event. */
@@ -39,6 +45,9 @@ export class DebugSessionTracker
   private modulesChanged = new vscode.EventEmitter<
     vscode.DebugSession | undefined
   >();
+  private sessionReceivedCapabilities =
+      new vscode.EventEmitter<[ vscode.DebugSession, LLDBDapCapabilities ]>();
+  private sessionExited = new vscode.EventEmitter<vscode.DebugSession>();
 
   /**
    * Fired when modules are changed for any active debug session.
@@ -48,6 +57,15 @@ export class DebugSessionTracker
   onDidChangeModules: vscode.Event<vscode.DebugSession | undefined> =
     this.modulesChanged.event;
 
+  /** Fired when a debug session is initialized. */
+  onDidReceiveSessionCapabilities:
+      vscode.Event<[ vscode.DebugSession, LLDBDapCapabilities ]> =
+      this.sessionReceivedCapabilities.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 +164,10 @@ export class DebugSessionTracker
       this.logger.info(
         `Session "${session.name}" exited with code ${exitCode}`,
       );
+
+      this.sessionExited.fire(session);
+    } else if (isEvent(message, "capabilities")) {
+      this.sessionReceivedCapabilities.fire([ session, 
message.body.capabilities ]);
     }
   }
 }
diff --git a/lldb/tools/lldb-dap/src-ts/extension.ts 
b/lldb/tools/lldb-dap/src-ts/extension.ts
index 4b7a35e6944c6..7119cba972fa4 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
@@ -19,6 +20,7 @@ import { LogFilePathProvider } from "./logging";
  */
 export class LLDBDapExtension extends DisposableContext {
   constructor(
+    context: vscode.ExtensionContext,
     logger: vscode.LogOutputChannel,
     logFilePath: LogFilePathProvider,
     outputChannel: vscode.OutputChannel,
@@ -52,10 +54,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, context));
   }
 }
 
@@ -67,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/index.d.ts 
b/lldb/tools/lldb-dap/src-ts/index.d.ts
new file mode 100644
index 0000000000000..d4618f44dee7b
--- /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 declare interface SymbolType {
+  id: 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/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
new file mode 100644
index 0000000000000..84b9387ffe49f
--- /dev/null
+++ b/lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts
@@ -0,0 +1,127 @@
+import * as vscode from "vscode";
+import { DebugProtocol } from "@vscode/debugprotocol";
+
+import { DebugSessionTracker } from "../debug-session-tracker";
+import { DisposableContext } from "../disposable-context";
+
+import { SymbolType } from "..";
+import { getSymbolsTableHTMLContent } from "./symbols-webview-html";
+import { getDefaultConfigKey } from "../debug-configuration-provider";
+
+export class SymbolsProvider extends DisposableContext {
+  constructor(
+    private readonly tracker: DebugSessionTracker,
+    private readonly extensionContext: vscode.ExtensionContext,
+  ) {
+    super();
+
+    this.pushSubscription(vscode.commands.registerCommand(
+      "lldb-dap.debug.showSymbols",
+      () => {
+        const session = vscode.debug.activeDebugSession;
+        if (!session) return;
+
+        this.SelectModuleAndShowSymbols(session);
+      },
+    ));
+
+    this.pushSubscription(vscode.commands.registerCommand(
+      "lldb-dap.modules.showSymbols",
+      (moduleItem: DebugProtocol.Module) => {
+        const session = vscode.debug.activeDebugSession;
+        if (!session) return;
+
+        this.showSymbolsForModule(session, moduleItem);
+      },
+    ));
+
+    this.tracker.onDidReceiveSessionCapabilities(([ _session, capabilities ]) 
=> {
+      if (capabilities.supportsModuleSymbolsRequest) {
+        vscode.commands.executeCommand(
+            "setContext", "lldb-dap.supportsModuleSymbolsRequest", true);
+      }
+    });
+
+    this.tracker.onDidExitSession((_session) => {
+      vscode.commands.executeCommand("setContext", 
"lldb-dap.supportsModuleSymbolsRequest", false);
+    });
+  }
+
+  private async SelectModuleAndShowSymbols(session: vscode.DebugSession) {
+    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;
+    }
+
+    this.showSymbolsForModule(session, selectedModule.module);
+  }
+
+  private async showSymbolsForModule(session: vscode.DebugSession, module: 
DebugProtocol.Module) {
+    try {
+      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);
+      } else {
+        vscode.window.showErrorMessage("Failed to retrieve symbols due to an 
unknown error.");
+      }
+      
+      return;
+    }
+  }
+
+  private async getSymbolsForModule(session: vscode.DebugSession, moduleId: 
string): Promise<SymbolType[]> {
+    const symbols_response: { symbols: Array<SymbolType> } = await 
session.customRequest("__lldb_moduleSymbols", { moduleId, moduleName: '' });
+    return symbols_response?.symbols || [];
+  }
+
+  private async showSymbolsInNewTab(moduleName: string, symbols: SymbolType[]) 
{
+    const panel = vscode.window.createWebviewPanel(
+      "lldb-dap.symbols",
+      `Symbols for ${moduleName}`,
+      vscode.ViewColumn.Active,
+      {
+        enableScripts: true,
+        localResourceRoots: [
+          this.getExtensionResourcePath()
+        ]
+      }
+    );
+
+    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";
+    }
+    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 symbolsTableScriptPath = 
panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), 
"symbols-table-view.js"));
+
+    panel.webview.html = getSymbolsTableHTMLContent(tabulatorJsPath, 
tabulatorCssPath, symbolsTableScriptPath);
+    panel.webview.postMessage({ command: "updateSymbols", symbols: symbols });
+  }
+
+  private getExtensionResourcePath(): vscode.Uri {
+    return vscode.Uri.joinPath(this.extensionContext.extensionUri, "out", 
"webview");
+  }
+}
+
+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();
+  }
+}
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
new file mode 100644
index 0000000000000..8454378abef16
--- /dev/null
+++ b/lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts
@@ -0,0 +1,114 @@
+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();
+    if (val === undefined || val === null) {
+      return "";
+    }
+
+    return val !== undefined ? "0x" + 
val.toString(16).toLowerCase().padStart(padding, "0") : "";
+  };
+}
+
+const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [
+  { title: "ID", field: "id", headerTooltip: true, sorter: "number", 
widthGrow: 0.6 },
+  {
+    title: "Name",
+    field: "name",
+    headerTooltip: true,
+    sorter: "string",
+    widthGrow: 2.5,
+    minWidth: 200,
+    tooltip : (_event: MouseEvent, cell: CellComponent) => {
+      const rowData = cell.getRow().getData();
+      return rowData.name;
+    }
+  },
+  {
+    title: "Debug",
+    field: "isDebug",
+    headerTooltip: true,
+    hozAlign: "center",
+    widthGrow: 0.8,
+    formatter: "tickCross",
+    formatterParams: {
+      tickElement: TICK_ELEMENT,
+      crossElement: false,
+    }
+  },
+  {
+    title: "Synthetic",
+    field: "isSynthetic",
+    headerTooltip: true,
+    hozAlign: "center",
+    widthGrow: 0.8,
+    formatter: "tickCross",
+    formatterParams: {
+      tickElement: TICK_ELEMENT,
+      crossElement: false,
+    }
+  },
+  {
+    title: "External",
+    field: "isExternal",
+    headerTooltip: true,
+    hozAlign: "center",
+    widthGrow: 0.8,
+    formatter: "tickCross",
+    formatterParams: {
+      tickElement: TICK_ELEMENT,
+      crossElement: false,
+    }
+  },
+  { title: "Type", field: "type", sorter: "string" },
+  {
+    title: "File Address",
+    field: "fileAddress",
+    headerTooltip: true,
+    sorter: "number",
+    widthGrow : 1.25,
+    formatter: getTabulatorHexaFormatter(16),
+  },
+  {
+    title: "Load Address",
+    field: "loadAddress",
+    headerTooltip: true,
+    sorter: "number",
+    widthGrow : 1.25,
+    formatter: getTabulatorHexaFormatter(16),
+  },
+  { title: "Size", field: "size", headerTooltip: true, sorter: "number", 
formatter: getTabulatorHexaFormatter(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: previousState?.symbols || [],
+});
+
+function updateSymbolsTable(symbols: SymbolType[]) {
+  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;
+  }
+});
+
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/tools/lldb-dap/tsconfig.json 
b/lldb/tools/lldb-dap/tsconfig.json
index 2092148888904..06a484a1fc263 100644
--- a/lldb/tools/lldb-dap/tsconfig.json
+++ b/lldb/tools/lldb-dap/tsconfig.json
@@ -1,5 +1,6 @@
 {
        "compilerOptions": {
+               "moduleResolution": "node",
                "module": "commonjs",
                "outDir": "out",
                "rootDir": "src-ts",
@@ -12,5 +13,6 @@
        ],
        "exclude": [
                "node_modules",
+               "src-ts/webview",
        ]
 }
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..f398c54b724a0
--- /dev/null
+++ b/lldb/unittests/DAP/DAPTypesTest.cpp
@@ -0,0 +1,60 @@
+//===-- 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 "lldb/lldb-enumerations.h"
+#include "llvm/Testing/Support/Error.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);
+}
+
+TEST(DAPTypesTest, DAPSymbol) {
+  Symbol symbol;
+  symbol.id = 42;
+  symbol.isDebug = true;
+  symbol.isExternal = false;
+  symbol.isSynthetic = true;
+  symbol.type = lldb::eSymbolTypeTrampoline;
+  symbol.fileAddress = 0x12345678;
+  symbol.loadAddress = 0x87654321;
+  symbol.size = 64;
+  symbol.name = "testSymbol";
+
+  llvm::Expected<Symbol> deserialized_symbol = roundtripJSON(symbol);
+  ASSERT_THAT_EXPECTED(deserialized_symbol, llvm::Succeeded());
+
+  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);
+  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 4d1cc346824a530d53682f423e5046d55fccd109 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyron...@gmail.com>
Date: Fri, 22 Aug 2025 21:32:31 +0200
Subject: [PATCH 2/3] fix null dereference when symbol doesn't have a name

---
 lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp
index 6e50ee122c41f..4a9d256cfa975 100644
--- a/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp
@@ -79,7 +79,8 @@ ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments 
&args) const {
     }
 
     dap_symbol.size = symbol.GetSize();
-    dap_symbol.name = symbol.GetName();
+    if (const char *symbol_name = symbol.GetName())
+      dap_symbol.name = symbol_name;
     symbols.push_back(std::move(dap_symbol));
   }
 

>From 741ad6ae27b5158366ff101fc56e8edc99d1aff7 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyron...@gmail.com>
Date: Fri, 22 Aug 2025 21:48:44 +0200
Subject: [PATCH 3/3] skipIfWindows for test_moduleSymbols

---
 .../API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py  | 3 +++
 1 file changed, 3 insertions(+)

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 b99edf369a7fd..2336b9f2a5a1a 100644
--- a/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py
+++ b/lldb/test/API/tools/lldb-dap/moduleSymbols/TestDAP_moduleSymbols.py
@@ -3,9 +3,12 @@
 """
 
 import lldbdap_testcase
+from lldbsuite.test.decorators import *
 
 
 class TestDAP_moduleSymbols(lldbdap_testcase.DAPTestCaseBase):
+    # On windows LLDB doesn't recognize symbols in a.out.
+    @skipIfWindows
     def test_moduleSymbols(self):
         """
         Test that the moduleSymbols request returns correct symbols from the 
module.

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to