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/t.yaml b/lldb/test/Shell/Symtab/Inputs/t.yaml new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/Symtab/Inputs/t.yaml @@ -0,0 +1,381 @@ +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x2 + ncmds: 17 + sizeofcmds: 872 + flags: 0x200085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __PAGEZERO + vmaddr: 0 + vmsize: 4294967296 + fileoff: 0 + filesize: 0 + maxprot: 0 + initprot: 0 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 3 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x100003E98 + size: 100 + offset: 0x3E98 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: FF4300D1E00F00B9E10B00B9E20700B900008052FF430091C0035FD6FF4300D1E03F0039E10B00B900008052FF430091C0035FD6C0035FD6FF4300D1E00700FDFF430091C0035FD600008052C0035FD6FF4300D100008052FF0F00B9FF430091C0035FD6 + - sectname: __unwind_info + segname: __TEXT + addr: 0x100003EFC + size: 108 + offset: 0x3EFC + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000002983E00003800000038000000FD3E00000000000038000000030000000C00060024000400000000041C0000033400000038000002480000005000000178000003580000033800000314000003 + - sectname: __eh_frame + segname: __TEXT + addr: 0x100003F68 + size: 152 + offset: 0x3F68 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 1000000000000000017A520001781E01100C1F00200000001800000014FFFFFFFFFFFFFF1C0000000000000000440E10540E0000000000001C0000003C0000000CFFFFFFFFFFFFFF180000000000000000440E10500E00001C0000005C00000008FFFFFFFFFFFFFF100000000000000000440E10480E00001C0000007C00000000FFFFFFFFFFFFFF140000000000000000440E104C0E0000 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 4294983680 + vmsize: 16384 + fileoff: 16384 + filesize: 1406 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_CHAINED_FIXUPS + cmdsize: 16 + dataoff: 16384 + datasize: 56 + - cmd: LC_DYLD_EXPORTS_TRIE + cmdsize: 16 + dataoff: 16440 + datasize: 152 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 16600 + nsyms: 36 + stroff: 17176 + strsize: 336 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 29 + iextdefsym: 29 + nextdefsym: 7 + iundefsym: 36 + nundefsym: 0 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_LOAD_DYLINKER + cmdsize: 32 + name: 12 + Content: '/usr/lib/dyld' + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 6B38C912-BA3D-3844-A980-CB841E352057 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 786432 + sdk: 787712 + ntools: 1 + Tools: + - tool: 3 + version: 53674497 + - cmd: LC_SOURCE_VERSION + cmdsize: 16 + version: 0 + - cmd: LC_MAIN + cmdsize: 24 + entryoff: 16104 + stacksize: 0 + - cmd: LC_LOAD_DYLIB + cmdsize: 48 + dylib: + name: 24 + timestamp: 2 + current_version: 85203200 + compatibility_version: 65536 + Content: '/usr/lib/libc++.1.dylib' + ZeroPadBytes: 1 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 2 + current_version: 85948417 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 16592 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 16600 + datasize: 0 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 17520 + datasize: 270 +LinkEditData: + NameList: + - n_strx: 1 + n_type: 0x64 + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 124 + n_type: 0x64 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 161 + n_type: 0x64 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 167 + n_type: 0x66 + n_sect: 0 + n_desc: 1 + n_value: 1659474921 + - n_strx: 1 + n_type: 0x2E + n_sect: 1 + n_desc: 0 + n_value: 4294983320 + - n_strx: 227 + n_type: 0x24 + n_sect: 1 + n_desc: 0 + n_value: 4294983320 + - n_strx: 1 + n_type: 0x24 + n_sect: 0 + n_desc: 0 + n_value: 28 + - n_strx: 1 + n_type: 0x4E + n_sect: 1 + n_desc: 0 + n_value: 4294983320 + - n_strx: 1 + n_type: 0x2E + n_sect: 1 + n_desc: 0 + n_value: 4294983348 + - n_strx: 243 + n_type: 0x24 + n_sect: 1 + n_desc: 0 + n_value: 4294983348 + - n_strx: 1 + n_type: 0x24 + n_sect: 0 + n_desc: 0 + n_value: 24 + - n_strx: 1 + n_type: 0x4E + n_sect: 1 + n_desc: 0 + n_value: 4294983348 + - n_strx: 1 + n_type: 0x2E + n_sect: 1 + n_desc: 0 + n_value: 4294983372 + - n_strx: 258 + n_type: 0x24 + n_sect: 1 + n_desc: 0 + n_value: 4294983372 + - n_strx: 1 + n_type: 0x24 + n_sect: 0 + n_desc: 0 + n_value: 4 + - n_strx: 1 + n_type: 0x4E + n_sect: 1 + n_desc: 0 + n_value: 4294983372 + - n_strx: 1 + n_type: 0x2E + n_sect: 1 + n_desc: 0 + n_value: 4294983376 + - n_strx: 278 + n_type: 0x24 + n_sect: 1 + n_desc: 0 + n_value: 4294983376 + - n_strx: 1 + n_type: 0x24 + n_sect: 0 + n_desc: 0 + n_value: 16 + - n_strx: 1 + n_type: 0x4E + n_sect: 1 + n_desc: 0 + n_value: 4294983376 + - n_strx: 1 + n_type: 0x2E + n_sect: 1 + n_desc: 0 + n_value: 4294983392 + - n_strx: 298 + n_type: 0x24 + n_sect: 1 + n_desc: 0 + n_value: 4294983392 + - n_strx: 1 + n_type: 0x24 + n_sect: 0 + n_desc: 0 + n_value: 8 + - n_strx: 1 + n_type: 0x4E + n_sect: 1 + n_desc: 0 + n_value: 4294983392 + - n_strx: 1 + n_type: 0x2E + n_sect: 1 + n_desc: 0 + n_value: 4294983400 + - n_strx: 323 + n_type: 0x24 + n_sect: 1 + n_desc: 0 + n_value: 4294983400 + - n_strx: 1 + n_type: 0x24 + n_sect: 0 + n_desc: 0 + n_value: 20 + - n_strx: 1 + n_type: 0x4E + n_sect: 1 + n_desc: 0 + n_value: 4294983400 + - n_strx: 1 + n_type: 0x64 + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4294983376 + - n_strx: 22 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4294983372 + - n_strx: 42 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4294983392 + - n_strx: 67 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4294983348 + - n_strx: 82 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4294983320 + - n_strx: 98 + n_type: 0xF + n_sect: 1 + n_desc: 16 + n_value: 4294967296 + - n_strx: 118 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4294983400 + StringTable: + - ' ' + - __Z13someOtherFuncd + - __Z13someOtherFuncv + - __Z18ignoreThisFunctionv + - __Z8someFuncci + - __Z8someFunciii + - __mh_execute_header + - _main + - '/Users/augusto/Developer/llvm/build/' + - t.cpp + - '/var/folders/jx/c2z2mmps7fl3bn58k7b8ztdm0000gn/T/t-93fc40.o' + - __Z8someFunciii + - __Z8someFuncci + - __Z13someOtherFuncv + - __Z13someOtherFuncd + - __Z18ignoreThisFunctionv + - _main + - '' + - '' + - '' + - '' + - '' + - '' + - '' + FunctionStarts: [ 0x3E98, 0x3EB4, 0x3ECC, 0x3ED0, 0x3EE0, 0x3EE8 ] +... 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/t.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/t.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)