- VS Code extension: - Add module symbol table viewer using [Tabulator](https://tabulator.info/) for sorting and formatting rows. - Add context menu action to the modules tree. - lldb-dap - Add `DAPGetModuleSymbolsRequest` to get symbols from a module. Fixes #140626 [Screencast From 2025-08-15 19-12-33.webm](https://github.com/user-attachments/assets/75e2f229-ac82-487c-812e-3ea33a575b70)
This commit is contained in:
parent
27fc9671f9
commit
8b64cd8be2
@ -85,6 +85,12 @@ public:
|
|||||||
|
|
||||||
SymbolType GetType();
|
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;
|
||||||
|
|
||||||
bool operator!=(const lldb::SBSymbol &rhs) const;
|
bool operator!=(const lldb::SBSymbol &rhs) const;
|
||||||
@ -99,6 +105,15 @@ public:
|
|||||||
// other than the actual symbol table itself in the object file.
|
// other than the actual symbol table itself in the object file.
|
||||||
bool IsSynthetic();
|
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:
|
protected:
|
||||||
lldb_private::Symbol *get();
|
lldb_private::Symbol *get();
|
||||||
|
|
||||||
|
@ -324,6 +324,16 @@ public:
|
|||||||
|
|
||||||
lldb::SBModule FindModule(const lldb::SBFileSpec &file_spec);
|
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
|
/// Find compile units related to *this target and passed source
|
||||||
/// file.
|
/// file.
|
||||||
///
|
///
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "lldb/Symbol/SymbolContextScope.h"
|
#include "lldb/Symbol/SymbolContextScope.h"
|
||||||
#include "lldb/Utility/Stream.h"
|
#include "lldb/Utility/Stream.h"
|
||||||
#include "lldb/Utility/UserID.h"
|
#include "lldb/Utility/UserID.h"
|
||||||
|
#include "lldb/lldb-enumerations.h"
|
||||||
#include "lldb/lldb-private.h"
|
#include "lldb/lldb-private.h"
|
||||||
#include "llvm/Support/JSON.h"
|
#include "llvm/Support/JSON.h"
|
||||||
|
|
||||||
@ -301,6 +302,10 @@ public:
|
|||||||
|
|
||||||
bool operator==(const Symbol &rhs) const;
|
bool operator==(const Symbol &rhs) const;
|
||||||
|
|
||||||
|
static const char *GetTypeAsString(lldb::SymbolType symbol_type);
|
||||||
|
|
||||||
|
static lldb::SymbolType GetTypeFromString(const char *str);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// This is the internal guts of ResolveReExportedSymbol, it assumes
|
// This is the internal guts of ResolveReExportedSymbol, it assumes
|
||||||
// reexport_name is not null, and that module_spec is valid. We track the
|
// reexport_name is not null, and that module_spec is valid. We track the
|
||||||
|
@ -1199,6 +1199,25 @@ class DebugCommunication(object):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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(
|
def request_stackTrace(
|
||||||
self, threadId=None, startFrame=None, levels=None, format=None, dump=False
|
self, threadId=None, startFrame=None, levels=None, format=None, dump=False
|
||||||
):
|
):
|
||||||
|
@ -193,6 +193,14 @@ SymbolType SBSymbol::GetType() {
|
|||||||
return eSymbolTypeInvalid;
|
return eSymbolTypeInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t SBSymbol::GetID() {
|
||||||
|
LLDB_INSTRUMENT_VA(this);
|
||||||
|
|
||||||
|
if (m_opaque_ptr)
|
||||||
|
return m_opaque_ptr->GetID();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool SBSymbol::IsExternal() {
|
bool SBSymbol::IsExternal() {
|
||||||
LLDB_INSTRUMENT_VA(this);
|
LLDB_INSTRUMENT_VA(this);
|
||||||
|
|
||||||
@ -208,3 +216,23 @@ bool SBSymbol::IsSynthetic() {
|
|||||||
return m_opaque_ptr->IsSynthetic();
|
return m_opaque_ptr->IsSynthetic();
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
|
@ -1570,6 +1570,18 @@ SBModule SBTarget::FindModule(const SBFileSpec &sb_file_spec) {
|
|||||||
return sb_module;
|
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) {
|
SBSymbolContextList SBTarget::FindCompileUnits(const SBFileSpec &sb_file_spec) {
|
||||||
LLDB_INSTRUMENT_VA(this, sb_file_spec);
|
LLDB_INSTRUMENT_VA(this, sb_file_spec);
|
||||||
|
|
||||||
|
@ -392,45 +392,8 @@ bool Symbol::Compare(ConstString name, SymbolType type) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ENUM_TO_CSTRING(x) \
|
|
||||||
case eSymbolType##x: \
|
|
||||||
return #x;
|
|
||||||
|
|
||||||
const char *Symbol::GetTypeAsString() const {
|
const char *Symbol::GetTypeAsString() const {
|
||||||
switch (m_type) {
|
return GetTypeAsString(static_cast<lldb::SymbolType>(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>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Symbol::CalculateSymbolContext(SymbolContext *sc) {
|
void Symbol::CalculateSymbolContext(SymbolContext *sc) {
|
||||||
@ -774,6 +737,79 @@ bool Symbol::operator==(const Symbol &rhs) const {
|
|||||||
return true;
|
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 llvm {
|
||||||
namespace json {
|
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,
|
bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
|
||||||
llvm::json::Path path) {
|
llvm::json::Path path) {
|
||||||
if (auto str = value.getAsString()) {
|
if (auto str = value.getAsString()) {
|
||||||
type = llvm::StringSwitch<lldb::SymbolType>(*str)
|
llvm::StringRef str_ref = str.value_or("");
|
||||||
.Case("absolute", eSymbolTypeAbsolute)
|
type = Symbol::GetTypeFromString(str_ref.data());
|
||||||
.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);
|
|
||||||
|
|
||||||
if (type == eSymbolTypeInvalid) {
|
if (type == eSymbolTypeInvalid) {
|
||||||
path.report("invalid symbol type");
|
path.report("invalid symbol type");
|
||||||
|
3
lldb/test/API/tools/lldb-dap/moduleSymbols/Makefile
Normal file
3
lldb/test/API/tools/lldb-dap/moduleSymbols/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
C_SOURCES := main.c
|
||||||
|
|
||||||
|
include Makefile.rules
|
@ -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)
|
9
lldb/test/API/tools/lldb-dap/moduleSymbols/main.c
Normal file
9
lldb/test/API/tools/lldb-dap/moduleSymbols/main.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
int func1() { return 42; }
|
||||||
|
|
||||||
|
int func2() { return 84; }
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
func1();
|
||||||
|
func2();
|
||||||
|
return 0;
|
||||||
|
}
|
@ -45,6 +45,7 @@ add_lldb_library(lldbDAP
|
|||||||
Handler/LaunchRequestHandler.cpp
|
Handler/LaunchRequestHandler.cpp
|
||||||
Handler/LocationsRequestHandler.cpp
|
Handler/LocationsRequestHandler.cpp
|
||||||
Handler/ModulesRequestHandler.cpp
|
Handler/ModulesRequestHandler.cpp
|
||||||
|
Handler/ModuleSymbolsRequestHandler.cpp
|
||||||
Handler/NextRequestHandler.cpp
|
Handler/NextRequestHandler.cpp
|
||||||
Handler/PauseRequestHandler.cpp
|
Handler/PauseRequestHandler.cpp
|
||||||
Handler/ReadMemoryRequestHandler.cpp
|
Handler/ReadMemoryRequestHandler.cpp
|
||||||
|
@ -1258,6 +1258,27 @@ protocol::Capabilities DAP::GetCapabilities() {
|
|||||||
return capabilities;
|
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() {
|
void DAP::StartEventThread() {
|
||||||
event_thread = std::thread(&DAP::EventThread, this);
|
event_thread = std::thread(&DAP::EventThread, this);
|
||||||
}
|
}
|
||||||
@ -1614,6 +1635,7 @@ void DAP::RegisterRequests() {
|
|||||||
// Custom requests
|
// Custom requests
|
||||||
RegisterRequest<CompileUnitsRequestHandler>();
|
RegisterRequest<CompileUnitsRequestHandler>();
|
||||||
RegisterRequest<ModulesRequestHandler>();
|
RegisterRequest<ModulesRequestHandler>();
|
||||||
|
RegisterRequest<ModuleSymbolsRequestHandler>();
|
||||||
|
|
||||||
// Testing requests
|
// Testing requests
|
||||||
RegisterRequest<TestGetTargetBreakpointsRequestHandler>();
|
RegisterRequest<TestGetTargetBreakpointsRequestHandler>();
|
||||||
|
@ -367,6 +367,9 @@ struct DAP final : private DAPTransport::MessageHandler {
|
|||||||
/// The set of capabilities supported by this adapter.
|
/// The set of capabilities supported by this adapter.
|
||||||
protocol::Capabilities GetCapabilities();
|
protocol::Capabilities GetCapabilities();
|
||||||
|
|
||||||
|
/// The set of custom capabilities supported by this adapter.
|
||||||
|
protocol::Capabilities GetCustomCapabilities();
|
||||||
|
|
||||||
/// Debuggee will continue from stopped state.
|
/// Debuggee will continue from stopped state.
|
||||||
void WillContinue() { variables.Clear(); }
|
void WillContinue() { variables.Clear(); }
|
||||||
|
|
||||||
|
@ -38,25 +38,37 @@ static void SendThreadExitedEvent(DAP &dap, lldb::tid_t tid) {
|
|||||||
dap.SendJSON(llvm::json::Value(std::move(event)));
|
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())
|
if (!dap.target.IsValid())
|
||||||
return;
|
return capabilities;
|
||||||
|
|
||||||
protocol::CapabilitiesEventBody body;
|
|
||||||
|
|
||||||
const llvm::StringRef target_triple = dap.target.GetTriple();
|
const llvm::StringRef target_triple = dap.target.GetTriple();
|
||||||
if (target_triple.starts_with("x86"))
|
if (target_triple.starts_with("x86"))
|
||||||
body.capabilities.supportedFeatures.insert(
|
capabilities.insert(protocol::eAdapterFeatureStepInTargetsRequest);
|
||||||
protocol::eAdapterFeatureStepInTargetsRequest);
|
|
||||||
|
|
||||||
// We only support restarting launch requests not attach requests.
|
// We only support restarting launch requests not attach requests.
|
||||||
if (dap.last_launch_request)
|
if (dap.last_launch_request)
|
||||||
body.capabilities.supportedFeatures.insert(
|
capabilities.insert(protocol::eAdapterFeatureRestartRequest);
|
||||||
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.
|
// Only notify the client if supportedFeatures changed.
|
||||||
if (!body.capabilities.supportedFeatures.empty())
|
if (!body.capabilities.supportedFeatures.empty())
|
||||||
dap.Send(protocol::Event{"capabilities", body});
|
dap.Send(protocol::Event{"capabilities", std::move(body)});
|
||||||
}
|
}
|
||||||
|
|
||||||
// "ProcessEvent": {
|
// "ProcessEvent": {
|
||||||
|
@ -17,8 +17,8 @@ struct DAP;
|
|||||||
|
|
||||||
enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
|
enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
|
||||||
|
|
||||||
/// Update capabilities based on the configured target.
|
/// Sends target based capabilities and lldb-dap custom capabilities.
|
||||||
void SendTargetBasedCapabilities(DAP &dap);
|
void SendExtraCapabilities(DAP &dap);
|
||||||
|
|
||||||
void SendProcessEvent(DAP &dap, LaunchMethod launch_method);
|
void SendProcessEvent(DAP &dap, LaunchMethod launch_method);
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "DAP.h"
|
#include "DAP.h"
|
||||||
#include "EventHelper.h"
|
#include "EventHelper.h"
|
||||||
#include "LLDBUtils.h"
|
#include "LLDBUtils.h"
|
||||||
|
#include "Protocol/ProtocolEvents.h"
|
||||||
#include "Protocol/ProtocolRequests.h"
|
#include "Protocol/ProtocolRequests.h"
|
||||||
#include "ProtocolUtils.h"
|
#include "ProtocolUtils.h"
|
||||||
#include "RequestHandler.h"
|
#include "RequestHandler.h"
|
||||||
@ -44,7 +45,10 @@ ConfigurationDoneRequestHandler::Run(const ConfigurationDoneArguments &) const {
|
|||||||
// Waiting until 'configurationDone' to send target based capabilities in case
|
// Waiting until 'configurationDone' to send target based capabilities in case
|
||||||
// the launch or attach scripts adjust the target. The initial dummy target
|
// the launch or attach scripts adjust the target. The initial dummy target
|
||||||
// may have different capabilities than the final 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
|
// Clients can request a baseline of currently existing threads after
|
||||||
// we acknowledge the configurationDone request.
|
// we acknowledge the configurationDone request.
|
||||||
|
89
lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp
Normal file
89
lldb/tools/lldb-dap/Handler/ModuleSymbolsRequestHandler.cpp
Normal file
@ -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
|
@ -594,6 +594,20 @@ public:
|
|||||||
llvm::Error Run(const protocol::CancelArguments &args) const override;
|
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
|
/// 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
|
/// currently set in the target. This helps us to test "setBreakpoints" and
|
||||||
/// "setFunctionBreakpoints" requests to verify we have the correct set of
|
/// "setFunctionBreakpoints" requests to verify we have the correct set of
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include "Protocol/DAPTypes.h"
|
#include "Protocol/DAPTypes.h"
|
||||||
|
#include "lldb/API/SBSymbol.h"
|
||||||
|
#include "lldb/lldb-enumerations.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@ -33,4 +35,35 @@ llvm::json::Value toJSON(const SourceLLDBData &SLD) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace lldb_dap::protocol
|
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
|
||||||
|
@ -48,6 +48,38 @@ struct SourceLLDBData {
|
|||||||
bool fromJSON(const llvm::json::Value &, SourceLLDBData &, llvm::json::Path);
|
bool fromJSON(const llvm::json::Value &, SourceLLDBData &, llvm::json::Path);
|
||||||
llvm::json::Value toJSON(const SourceLLDBData &);
|
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
|
} // namespace lldb_dap::protocol
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -598,4 +598,19 @@ json::Value toJSON(const WriteMemoryResponseBody &WMR) {
|
|||||||
return result;
|
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
|
} // namespace lldb_dap::protocol
|
||||||
|
@ -981,6 +981,30 @@ struct WriteMemoryResponseBody {
|
|||||||
};
|
};
|
||||||
llvm::json::Value toJSON(const 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
|
} // namespace lldb_dap::protocol
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -335,6 +335,8 @@ static llvm::StringLiteral ToString(AdapterFeature feature) {
|
|||||||
return "supportsWriteMemoryRequest";
|
return "supportsWriteMemoryRequest";
|
||||||
case eAdapterFeatureTerminateDebuggee:
|
case eAdapterFeatureTerminateDebuggee:
|
||||||
return "supportTerminateDebuggee";
|
return "supportTerminateDebuggee";
|
||||||
|
case eAdapterFeatureSupportsModuleSymbolsRequest:
|
||||||
|
return "supportsModuleSymbolsRequest";
|
||||||
}
|
}
|
||||||
llvm_unreachable("unhandled adapter feature.");
|
llvm_unreachable("unhandled adapter feature.");
|
||||||
}
|
}
|
||||||
@ -406,6 +408,8 @@ bool fromJSON(const llvm::json::Value &Params, AdapterFeature &feature,
|
|||||||
eAdapterFeatureValueFormattingOptions)
|
eAdapterFeatureValueFormattingOptions)
|
||||||
.Case("supportsWriteMemoryRequest", eAdapterFeatureWriteMemoryRequest)
|
.Case("supportsWriteMemoryRequest", eAdapterFeatureWriteMemoryRequest)
|
||||||
.Case("supportTerminateDebuggee", eAdapterFeatureTerminateDebuggee)
|
.Case("supportTerminateDebuggee", eAdapterFeatureTerminateDebuggee)
|
||||||
|
.Case("supportsModuleSymbolsRequest",
|
||||||
|
eAdapterFeatureSupportsModuleSymbolsRequest)
|
||||||
.Default(std::nullopt);
|
.Default(std::nullopt);
|
||||||
|
|
||||||
if (!parsedFeature) {
|
if (!parsedFeature) {
|
||||||
|
@ -242,8 +242,11 @@ enum AdapterFeature : unsigned {
|
|||||||
/// The debug adapter supports the `terminateDebuggee` attribute on the
|
/// The debug adapter supports the `terminateDebuggee` attribute on the
|
||||||
/// `disconnect` request.
|
/// `disconnect` request.
|
||||||
eAdapterFeatureTerminateDebuggee,
|
eAdapterFeatureTerminateDebuggee,
|
||||||
|
/// The debug adapter supports the `supportsModuleSymbols` request.
|
||||||
|
/// This request is a custom request of lldb-dap.
|
||||||
|
eAdapterFeatureSupportsModuleSymbolsRequest,
|
||||||
eAdapterFeatureFirst = eAdapterFeatureANSIStyling,
|
eAdapterFeatureFirst = eAdapterFeatureANSIStyling,
|
||||||
eAdapterFeatureLast = eAdapterFeatureTerminateDebuggee,
|
eAdapterFeatureLast = eAdapterFeatureSupportsModuleSymbolsRequest,
|
||||||
};
|
};
|
||||||
bool fromJSON(const llvm::json::Value &, AdapterFeature &, llvm::json::Path);
|
bool fromJSON(const llvm::json::Value &, AdapterFeature &, llvm::json::Path);
|
||||||
llvm::json::Value toJSON(const AdapterFeature &);
|
llvm::json::Value toJSON(const AdapterFeature &);
|
||||||
|
513
lldb/tools/lldb-dap/package-lock.json
generated
513
lldb/tools/lldb-dap/package-lock.json
generated
@ -1,20 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "lldb-dap",
|
"name": "lldb-dap",
|
||||||
"version": "0.2.15",
|
"version": "0.2.16",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "lldb-dap",
|
"name": "lldb-dap",
|
||||||
"version": "0.2.15",
|
"version": "0.2.16",
|
||||||
"license": "Apache 2.0 License with LLVM exceptions",
|
"license": "Apache 2.0 License with LLVM exceptions",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.19.41",
|
"@types/node": "^18.19.41",
|
||||||
|
"@types/tabulator-tables": "^6.2.10",
|
||||||
"@types/vscode": "1.75.0",
|
"@types/vscode": "1.75.0",
|
||||||
|
"@types/vscode-webview": "^1.57.5",
|
||||||
"@vscode/debugprotocol": "^1.68.0",
|
"@vscode/debugprotocol": "^1.68.0",
|
||||||
"@vscode/vsce": "^3.2.2",
|
"@vscode/vsce": "^3.2.2",
|
||||||
|
"esbuild": "^0.25.9",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"prettier-plugin-curly": "^0.3.1",
|
"prettier-plugin-curly": "^0.3.1",
|
||||||
|
"tabulator-tables": "^6.3.1",
|
||||||
"typescript": "^5.7.3"
|
"typescript": "^5.7.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -318,6 +322,448 @@
|
|||||||
"node": ">=6.9.0"
|
"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": {
|
"node_modules/@isaacs/cliui": {
|
||||||
"version": "8.0.2",
|
"version": "8.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||||
@ -399,6 +845,13 @@
|
|||||||
"undici-types": "~5.26.4"
|
"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": {
|
"node_modules/@types/vscode": {
|
||||||
"version": "1.75.0",
|
"version": "1.75.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.0.tgz",
|
||||||
@ -406,6 +859,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/@vscode/debugprotocol": {
|
||||||
"version": "1.68.0",
|
"version": "1.68.0",
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/debugprotocol/-/debugprotocol-1.68.0.tgz",
|
"resolved": "https://registry.npmjs.org/@vscode/debugprotocol/-/debugprotocol-1.68.0.tgz",
|
||||||
@ -1169,6 +1629,48 @@
|
|||||||
"node": ">= 0.4"
|
"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": {
|
"node_modules/escape-string-regexp": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
@ -2557,6 +3059,13 @@
|
|||||||
"node": ">=4"
|
"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": {
|
"node_modules/tar-fs": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||||
|
@ -29,11 +29,15 @@
|
|||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.19.41",
|
"@types/node": "^18.19.41",
|
||||||
|
"@types/tabulator-tables": "^6.2.10",
|
||||||
"@types/vscode": "1.75.0",
|
"@types/vscode": "1.75.0",
|
||||||
|
"@types/vscode-webview": "^1.57.5",
|
||||||
"@vscode/debugprotocol": "^1.68.0",
|
"@vscode/debugprotocol": "^1.68.0",
|
||||||
"@vscode/vsce": "^3.2.2",
|
"@vscode/vsce": "^3.2.2",
|
||||||
|
"esbuild": "^0.25.9",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"prettier-plugin-curly": "^0.3.1",
|
"prettier-plugin-curly": "^0.3.1",
|
||||||
|
"tabulator-tables": "^6.3.1",
|
||||||
"typescript": "^5.7.3"
|
"typescript": "^5.7.3"
|
||||||
},
|
},
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
@ -42,8 +46,11 @@
|
|||||||
],
|
],
|
||||||
"main": "./out/extension",
|
"main": "./out/extension",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"vscode:prepublish": "tsc -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",
|
||||||
"watch": "tsc -watch -p ./",
|
"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",
|
"format": "npx prettier './src-ts/' --write",
|
||||||
"package": "rm -rf ./out/lldb-dap.vsix && vsce package --out ./out/lldb-dap.vsix",
|
"package": "rm -rf ./out/lldb-dap.vsix && vsce package --out ./out/lldb-dap.vsix",
|
||||||
"publish": "vsce publish",
|
"publish": "vsce publish",
|
||||||
@ -259,6 +266,15 @@
|
|||||||
{
|
{
|
||||||
"command": "lldb-dap.modules.copyProperty",
|
"command": "lldb-dap.modules.copyProperty",
|
||||||
"title": "Copy Value"
|
"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": {
|
"menus": {
|
||||||
@ -266,12 +282,24 @@
|
|||||||
{
|
{
|
||||||
"command": "lldb-dap.modules.copyProperty",
|
"command": "lldb-dap.modules.copyProperty",
|
||||||
"when": "false"
|
"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": [
|
"view/item/context": [
|
||||||
{
|
{
|
||||||
"command": "lldb-dap.modules.copyProperty",
|
"command": "lldb-dap.modules.copyProperty",
|
||||||
"when": "view == lldb-dap.modules && viewItem == property"
|
"when": "view == lldb-dap.modules && viewItem == property"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "lldb-dap.modules.showSymbols",
|
||||||
|
"when": "view == lldb-dap.modules && viewItem == module && lldb-dap.supportsModuleSymbolsRequest"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -69,6 +69,10 @@ const configurations: Record<string, DefaultConfig> = {
|
|||||||
terminateCommands: { type: "stringArray", default: [] },
|
terminateCommands: { type: "stringArray", default: [] },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function getDefaultConfigKey(key: string): string | number | boolean | string[] | undefined {
|
||||||
|
return configurations[key]?.default;
|
||||||
|
}
|
||||||
|
|
||||||
export class LLDBDapConfigurationProvider
|
export class LLDBDapConfigurationProvider
|
||||||
implements vscode.DebugConfigurationProvider
|
implements vscode.DebugConfigurationProvider
|
||||||
{
|
{
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
import { DebugProtocol } from "@vscode/debugprotocol";
|
import { DebugProtocol } from "@vscode/debugprotocol";
|
||||||
import * as vscode from "vscode";
|
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. */
|
/** A helper type for mapping event types to their corresponding data type. */
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
interface EventMap {
|
interface EventMap {
|
||||||
"module": DebugProtocol.ModuleEvent;
|
"module": DebugProtocol.ModuleEvent;
|
||||||
"exited": DebugProtocol.ExitedEvent;
|
"exited": DebugProtocol.ExitedEvent;
|
||||||
|
"capabilities": DebugProtocol.CapabilitiesEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A type assertion to check if a ProtocolMessage is an event or if it is a specific event. */
|
/** 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<
|
private modulesChanged = new vscode.EventEmitter<
|
||||||
vscode.DebugSession | undefined
|
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.
|
* Fired when modules are changed for any active debug session.
|
||||||
@ -48,6 +57,15 @@ export class DebugSessionTracker
|
|||||||
onDidChangeModules: vscode.Event<vscode.DebugSession | undefined> =
|
onDidChangeModules: vscode.Event<vscode.DebugSession | undefined> =
|
||||||
this.modulesChanged.event;
|
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) {
|
constructor(private logger: vscode.LogOutputChannel) {
|
||||||
this.onDidChangeModules(this.moduleChangedListener, this);
|
this.onDidChangeModules(this.moduleChangedListener, this);
|
||||||
vscode.debug.onDidChangeActiveDebugSession((session) =>
|
vscode.debug.onDidChangeActiveDebugSession((session) =>
|
||||||
@ -146,6 +164,10 @@ export class DebugSessionTracker
|
|||||||
this.logger.info(
|
this.logger.info(
|
||||||
`Session "${session.name}" exited with code ${exitCode}`,
|
`Session "${session.name}" exited with code ${exitCode}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.sessionExited.fire(session);
|
||||||
|
} else if (isEvent(message, "capabilities")) {
|
||||||
|
this.sessionReceivedCapabilities.fire([ session, message.body.capabilities ]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
ModuleProperty,
|
ModuleProperty,
|
||||||
} from "./ui/modules-data-provider";
|
} from "./ui/modules-data-provider";
|
||||||
import { LogFilePathProvider } from "./logging";
|
import { LogFilePathProvider } from "./logging";
|
||||||
|
import { SymbolsProvider } from "./ui/symbols-provider";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents the extension and manages its life cycle. Other extensions
|
* 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 {
|
export class LLDBDapExtension extends DisposableContext {
|
||||||
constructor(
|
constructor(
|
||||||
|
context: vscode.ExtensionContext,
|
||||||
logger: vscode.LogOutputChannel,
|
logger: vscode.LogOutputChannel,
|
||||||
logFilePath: LogFilePathProvider,
|
logFilePath: LogFilePathProvider,
|
||||||
outputChannel: vscode.OutputChannel,
|
outputChannel: vscode.OutputChannel,
|
||||||
@ -52,10 +54,12 @@ export class LLDBDapExtension extends DisposableContext {
|
|||||||
vscode.window.registerUriHandler(new LaunchUriHandler()),
|
vscode.window.registerUriHandler(new LaunchUriHandler()),
|
||||||
);
|
);
|
||||||
|
|
||||||
vscode.commands.registerCommand(
|
this.pushSubscription(vscode.commands.registerCommand(
|
||||||
"lldb-dap.modules.copyProperty",
|
"lldb-dap.modules.copyProperty",
|
||||||
(node: ModuleProperty) => vscode.env.clipboard.writeText(node.value),
|
(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...");
|
outputChannel.info("LLDB-DAP extension activating...");
|
||||||
const logFilePath = new LogFilePathProvider(context, outputChannel);
|
const logFilePath = new LogFilePathProvider(context, outputChannel);
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
new LLDBDapExtension(outputChannel, logFilePath, outputChannel),
|
new LLDBDapExtension(context, outputChannel, logFilePath, outputChannel),
|
||||||
);
|
);
|
||||||
outputChannel.info("LLDB-DAP extension activated");
|
outputChannel.info("LLDB-DAP extension activated");
|
||||||
}
|
}
|
||||||
|
14
lldb/tools/lldb-dap/src-ts/index.d.ts
vendored
Normal file
14
lldb/tools/lldb-dap/src-ts/index.d.ts
vendored
Normal file
@ -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;
|
||||||
|
}
|
@ -19,6 +19,7 @@ class ModuleItem extends vscode.TreeItem {
|
|||||||
constructor(module: DebugProtocol.Module) {
|
constructor(module: DebugProtocol.Module) {
|
||||||
super(module.name, vscode.TreeItemCollapsibleState.Collapsed);
|
super(module.name, vscode.TreeItemCollapsibleState.Collapsed);
|
||||||
this.description = module.symbolStatus;
|
this.description = module.symbolStatus;
|
||||||
|
this.contextValue = "module";
|
||||||
}
|
}
|
||||||
|
|
||||||
static getProperties(module: DebugProtocol.Module): ModuleProperty[] {
|
static getProperties(module: DebugProtocol.Module): ModuleProperty[] {
|
||||||
|
127
lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts
Normal file
127
lldb/tools/lldb-dap/src-ts/ui/symbols-provider.ts
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
51
lldb/tools/lldb-dap/src-ts/ui/symbols-webview-html.ts
Normal file
51
lldb/tools/lldb-dap/src-ts/ui/symbols-webview-html.ts
Normal file
@ -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>`;
|
||||||
|
}
|
114
lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts
Normal file
114
lldb/tools/lldb-dap/src-ts/webview/symbols-table-view.ts
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
15
lldb/tools/lldb-dap/src-ts/webview/tsconfig.json
Normal file
15
lldb/tools/lldb-dap/src-ts/webview/tsconfig.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"module": "esnext",
|
||||||
|
"outDir": "out",
|
||||||
|
"rootDir": ".",
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"target": "es2017"
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"./"
|
||||||
|
],
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"moduleResolution": "node",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"outDir": "out",
|
"outDir": "out",
|
||||||
"rootDir": "src-ts",
|
"rootDir": "src-ts",
|
||||||
@ -12,5 +13,6 @@
|
|||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
|
"src-ts/webview",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
add_lldb_unittest(DAPTests
|
add_lldb_unittest(DAPTests
|
||||||
DAPErrorTest.cpp
|
DAPErrorTest.cpp
|
||||||
DAPTest.cpp
|
DAPTest.cpp
|
||||||
|
DAPTypesTest.cpp
|
||||||
FifoFilesTest.cpp
|
FifoFilesTest.cpp
|
||||||
Handler/DisconnectTest.cpp
|
Handler/DisconnectTest.cpp
|
||||||
Handler/ContinueTest.cpp
|
Handler/ContinueTest.cpp
|
||||||
|
60
lldb/unittests/DAP/DAPTypesTest.cpp
Normal file
60
lldb/unittests/DAP/DAPTypesTest.cpp
Normal file
@ -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);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user