From 3aef968ec3faada22319aaa3530776974082d2d5 Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Fri, 29 Jul 2022 15:19:17 -0700 Subject: [PATCH] [lldb] Allow SymbolTable regex search functions to match mangled name It may be useful to search symbol table entries by mangled instead of demangled names. Add this optional functionality in the SymbolTable functions. Differential Revision: https://reviews.llvm.org/D130803 --- lldb/include/lldb/Core/Module.h | 7 +- lldb/include/lldb/Symbol/Symtab.h | 15 ++-- lldb/source/Core/Module.cpp | 8 +- lldb/source/Symbol/Symtab.cpp | 16 ++-- lldb/test/Shell/Symtab/Inputs/symbols.yaml | 48 +++++++++++ lldb/test/Shell/Symtab/symtab-regex-demangled.test | 9 ++ lldb/test/Shell/Symtab/symtab-regex-mangled.test | 9 ++ lldb/tools/lldb-test/lldb-test.cpp | 98 ++++++++++++++++++++++ 8 files changed, 191 insertions(+), 19 deletions(-) create mode 100644 lldb/test/Shell/Symtab/Inputs/symbols.yaml create mode 100644 lldb/test/Shell/Symtab/symtab-regex-demangled.test create mode 100644 lldb/test/Shell/Symtab/symtab-regex-mangled.test diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index cc3edbb..117b14c 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -261,9 +261,10 @@ public: 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 index 504b49c..57627d2 100644 --- a/lldb/include/lldb/Symbol/Symtab.h +++ b/lldb/include/lldb/Symbol/Symtab.h @@ -89,14 +89,16 @@ public: 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 @@ public: 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 index 893e208..0d4466a 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1367,9 +1367,9 @@ void Module::FindSymbolsWithNameAndType(ConstString name, } } -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 @@ void Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, 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 index 936ee04..40777e0 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -744,7 +744,7 @@ uint32_t Symtab::AppendSymbolIndexesWithNameAndType( 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 @@ uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 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( 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 @@ uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( 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::FindAllSymbolsWithNameAndType( 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 index 0000000..64200ec --- /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 index 0000000..46cbc0d --- /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 index 0000000..d93091a --- /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 index 8c52648..c0dd95d 100644 --- 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 @@ static cl::SubCommand BreakpointSubcommand("breakpoints", 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::opt Log("log", cl::desc("Path to a log file"), cl::init(""), 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::list InputFilenames(cl::Positional, cl::desc(""), 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 @@ Expected opts::symbols::getAction() { 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 @@ int main(int argc, const char *argv[]) { 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) -- 2.7.4