Add a multi-type version of iterateSymbolsWithType
authorTeng Qin <qinteng@fb.com>
Thu, 9 Nov 2017 04:04:18 +0000 (20:04 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 9 Nov 2017 04:06:49 +0000 (20:06 -0800)
Summary:
When using `folly::symbolizer`, it's very often that we want to use `iterateSymbolsWithType` iterate through symbols of a few types using the same callback. Current approach would require iterating the section multiple times.

This Diff adds `iterateSymbolsWithTypes`, which is basically just `iterateSymbolsWithType` but accepts symbol types.

This Diff also updated implementation of `getDefinitionByAddress` and `getSymbolByName` which currently does two iterations for `STT_OBJECT` and `STT_FUNC`.

Reviewed By: yfeldblum

Differential Revision: D6279651

fbshipit-source-id: a661dd15f18e4f2f63dbcca615f5a86d92e528ea

folly/experimental/symbolizer/Elf-inl.h
folly/experimental/symbolizer/Elf.cpp
folly/experimental/symbolizer/Elf.h

index bd9b0a4029252332494027a9e7d147f3334d9640..3e2f4dcf3ba70a9f2d306c0d8e2e2dcb4b87b8f3 100644 (file)
@@ -97,5 +97,18 @@ const ElfSym* ElfFile::iterateSymbolsWithType(
   });
 }
 
   });
 }
 
+template <class Fn>
+const ElfSym* ElfFile::iterateSymbolsWithTypes(
+    const ElfShdr& section,
+    std::initializer_list<uint32_t> types,
+    Fn fn) const {
+  // N.B. st_info has the same representation on 32- and 64-bit platforms
+  return iterateSymbols(section, [&](const ElfSym& sym) -> bool {
+    auto const elfType = ELF32_ST_TYPE(sym.st_info);
+    auto const it = std::find(types.begin(), types.end(), elfType);
+    return it != types.end() && fn(sym);
+  });
+}
+
 } // namespace symbolizer
 } // namespace folly
 } // namespace symbolizer
 } // namespace folly
index a0dfe9ce9b1e66baa4ba8d140690c7f456519424..7be8f69db89d63891956ab8c554fbd0f7c78f280 100644 (file)
@@ -360,8 +360,8 @@ ElfFile::Symbol ElfFile::getDefinitionByAddress(uintptr_t address) const {
       return false;
     };
 
       return false;
     };
 
-    return iterateSymbolsWithType(section, STT_OBJECT, findSymbols) ||
-        iterateSymbolsWithType(section, STT_FUNC, findSymbols);
+    return iterateSymbolsWithTypes(
+        section, {STT_OBJECT, STT_FUNC}, findSymbols);
   };
 
   // Try the .dynsym section first if it exists, it's smaller.
   };
 
   // Try the .dynsym section first if it exists, it's smaller.
@@ -399,8 +399,8 @@ ElfFile::Symbol ElfFile::getSymbolByName(const char* name) const {
       return false;
     };
 
       return false;
     };
 
-    return iterateSymbolsWithType(section, STT_OBJECT, findSymbols) ||
-        iterateSymbolsWithType(section, STT_FUNC, findSymbols);
+    return iterateSymbolsWithTypes(
+        section, {STT_OBJECT, STT_FUNC}, findSymbols);
   };
 
   // Try the .dynsym section first if it exists, it's smaller.
   };
 
   // Try the .dynsym section first if it exists, it's smaller.
index c097be6928e80f66d483ba2846736fc7e50ceacd..477d8798b512f50968a6825081ecfb427748f238 100644 (file)
@@ -23,6 +23,7 @@
 #include <link.h> // For ElfW()
 
 #include <cstdio>
 #include <link.h> // For ElfW()
 
 #include <cstdio>
+#include <initializer_list>
 #include <stdexcept>
 #include <system_error>
 
 #include <stdexcept>
 #include <system_error>
 
@@ -156,6 +157,11 @@ class ElfFile {
   template <class Fn>
   const ElfSym*
   iterateSymbolsWithType(const ElfShdr& section, uint32_t type, Fn fn) const;
   template <class Fn>
   const ElfSym*
   iterateSymbolsWithType(const ElfShdr& section, uint32_t type, Fn fn) const;
+  template <class Fn>
+  const ElfSym* iterateSymbolsWithTypes(
+      const ElfShdr& section,
+      std::initializer_list<uint32_t> types,
+      Fn fn) const;
 
   /**
    * Find symbol definition by address.
 
   /**
    * Find symbol definition by address.