llvm-symbolizer: speedup symbol lookup
authorDmitry Vyukov <dvyukov@google.com>
Thu, 14 Feb 2013 13:06:18 +0000 (13:06 +0000)
committerDmitry Vyukov <dvyukov@google.com>
Thu, 14 Feb 2013 13:06:18 +0000 (13:06 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175158 91177308-0d34-0410-b5e6-96231b3b80d8

tools/llvm-symbolizer/LLVMSymbolize.cpp
tools/llvm-symbolizer/LLVMSymbolize.h

index 227580f4659691e46e34ce1d360c04e754916434..fe32178f02dbbb582737ee950fa67e0f320d9c91 100644 (file)
 namespace llvm {
 namespace symbolize {
 
+static bool error(error_code ec) {
+  if (!ec) return false;
+  errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
+  return true;
+}
+
 static uint32_t getDILineInfoSpecifierFlags(
     const LLVMSymbolizer::Options &Opts) {
   uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo |
@@ -37,6 +43,58 @@ static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName,
                         LineInfo.getLine(), LineInfo.getColumn());
 }
 
+ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
+    : Module(Obj)
+    , DebugInfoContext(DICtx) {
+  error_code ec;
+  for (symbol_iterator si = Module->begin_symbols(),
+                       se = Module->end_symbols();
+                       si != se; si.increment(ec)) {
+    if (error(ec))
+      return;
+    SymbolRef::Type SymbolType;
+    if (error(si->getType(SymbolType)))
+      continue;
+    if (SymbolType != SymbolRef::ST_Function
+        && SymbolType != SymbolRef::ST_Data)
+      continue;
+    uint64_t SymbolAddress;
+    if (error(si->getAddress(SymbolAddress))
+        || SymbolAddress == UnknownAddressOrSize)
+      continue;
+    uint64_t SymbolSize;
+    if (error(si->getSize(SymbolSize))
+        || SymbolSize == UnknownAddressOrSize)
+      continue;
+    StringRef SymbolName;
+    if (error(si->getName(SymbolName)))
+      continue;
+    // FIXME: If a function has alias, there are two entries in symbol table
+    // with same address size. Make sure we choose the correct one.
+    SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ?
+        Functions : Objects;
+    SymbolDesc SD = {SymbolAddress, SymbolAddress + SymbolSize};
+    M.insert(std::make_pair(SD, SymbolName));
+  }
+}
+
+bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
+                                        std::string &Name, uint64_t &Addr,
+                                        uint64_t &Size) const {
+  const SymbolMapTy& M = Type == SymbolRef::ST_Function ?
+      Functions : Objects;
+  SymbolDesc SD = {Address, Address + 1};
+  SymbolMapTy::const_iterator it = M.find(SD);
+  if (it == M.end())
+    return false;
+  if (Address < it->first.Addr || Address >= it->first.AddrEnd)
+    return false;
+  Name = it->second.str();
+  Addr = it->first.Addr;
+  Size = it->first.AddrEnd - it->first.Addr;
+  return true;
+}
+
 DILineInfo ModuleInfo::symbolizeCode(uint64_t ModuleOffset,
     const LLVMSymbolizer::Options& Opts) const {
   DILineInfo LineInfo;
@@ -94,44 +152,6 @@ bool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name,
                                 ModuleOffset, Name, Start, Size);
 }
 
-static bool error(error_code ec) {
-  if (!ec) return false;
-  errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
-  return true;
-}
-
-bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
-                                        std::string &Name, uint64_t &Addr,
-                                        uint64_t &Size) const {
-  assert(Module);
-  error_code ec;
-  for (symbol_iterator si = Module->begin_symbols(),
-                       se = Module->end_symbols();
-                       si != se; si.increment(ec)) {
-    if (error(ec)) return false;
-    uint64_t SymbolAddress;
-    uint64_t SymbolSize;
-    SymbolRef::Type SymbolType;
-    if (error(si->getAddress(SymbolAddress)) ||
-        SymbolAddress == UnknownAddressOrSize) continue;
-    if (error(si->getSize(SymbolSize)) ||
-        SymbolSize == UnknownAddressOrSize) continue;
-    if (error(si->getType(SymbolType))) continue;
-    // FIXME: If a function has alias, there are two entries in symbol table
-    // with same address size. Make sure we choose the correct one.
-    if (SymbolAddress <= Address && Address < SymbolAddress + SymbolSize &&
-        SymbolType == Type) {
-      StringRef SymbolName;
-      if (error(si->getName(SymbolName))) continue;
-      Name = SymbolName.str();
-      Addr = SymbolAddress;
-      Size = SymbolSize;
-      return true;
-    }
-  }
-  return false;
-}
-
 const char LLVMSymbolizer::kBadString[] = "??";
 
 std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
@@ -202,7 +222,6 @@ ModuleInfo *LLVMSymbolizer::getOrCreateModuleInfo(
     return I->second;
 
   ObjectFile *Obj = getObjectFile(ModuleName);
-  ObjectFile *DbgObj = Obj;
   if (Obj == 0) {
     // Module name doesn't point to a valid object file.
     Modules.insert(make_pair(ModuleName, (ModuleInfo*)0));
@@ -214,6 +233,7 @@ ModuleInfo *LLVMSymbolizer::getOrCreateModuleInfo(
   if (getObjectEndianness(Obj, IsLittleEndian)) {
     // On Darwin we may find DWARF in separate object file in
     // resource directory.
+    ObjectFile *DbgObj = Obj;
     if (isa<MachOObjectFile>(Obj)) {
       const std::string &ResourceName = getDarwinDWARFResourceForModule(
           ModuleName);
index 89684ddef25e7424fb2436d4f2dfb9f9ad724696..1755e1dc8827e937dd02bdfcd1f7503cce2a4ae5 100644 (file)
@@ -63,11 +63,8 @@ private:
 };
 
 class ModuleInfo {
-  OwningPtr<ObjectFile> Module;
-  OwningPtr<DIContext> DebugInfoContext;
  public:
-  ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
-      : Module(Obj), DebugInfoContext(DICtx) {}
+  ModuleInfo(ObjectFile *Obj, DIContext *DICtx);
 
   DILineInfo symbolizeCode(
       uint64_t ModuleOffset, const LLVMSymbolizer::Options& Opts) const;
@@ -80,6 +77,19 @@ class ModuleInfo {
   bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
                               std::string &Name, uint64_t &Addr,
                               uint64_t &Size) const;
+  OwningPtr<ObjectFile> Module;
+  OwningPtr<DIContext> DebugInfoContext;
+
+  struct SymbolDesc {
+    uint64_t Addr;
+    uint64_t AddrEnd;
+    friend bool operator<(const SymbolDesc& s1, const SymbolDesc& s2) {
+      return s1.AddrEnd <= s2.Addr;
+    }
+  };
+  typedef std::map<SymbolDesc, StringRef> SymbolMapTy;
+  SymbolMapTy Functions;
+  SymbolMapTy Objects;
 };
 
 }  // namespace symbolize