diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -261,9 +261,10 @@ lldb::SymbolType symbol_type, SymbolContextList &sc_list); - void FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, - lldb::SymbolType symbol_type, - SymbolContextList &sc_list); + void FindSymbolsMatchingRegExAndType( + const RegularExpression ®ex, lldb::SymbolType symbol_type, + SymbolContextList &sc_list, + Mangled::NamePreference mangling_preference = Mangled::ePreferDemangled); /// Find a function symbols in the object file's symbol table. /// diff --git a/lldb/include/lldb/Symbol/Symtab.h b/lldb/include/lldb/Symbol/Symtab.h --- a/lldb/include/lldb/Symbol/Symtab.h +++ b/lldb/include/lldb/Symbol/Symtab.h @@ -89,14 +89,16 @@ Debug symbol_debug_type, Visibility symbol_visibility, std::vector &matches); - uint32_t - AppendSymbolIndexesMatchingRegExAndType(const RegularExpression ®ex, - lldb::SymbolType symbol_type, - std::vector &indexes); + uint32_t AppendSymbolIndexesMatchingRegExAndType( + const RegularExpression ®ex, lldb::SymbolType symbol_type, + std::vector &indexes, + Mangled::NamePreference name_preference = Mangled::ePreferDemangled); uint32_t AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector &indexes); + std::vector &indexes, + Mangled::NamePreference name_preference = + Mangled::NamePreference::ePreferDemangled); void FindAllSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, std::vector &symbol_indexes); @@ -108,7 +110,8 @@ void FindAllSymbolsMatchingRexExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector &symbol_indexes); + std::vector &symbol_indexes, + Mangled::NamePreference name_preference = Mangled::ePreferDemangled); Symbol *FindFirstSymbolWithNameAndType(ConstString name, lldb::SymbolType symbol_type, Debug symbol_debug_type, diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1367,9 +1367,9 @@ } } -void Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, - SymbolType symbol_type, - SymbolContextList &sc_list) { +void Module::FindSymbolsMatchingRegExAndType( + const RegularExpression ®ex, SymbolType symbol_type, + SymbolContextList &sc_list, Mangled::NamePreference mangling_preference) { // No need to protect this call using m_mutex all other method calls are // already thread safe. LLDB_SCOPED_TIMERF( @@ -1379,7 +1379,7 @@ std::vector symbol_indexes; symtab->FindAllSymbolsMatchingRexExAndType( regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, - symbol_indexes); + symbol_indexes, mangling_preference); SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); } } diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -744,7 +744,7 @@ uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®exp, SymbolType symbol_type, - std::vector &indexes) { + std::vector &indexes, Mangled::NamePreference name_preference) { std::lock_guard guard(m_mutex); uint32_t prev_size = indexes.size(); @@ -753,7 +753,8 @@ for (uint32_t i = 0; i < sym_end; i++) { if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) { - const char *name = m_symbols[i].GetName().AsCString(); + const char *name = + m_symbols[i].GetMangled().GetName(name_preference).AsCString(); if (name) { if (regexp.Execute(name)) indexes.push_back(i); @@ -766,7 +767,7 @@ uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®exp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector &indexes) { + std::vector &indexes, Mangled::NamePreference name_preference) { std::lock_guard guard(m_mutex); uint32_t prev_size = indexes.size(); @@ -778,7 +779,8 @@ if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) continue; - const char *name = m_symbols[i].GetName().AsCString(); + const char *name = + m_symbols[i].GetMangled().GetName(name_preference).AsCString(); if (name) { if (regexp.Execute(name)) indexes.push_back(i); @@ -847,11 +849,13 @@ void Symtab::FindAllSymbolsMatchingRexExAndType( const RegularExpression ®ex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector &symbol_indexes) { + std::vector &symbol_indexes, + Mangled::NamePreference name_preference) { std::lock_guard guard(m_mutex); AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, - symbol_visibility, symbol_indexes); + symbol_visibility, symbol_indexes, + name_preference); } Symbol *Symtab::FindFirstSymbolWithNameAndType(ConstString name, diff --git a/lldb/test/Shell/Symtab/Inputs/symbols.yaml b/lldb/test/Shell/Symtab/Inputs/symbols.yaml new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Symtab/Inputs/symbols.yaml @@ -0,0 +1,48 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_AARCH64 + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x4 + - Type: SectionHeaderTable + Sections: + - Name: .text + - Name: .strtab + - Name: .symtab +Symbols: + - Name: _Z8someFunciii + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Size: 0x1C + - Name: _Z8someFuncci + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x1C + Size: 0x18 + - Name: _Z13someOtherFuncv + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x34 + Size: 0x4 + - Name: _Z13someOtherFuncd + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x38 + Size: 0x10 + - Name: _Z18ignoreThisFunctionv + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x48 + Size: 0x8 +... diff --git a/lldb/test/Shell/Symtab/symtab-regex-demangled.test b/lldb/test/Shell/Symtab/symtab-regex-demangled.test new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Symtab/symtab-regex-demangled.test @@ -0,0 +1,9 @@ +# RUN: yaml2obj %S/Inputs/symbols.yaml -o %t +# + +# RUN: lldb-test symtab --find-symbols-by-regex='.*some.*' --mangling-preference=demangled %t | Filecheck %s +# CHECK: someFunc(int, int, int) +# CHECK: someFunc(char, int) +# CHECK: someOtherFunc() +# CHECK: someOtherFunc(double) +# CHECK-NOT: ignoreThisFunction() diff --git a/lldb/test/Shell/Symtab/symtab-regex-mangled.test b/lldb/test/Shell/Symtab/symtab-regex-mangled.test new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Symtab/symtab-regex-mangled.test @@ -0,0 +1,9 @@ +# RUN: yaml2obj %S/Inputs/symbols.yaml -o %t +# + +# RUN: lldb-test symtab --find-symbols-by-regex='.*some.*' --mangling-preference=mangled %t | Filecheck %s +# CHECK: _Z8someFunciii +# CHECK: _Z8someFuncci +# CHECK: _Z13someOtherFuncv +# CHECK: _Z13someOtherFuncd +# CHECK-NOT: _Z18ignoreThisFunctionv diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp --- a/lldb/tools/lldb-test/lldb-test.cpp +++ b/lldb/tools/lldb-test/lldb-test.cpp @@ -22,6 +22,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/Symtab.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/VariableList.h" @@ -57,6 +58,8 @@ cl::SubCommand ObjectFileSubcommand("object-file", "Display LLDB object file information"); cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file"); +cl::SubCommand SymTabSubcommand("symtab", + "Test symbol table functionality"); cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap"); cl::SubCommand AssertSubcommand("assert", "Test assert handling"); @@ -64,6 +67,7 @@ cl::sub(BreakpointSubcommand), cl::sub(ObjectFileSubcommand), cl::sub(SymbolsSubcommand), + cl::sub(SymTabSubcommand), cl::sub(IRMemoryMapSubcommand)); /// Create a target using the file pointed to by \p Filename, or abort. @@ -102,6 +106,48 @@ cl::sub(ObjectFileSubcommand)); } // namespace object +namespace symtab { + +/// The same enum as Mangled::NamePreference but with a default +/// 'None' case. This is needed to disambiguate wheter "ManglingPreference" was +/// explicitly set or not. +enum class ManglingPreference { + None, + Mangled, + Demangled, + MangledWithoutArguments, +}; + +static cl::opt FindSymbolsByRegex( + "find-symbols-by-regex", + cl::desc( + "Dump symbols found in the symbol table matching the specified regex."), + cl::sub(SymTabSubcommand)); + +static cl::opt ManglingPreference( + "mangling-preference", + cl::desc("Preference on mangling scheme the regex should match against and " + "dumped."), + cl::values( + clEnumValN(ManglingPreference::Mangled, "mangled", "Prefer mangled"), + clEnumValN(ManglingPreference::Demangled, "demangled", + "Prefer demangled"), + clEnumValN(ManglingPreference::MangledWithoutArguments, + "demangled-without-args", "Prefer mangled without args")), + cl::sub(SymTabSubcommand)); + +static cl::opt InputFile(cl::Positional, cl::desc(""), + cl::Required, cl::sub(SymTabSubcommand)); + +/// Validate that the options passed make sense. +static llvm::Optional validate(); + +/// Transforms the selected mangling preference into a Mangled::NamePreference +static Mangled::NamePreference getNamePreference(); + +static int handleSymtabCommand(Debugger &Dbg); +} // namespace symtab + namespace symbols { static cl::opt InputFile(cl::Positional, cl::desc(""), cl::Required, cl::sub(SymbolsSubcommand)); @@ -814,6 +860,56 @@ llvm_unreachable("Unsupported symbol action."); } +llvm::Optional opts::symtab::validate() { + if (ManglingPreference != ManglingPreference::None && + FindSymbolsByRegex.empty()) + return make_string_error("Mangling preference set but no regex specified."); + + return {}; +} + +static Mangled::NamePreference opts::symtab::getNamePreference() { + switch (ManglingPreference) { + case ManglingPreference::None: + case ManglingPreference::Mangled: + return Mangled::ePreferMangled; + case ManglingPreference::Demangled: + return Mangled::ePreferDemangled; + case ManglingPreference::MangledWithoutArguments: + return Mangled::ePreferDemangledWithoutArguments; + } +} + +int opts::symtab::handleSymtabCommand(Debugger &Dbg) { + if (auto error = validate()) { + logAllUnhandledErrors(std::move(error.getValue()), WithColor::error(), ""); + return 1; + } + + if (!FindSymbolsByRegex.empty()) { + ModuleSpec Spec{FileSpec(InputFile)}; + + auto ModulePtr = std::make_shared(Spec); + auto *Symtab = ModulePtr->GetSymtab(); + auto NamePreference = getNamePreference(); + std::vector Indexes; + + Symtab->FindAllSymbolsMatchingRexExAndType( + RegularExpression(FindSymbolsByRegex), lldb::eSymbolTypeAny, + Symtab::eDebugAny, Symtab::eVisibilityAny, Indexes, NamePreference); + for (auto i : Indexes) { + auto *symbol = Symtab->SymbolAtIndex(i); + if (symbol) { + StreamString stream; + symbol->Dump(&stream, nullptr, i, NamePreference); + outs() << stream.GetString(); + } + } + } + + return 0; +} + int opts::symbols::dumpSymbols(Debugger &Dbg) { auto ActionOr = getAction(); if (!ActionOr) { @@ -1128,6 +1224,8 @@ return dumpObjectFiles(*Dbg); if (opts::SymbolsSubcommand) return opts::symbols::dumpSymbols(*Dbg); + if (opts::SymTabSubcommand) + return opts::symtab::handleSymtabCommand(*Dbg); if (opts::IRMemoryMapSubcommand) return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg); if (opts::AssertSubcommand)