Skip to content

Commit 428ffbd

Browse files
authored
Re-land LLDB dap module symbol tables (llvm#155021)
Re-land the symbol table feature in lldb-dap after it was [reverted](llvm@2b8e806) because of a crash in the `aarch64` tests, which was caused by dereferencing `SBSymbol::GetName` which might return `nullptr` for an invalid symbol. This patch reapplies the original commits and adds the missing null check. Also adding `skipIfWindows` for the module symbols tests, since LLDB doesn't recognize the symbols from a.out there.
1 parent 8b3d4bd commit 428ffbd

38 files changed

+1447
-89
lines changed

lldb/include/lldb/API/SBSymbol.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ class LLDB_API SBSymbol {
8585

8686
SymbolType GetType();
8787

88+
/// Get the ID of this symbol, usually the original symbol table index.
89+
///
90+
/// \returns
91+
/// Returns the ID of this symbol.
92+
uint32_t GetID();
93+
8894
bool operator==(const lldb::SBSymbol &rhs) const;
8995

9096
bool operator!=(const lldb::SBSymbol &rhs) const;
@@ -99,6 +105,15 @@ class LLDB_API SBSymbol {
99105
// other than the actual symbol table itself in the object file.
100106
bool IsSynthetic();
101107

108+
/// Returns true if the symbol is a debug symbol.
109+
bool IsDebug();
110+
111+
/// Get the string representation of a symbol type.
112+
static const char *GetTypeAsString(lldb::SymbolType symbol_type);
113+
114+
/// Get the symbol type from a string representation.
115+
static lldb::SymbolType GetTypeFromString(const char *str);
116+
102117
protected:
103118
lldb_private::Symbol *get();
104119

lldb/include/lldb/API/SBTarget.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,16 @@ class LLDB_API SBTarget {
324324

325325
lldb::SBModule FindModule(const lldb::SBFileSpec &file_spec);
326326

327+
/// Find a module with the given module specification.
328+
///
329+
/// \param[in] module_spec
330+
/// A lldb::SBModuleSpec object that contains module specification.
331+
///
332+
/// \return
333+
/// A lldb::SBModule object that represents the found module, or an
334+
/// invalid SBModule object if no module was found.
335+
lldb::SBModule FindModule(const lldb::SBModuleSpec &module_spec);
336+
327337
/// Find compile units related to *this target and passed source
328338
/// file.
329339
///

lldb/include/lldb/Symbol/Symbol.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "lldb/Symbol/SymbolContextScope.h"
1616
#include "lldb/Utility/Stream.h"
1717
#include "lldb/Utility/UserID.h"
18+
#include "lldb/lldb-enumerations.h"
1819
#include "lldb/lldb-private.h"
1920
#include "llvm/Support/JSON.h"
2021

@@ -301,6 +302,10 @@ class Symbol : public SymbolContextScope {
301302

302303
bool operator==(const Symbol &rhs) const;
303304

305+
static const char *GetTypeAsString(lldb::SymbolType symbol_type);
306+
307+
static lldb::SymbolType GetTypeFromString(const char *str);
308+
304309
protected:
305310
// This is the internal guts of ResolveReExportedSymbol, it assumes
306311
// reexport_name is not null, and that module_spec is valid. We track the

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,25 @@ def request_modules(
12991299
{"command": "modules", "type": "request", "arguments": args_dict}
13001300
)
13011301

1302+
def request_moduleSymbols(
1303+
self,
1304+
moduleId: str = "",
1305+
moduleName: str = "",
1306+
startIndex: int = 0,
1307+
count: int = 0,
1308+
):
1309+
command_dict = {
1310+
"command": "__lldb_moduleSymbols",
1311+
"type": "request",
1312+
"arguments": {
1313+
"moduleId": moduleId,
1314+
"moduleName": moduleName,
1315+
"startIndex": startIndex,
1316+
"count": count,
1317+
},
1318+
}
1319+
return self._send_recv(command_dict)
1320+
13021321
def request_stackTrace(
13031322
self, threadId=None, startFrame=None, levels=None, format=None, dump=False
13041323
):

lldb/source/API/SBSymbol.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,14 @@ SymbolType SBSymbol::GetType() {
193193
return eSymbolTypeInvalid;
194194
}
195195

196+
uint32_t SBSymbol::GetID() {
197+
LLDB_INSTRUMENT_VA(this);
198+
199+
if (m_opaque_ptr)
200+
return m_opaque_ptr->GetID();
201+
return 0;
202+
}
203+
196204
bool SBSymbol::IsExternal() {
197205
LLDB_INSTRUMENT_VA(this);
198206

@@ -208,3 +216,23 @@ bool SBSymbol::IsSynthetic() {
208216
return m_opaque_ptr->IsSynthetic();
209217
return false;
210218
}
219+
220+
bool SBSymbol::IsDebug() {
221+
LLDB_INSTRUMENT_VA(this);
222+
223+
if (m_opaque_ptr)
224+
return m_opaque_ptr->IsDebug();
225+
return false;
226+
}
227+
228+
const char *SBSymbol::GetTypeAsString(lldb::SymbolType symbol_type) {
229+
LLDB_INSTRUMENT_VA(symbol_type);
230+
231+
return Symbol::GetTypeAsString(symbol_type);
232+
}
233+
234+
lldb::SymbolType SBSymbol::GetTypeFromString(const char *str) {
235+
LLDB_INSTRUMENT_VA(str);
236+
237+
return Symbol::GetTypeFromString(str);
238+
}

lldb/source/API/SBTarget.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,18 @@ SBModule SBTarget::FindModule(const SBFileSpec &sb_file_spec) {
15701570
return sb_module;
15711571
}
15721572

1573+
SBModule SBTarget::FindModule(const SBModuleSpec &sb_module_spec) {
1574+
LLDB_INSTRUMENT_VA(this, sb_module_spec);
1575+
1576+
SBModule sb_module;
1577+
if (TargetSP target_sp = GetSP(); target_sp && sb_module_spec.IsValid()) {
1578+
// The module list is thread safe, no need to lock.
1579+
sb_module.SetSP(
1580+
target_sp->GetImages().FindFirstModule(*sb_module_spec.m_opaque_up));
1581+
}
1582+
return sb_module;
1583+
}
1584+
15731585
SBSymbolContextList SBTarget::FindCompileUnits(const SBFileSpec &sb_file_spec) {
15741586
LLDB_INSTRUMENT_VA(this, sb_file_spec);
15751587

lldb/source/Symbol/Symbol.cpp

Lines changed: 76 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -392,45 +392,8 @@ bool Symbol::Compare(ConstString name, SymbolType type) const {
392392
return false;
393393
}
394394

395-
#define ENUM_TO_CSTRING(x) \
396-
case eSymbolType##x: \
397-
return #x;
398-
399395
const char *Symbol::GetTypeAsString() const {
400-
switch (m_type) {
401-
ENUM_TO_CSTRING(Invalid);
402-
ENUM_TO_CSTRING(Absolute);
403-
ENUM_TO_CSTRING(Code);
404-
ENUM_TO_CSTRING(Resolver);
405-
ENUM_TO_CSTRING(Data);
406-
ENUM_TO_CSTRING(Trampoline);
407-
ENUM_TO_CSTRING(Runtime);
408-
ENUM_TO_CSTRING(Exception);
409-
ENUM_TO_CSTRING(SourceFile);
410-
ENUM_TO_CSTRING(HeaderFile);
411-
ENUM_TO_CSTRING(ObjectFile);
412-
ENUM_TO_CSTRING(CommonBlock);
413-
ENUM_TO_CSTRING(Block);
414-
ENUM_TO_CSTRING(Local);
415-
ENUM_TO_CSTRING(Param);
416-
ENUM_TO_CSTRING(Variable);
417-
ENUM_TO_CSTRING(VariableType);
418-
ENUM_TO_CSTRING(LineEntry);
419-
ENUM_TO_CSTRING(LineHeader);
420-
ENUM_TO_CSTRING(ScopeBegin);
421-
ENUM_TO_CSTRING(ScopeEnd);
422-
ENUM_TO_CSTRING(Additional);
423-
ENUM_TO_CSTRING(Compiler);
424-
ENUM_TO_CSTRING(Instrumentation);
425-
ENUM_TO_CSTRING(Undefined);
426-
ENUM_TO_CSTRING(ObjCClass);
427-
ENUM_TO_CSTRING(ObjCMetaClass);
428-
ENUM_TO_CSTRING(ObjCIVar);
429-
ENUM_TO_CSTRING(ReExported);
430-
default:
431-
break;
432-
}
433-
return "<unknown SymbolType>";
396+
return GetTypeAsString(static_cast<lldb::SymbolType>(m_type));
434397
}
435398

436399
void Symbol::CalculateSymbolContext(SymbolContext *sc) {
@@ -774,6 +737,79 @@ bool Symbol::operator==(const Symbol &rhs) const {
774737
return true;
775738
}
776739

740+
#define ENUM_TO_CSTRING(x) \
741+
case eSymbolType##x: \
742+
return #x;
743+
744+
const char *Symbol::GetTypeAsString(lldb::SymbolType symbol_type) {
745+
switch (symbol_type) {
746+
ENUM_TO_CSTRING(Invalid);
747+
ENUM_TO_CSTRING(Absolute);
748+
ENUM_TO_CSTRING(Code);
749+
ENUM_TO_CSTRING(Resolver);
750+
ENUM_TO_CSTRING(Data);
751+
ENUM_TO_CSTRING(Trampoline);
752+
ENUM_TO_CSTRING(Runtime);
753+
ENUM_TO_CSTRING(Exception);
754+
ENUM_TO_CSTRING(SourceFile);
755+
ENUM_TO_CSTRING(HeaderFile);
756+
ENUM_TO_CSTRING(ObjectFile);
757+
ENUM_TO_CSTRING(CommonBlock);
758+
ENUM_TO_CSTRING(Block);
759+
ENUM_TO_CSTRING(Local);
760+
ENUM_TO_CSTRING(Param);
761+
ENUM_TO_CSTRING(Variable);
762+
ENUM_TO_CSTRING(VariableType);
763+
ENUM_TO_CSTRING(LineEntry);
764+
ENUM_TO_CSTRING(LineHeader);
765+
ENUM_TO_CSTRING(ScopeBegin);
766+
ENUM_TO_CSTRING(ScopeEnd);
767+
ENUM_TO_CSTRING(Additional);
768+
ENUM_TO_CSTRING(Compiler);
769+
ENUM_TO_CSTRING(Instrumentation);
770+
ENUM_TO_CSTRING(Undefined);
771+
ENUM_TO_CSTRING(ObjCClass);
772+
ENUM_TO_CSTRING(ObjCMetaClass);
773+
ENUM_TO_CSTRING(ObjCIVar);
774+
ENUM_TO_CSTRING(ReExported);
775+
}
776+
return "<unknown SymbolType>";
777+
}
778+
779+
lldb::SymbolType Symbol::GetTypeFromString(const char *str) {
780+
std::string str_lower = llvm::StringRef(str).lower();
781+
return llvm::StringSwitch<lldb::SymbolType>(str_lower)
782+
.Case("absolute", eSymbolTypeAbsolute)
783+
.Case("code", eSymbolTypeCode)
784+
.Case("resolver", eSymbolTypeResolver)
785+
.Case("data", eSymbolTypeData)
786+
.Case("trampoline", eSymbolTypeTrampoline)
787+
.Case("runtime", eSymbolTypeRuntime)
788+
.Case("exception", eSymbolTypeException)
789+
.Case("sourcefile", eSymbolTypeSourceFile)
790+
.Case("headerfile", eSymbolTypeHeaderFile)
791+
.Case("objectfile", eSymbolTypeObjectFile)
792+
.Case("commonblock", eSymbolTypeCommonBlock)
793+
.Case("block", eSymbolTypeBlock)
794+
.Case("local", eSymbolTypeLocal)
795+
.Case("param", eSymbolTypeParam)
796+
.Case("variable", eSymbolTypeVariable)
797+
.Case("variableType", eSymbolTypeVariableType)
798+
.Case("lineentry", eSymbolTypeLineEntry)
799+
.Case("lineheader", eSymbolTypeLineHeader)
800+
.Case("scopebegin", eSymbolTypeScopeBegin)
801+
.Case("scopeend", eSymbolTypeScopeEnd)
802+
.Case("additional,", eSymbolTypeAdditional)
803+
.Case("compiler", eSymbolTypeCompiler)
804+
.Case("instrumentation", eSymbolTypeInstrumentation)
805+
.Case("undefined", eSymbolTypeUndefined)
806+
.Case("objcclass", eSymbolTypeObjCClass)
807+
.Case("objcmetaclass", eSymbolTypeObjCMetaClass)
808+
.Case("objcivar", eSymbolTypeObjCIVar)
809+
.Case("reexported", eSymbolTypeReExported)
810+
.Default(eSymbolTypeInvalid);
811+
}
812+
777813
namespace llvm {
778814
namespace json {
779815

@@ -804,36 +840,8 @@ bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
804840
bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
805841
llvm::json::Path path) {
806842
if (auto str = value.getAsString()) {
807-
type = llvm::StringSwitch<lldb::SymbolType>(*str)
808-
.Case("absolute", eSymbolTypeAbsolute)
809-
.Case("code", eSymbolTypeCode)
810-
.Case("resolver", eSymbolTypeResolver)
811-
.Case("data", eSymbolTypeData)
812-
.Case("trampoline", eSymbolTypeTrampoline)
813-
.Case("runtime", eSymbolTypeRuntime)
814-
.Case("exception", eSymbolTypeException)
815-
.Case("sourcefile", eSymbolTypeSourceFile)
816-
.Case("headerfile", eSymbolTypeHeaderFile)
817-
.Case("objectfile", eSymbolTypeObjectFile)
818-
.Case("commonblock", eSymbolTypeCommonBlock)
819-
.Case("block", eSymbolTypeBlock)
820-
.Case("local", eSymbolTypeLocal)
821-
.Case("param", eSymbolTypeParam)
822-
.Case("variable", eSymbolTypeVariable)
823-
.Case("variableType", eSymbolTypeVariableType)
824-
.Case("lineentry", eSymbolTypeLineEntry)
825-
.Case("lineheader", eSymbolTypeLineHeader)
826-
.Case("scopebegin", eSymbolTypeScopeBegin)
827-
.Case("scopeend", eSymbolTypeScopeEnd)
828-
.Case("additional,", eSymbolTypeAdditional)
829-
.Case("compiler", eSymbolTypeCompiler)
830-
.Case("instrumentation", eSymbolTypeInstrumentation)
831-
.Case("undefined", eSymbolTypeUndefined)
832-
.Case("objcclass", eSymbolTypeObjCClass)
833-
.Case("objcmetaClass", eSymbolTypeObjCMetaClass)
834-
.Case("objcivar", eSymbolTypeObjCIVar)
835-
.Case("reexporte", eSymbolTypeReExported)
836-
.Default(eSymbolTypeInvalid);
843+
llvm::StringRef str_ref = str.value_or("");
844+
type = Symbol::GetTypeFromString(str_ref.data());
837845

838846
if (type == eSymbolTypeInvalid) {
839847
path.report("invalid symbol type");
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
C_SOURCES := main.c
2+
3+
include Makefile.rules
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
Test lldb-dap moduleSymbols request
3+
"""
4+
5+
import lldbdap_testcase
6+
from lldbsuite.test.decorators import *
7+
8+
9+
class TestDAP_moduleSymbols(lldbdap_testcase.DAPTestCaseBase):
10+
# On windows LLDB doesn't recognize symbols in a.out.
11+
@skipIfWindows
12+
def test_moduleSymbols(self):
13+
"""
14+
Test that the moduleSymbols request returns correct symbols from the module.
15+
"""
16+
program = self.getBuildArtifact("a.out")
17+
self.build_and_launch(program)
18+
19+
symbol_names = []
20+
i = 0
21+
while True:
22+
next_symbol = self.dap_server.request_moduleSymbols(
23+
moduleName="a.out", startIndex=i, count=1
24+
)
25+
self.assertIn("symbols", next_symbol["body"])
26+
result_symbols = next_symbol["body"]["symbols"]
27+
self.assertLessEqual(len(result_symbols), 1)
28+
if len(result_symbols) == 0:
29+
break
30+
31+
self.assertIn("name", result_symbols[0])
32+
symbol_names.append(result_symbols[0]["name"])
33+
i += 1
34+
if i >= 1000:
35+
break
36+
37+
self.assertGreater(len(symbol_names), 0)
38+
self.assertIn("main", symbol_names)
39+
self.assertIn("func1", symbol_names)
40+
self.assertIn("func2", symbol_names)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
int func1() { return 42; }
2+
3+
int func2() { return 84; }
4+
5+
int main() {
6+
func1();
7+
func2();
8+
return 0;
9+
}

0 commit comments

Comments
 (0)