[lldb] Allow SymbolTable regex search functions to match mangled name
authorAugusto Noronha <augusto2112@me.com>
Fri, 29 Jul 2022 22:19:17 +0000 (15:19 -0700)
committerAugusto Noronha <augusto2112@me.com>
Wed, 3 Aug 2022 17:55:32 +0000 (10:55 -0700)
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
lldb/include/lldb/Symbol/Symtab.h
lldb/source/Core/Module.cpp
lldb/source/Symbol/Symtab.cpp
lldb/test/Shell/Symtab/Inputs/symbols.yaml [new file with mode: 0644]
lldb/test/Shell/Symtab/symtab-regex-demangled.test [new file with mode: 0644]
lldb/test/Shell/Symtab/symtab-regex-mangled.test [new file with mode: 0644]
lldb/tools/lldb-test/lldb-test.cpp

index cc3edbb..117b14c 100644 (file)
@@ -261,9 +261,10 @@ public:
                                   lldb::SymbolType symbol_type,
                                   SymbolContextList &sc_list);
 
-  void FindSymbolsMatchingRegExAndType(const RegularExpression &regex,
-                                       lldb::SymbolType symbol_type,
-                                       SymbolContextList &sc_list);
+  void FindSymbolsMatchingRegExAndType(
+      const RegularExpression &regex, lldb::SymbolType symbol_type,
+      SymbolContextList &sc_list,
+      Mangled::NamePreference mangling_preference = Mangled::ePreferDemangled);
 
   /// Find a function symbols in the object file's symbol table.
   ///
index 504b49c..57627d2 100644 (file)
@@ -89,14 +89,16 @@ public:
                                               Debug symbol_debug_type,
                                               Visibility symbol_visibility,
                                               std::vector<uint32_t> &matches);
-  uint32_t
-  AppendSymbolIndexesMatchingRegExAndType(const RegularExpression &regex,
-                                          lldb::SymbolType symbol_type,
-                                          std::vector<uint32_t> &indexes);
+  uint32_t AppendSymbolIndexesMatchingRegExAndType(
+      const RegularExpression &regex, lldb::SymbolType symbol_type,
+      std::vector<uint32_t> &indexes,
+      Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
   uint32_t AppendSymbolIndexesMatchingRegExAndType(
       const RegularExpression &regex, lldb::SymbolType symbol_type,
       Debug symbol_debug_type, Visibility symbol_visibility,
-      std::vector<uint32_t> &indexes);
+      std::vector<uint32_t> &indexes,
+      Mangled::NamePreference name_preference =
+          Mangled::NamePreference::ePreferDemangled);
   void FindAllSymbolsWithNameAndType(ConstString name,
                                      lldb::SymbolType symbol_type,
                                      std::vector<uint32_t> &symbol_indexes);
@@ -108,7 +110,8 @@ public:
   void FindAllSymbolsMatchingRexExAndType(
       const RegularExpression &regex, lldb::SymbolType symbol_type,
       Debug symbol_debug_type, Visibility symbol_visibility,
-      std::vector<uint32_t> &symbol_indexes);
+      std::vector<uint32_t> &symbol_indexes,
+      Mangled::NamePreference name_preference = Mangled::ePreferDemangled);
   Symbol *FindFirstSymbolWithNameAndType(ConstString name,
                                          lldb::SymbolType symbol_type,
                                          Debug symbol_debug_type,
index 893e208..0d4466a 100644 (file)
@@ -1367,9 +1367,9 @@ void Module::FindSymbolsWithNameAndType(ConstString name,
   }
 }
 
-void Module::FindSymbolsMatchingRegExAndType(const RegularExpression &regex,
-                                             SymbolType symbol_type,
-                                             SymbolContextList &sc_list) {
+void Module::FindSymbolsMatchingRegExAndType(
+    const RegularExpression &regex, 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 &regex,
     std::vector<uint32_t> symbol_indexes;
     symtab->FindAllSymbolsMatchingRexExAndType(
         regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny,
-        symbol_indexes);
+        symbol_indexes, mangling_preference);
     SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list);
   }
 }
index 936ee04..40777e0 100644 (file)
@@ -744,7 +744,7 @@ uint32_t Symtab::AppendSymbolIndexesWithNameAndType(
 
 uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType(
     const RegularExpression &regexp, SymbolType symbol_type,
-    std::vector<uint32_t> &indexes) {
+    std::vector<uint32_t> &indexes, Mangled::NamePreference name_preference) {
   std::lock_guard<std::recursive_mutex> 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 &regexp, SymbolType symbol_type,
     Debug symbol_debug_type, Visibility symbol_visibility,
-    std::vector<uint32_t> &indexes) {
+    std::vector<uint32_t> &indexes, Mangled::NamePreference name_preference) {
   std::lock_guard<std::recursive_mutex> 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 &regex, SymbolType symbol_type,
     Debug symbol_debug_type, Visibility symbol_visibility,
-    std::vector<uint32_t> &symbol_indexes) {
+    std::vector<uint32_t> &symbol_indexes,
+    Mangled::NamePreference name_preference) {
   std::lock_guard<std::recursive_mutex> 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 (file)
index 0000000..64200ec
--- /dev/null
@@ -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 (file)
index 0000000..46cbc0d
--- /dev/null
@@ -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 (file)
index 0000000..d93091a
--- /dev/null
@@ -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
index 8c52648..c0dd95d 100644 (file)
@@ -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<std::string> 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<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
                                      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<std::string> 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> 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<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
+                                      cl::Required, cl::sub(SymTabSubcommand));
+
+/// Validate that the options passed make sense.
+static llvm::Optional<llvm::Error> 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<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
                                       cl::Required, cl::sub(SymbolsSubcommand));
@@ -814,6 +860,56 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
   llvm_unreachable("Unsupported symbol action.");
 }
 
+llvm::Optional<llvm::Error> 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<lldb_private::Module>(Spec);
+    auto *Symtab = ModulePtr->GetSymtab();
+    auto NamePreference = getNamePreference();
+    std::vector<uint32_t> 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)