[Symbolize] Improve the ownership of parsed objects.
[oota-llvm.git] / lib / DebugInfo / Symbolize / Symbolize.cpp
index b0e17cfd3ffda035e407688686c8c28a32a05da3..3da1963bb791da7424f85078215e871595e5d694 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/DebugInfo/PDB/PDBContext.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/DebugInfo/PDB/PDBContext.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/MachO.h"
+#include "llvm/Object/MachOUniversal.h"
 #include "llvm/Support/COFF.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/COFF.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compression.h"
@@ -109,9 +110,10 @@ ErrorOr<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
 }
 
 void LLVMSymbolizer::flush() {
 }
 
 void LLVMSymbolizer::flush() {
-  Modules.clear();
+  ObjectForUBPathAndArch.clear();
+  BinaryForPath.clear();
   ObjectPairForPathArch.clear();
   ObjectPairForPathArch.clear();
-  ObjectFileForArch.clear();
+  Modules.clear();
 }
 
 // For Path="/path/to/foo" and Basename="foo" assume that debug info is in
 }
 
 // For Path="/path/to/foo" and Basename="foo" assume that debug info is in
@@ -223,49 +225,49 @@ ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
   for (const auto &Path : Opts.DsymHints) {
     DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename));
   }
   for (const auto &Path : Opts.DsymHints) {
     DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename));
   }
-  for (const auto &path : DsymPaths) {
-    ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(path);
-    if (!BinaryOrErr)
-      continue;
-    OwningBinary<Binary> &B = BinaryOrErr.get();
-    auto DbgObjOrErr = getObjectFileFromBinary(B.getBinary(), ArchName);
+  for (const auto &Path : DsymPaths) {
+    auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
     if (!DbgObjOrErr)
       continue;
     ObjectFile *DbgObj = DbgObjOrErr.get();
     if (!DbgObjOrErr)
       continue;
     ObjectFile *DbgObj = DbgObjOrErr.get();
-    const MachOObjectFile *MachDbgObj =
-        dyn_cast<const MachOObjectFile>(DbgObj);
+    const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
     if (!MachDbgObj)
       continue;
     if (!MachDbgObj)
       continue;
-    if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj)) {
-      addOwningBinary(std::move(B));
+    if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
       return DbgObj;
       return DbgObj;
-    }
   }
   return nullptr;
 }
 
   }
   return nullptr;
 }
 
+ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path,
+                                                  const ObjectFile *Obj,
+                                                  const std::string &ArchName) {
+  std::string DebuglinkName;
+  uint32_t CRCHash;
+  std::string DebugBinaryPath;
+  if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
+    return nullptr;
+  if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
+    return nullptr;
+  auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
+  if (!DbgObjOrErr)
+    return nullptr;
+  return DbgObjOrErr.get();
+}
+
 ErrorOr<LLVMSymbolizer::ObjectPair>
 ErrorOr<LLVMSymbolizer::ObjectPair>
-LLVMSymbolizer::getOrCreateObjects(const std::string &Path,
-                                   const std::string &ArchName) {
+LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
+                                      const std::string &ArchName) {
   const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
   if (I != ObjectPairForPathArch.end())
     return I->second;
 
   const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
   if (I != ObjectPairForPathArch.end())
     return I->second;
 
-  ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(Path);
-  if (auto EC = BinaryOrErr.getError()) {
-    ObjectPairForPathArch.insert(
-        std::make_pair(std::make_pair(Path, ArchName), EC));
-    return EC;
-  }
-  OwningBinary<Binary> &B = BinaryOrErr.get();
-
-  auto ObjOrErr = getObjectFileFromBinary(B.getBinary(), ArchName);
+  auto ObjOrErr = getOrCreateObject(Path, ArchName);
   if (auto EC = ObjOrErr.getError()) {
     ObjectPairForPathArch.insert(
         std::make_pair(std::make_pair(Path, ArchName), EC));
     return EC;
   }
   if (auto EC = ObjOrErr.getError()) {
     ObjectPairForPathArch.insert(
         std::make_pair(std::make_pair(Path, ArchName), EC));
     return EC;
   }
-  addOwningBinary(std::move(B));
 
   ObjectFile *Obj = ObjOrErr.get();
   assert(Obj != nullptr);
 
   ObjectFile *Obj = ObjOrErr.get();
   assert(Obj != nullptr);
@@ -273,27 +275,8 @@ LLVMSymbolizer::getOrCreateObjects(const std::string &Path,
 
   if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
     DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
 
   if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
     DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
-  // Try to locate the debug binary using .gnu_debuglink section.
-  if (!DbgObj) {
-    std::string DebuglinkName;
-    uint32_t CRCHash;
-    std::string DebugBinaryPath;
-    if (getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash) &&
-        findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) {
-      ErrorOr<OwningBinary<Binary>> DebugBinaryOrErr =
-          createBinary(DebugBinaryPath);
-      if (DebugBinaryOrErr) {
-        OwningBinary<Binary> &DB = DebugBinaryOrErr.get();
-        auto DbgObjOrErr = getObjectFileFromBinary(DB.getBinary(), ArchName);
-        if (DbgObjOrErr) {
-          DbgObj = DbgObjOrErr.get();
-          assert(DbgObj != nullptr);
-          addOwningBinary(std::move(DB));
-        }
-      }
-    }
-  }
-
+  if (!DbgObj)
+    DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
   if (!DbgObj)
     DbgObj = Obj;
   ObjectPair Res = std::make_pair(Obj, DbgObj);
   if (!DbgObj)
     DbgObj = Obj;
   ObjectPair Res = std::make_pair(Obj, DbgObj);
@@ -303,24 +286,43 @@ LLVMSymbolizer::getOrCreateObjects(const std::string &Path,
 }
 
 ErrorOr<ObjectFile *>
 }
 
 ErrorOr<ObjectFile *>
-LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin,
-                                        const std::string &ArchName) {
+LLVMSymbolizer::getOrCreateObject(const std::string &Path,
+                                  const std::string &ArchName) {
+  const auto &I = BinaryForPath.find(Path);
+  Binary *Bin = nullptr;
+  if (I == BinaryForPath.end()) {
+    ErrorOr<OwningBinary<Binary>> BinOrErr = createBinary(Path);
+    if (auto EC = BinOrErr.getError()) {
+      BinaryForPath.insert(std::make_pair(Path, EC));
+      return EC;
+    }
+    Bin = BinOrErr->getBinary();
+    BinaryForPath.insert(std::make_pair(Path, std::move(BinOrErr.get())));
+  } else if (auto EC = I->second.getError()) {
+    return EC;
+  } else {
+    Bin = I->second->getBinary();
+  }
+
   assert(Bin != nullptr);
   assert(Bin != nullptr);
+
   if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
   if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
-    const auto &I = ObjectFileForArch.find(
-        std::make_pair(UB, ArchName));
-    if (I != ObjectFileForArch.end())
-      return I->second;
-    ErrorOr<std::unique_ptr<ObjectFile>> ParsedObj =
+    const auto &I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
+    if (I != ObjectForUBPathAndArch.end()) {
+      if (auto EC = I->second.getError())
+        return EC;
+      return I->second->get();
+    }
+    ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
         UB->getObjectForArch(ArchName);
         UB->getObjectForArch(ArchName);
-    if (auto EC = ParsedObj.getError()) {
-      ObjectFileForArch.insert(
-          std::make_pair(std::make_pair(UB, ArchName), EC));
+    if (auto EC = ObjOrErr.getError()) {
+      ObjectForUBPathAndArch.insert(
+          std::make_pair(std::make_pair(Path, ArchName), EC));
       return EC;
     }
       return EC;
     }
-    ObjectFile *Res = ParsedObj.get().get();
-    ParsedBinariesAndObjects.push_back(std::move(ParsedObj.get()));
-    ObjectFileForArch.insert(std::make_pair(std::make_pair(UB, ArchName), Res));
+    ObjectFile *Res = ObjOrErr->get();
+    ObjectForUBPathAndArch.insert(std::make_pair(std::make_pair(Path, ArchName),
+                                                 std::move(ObjOrErr.get())));
     return Res;
   }
   if (Bin->isObject()) {
     return Res;
   }
   if (Bin->isObject()) {
@@ -349,7 +351,7 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
       ArchName = ArchStr;
     }
   }
       ArchName = ArchStr;
     }
   }
-  auto ObjectsOrErr = getOrCreateObjects(BinaryName, ArchName);
+  auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName);
   if (auto EC = ObjectsOrErr.getError()) {
     // Failed to find valid object file.
     Modules.insert(std::make_pair(ModuleName, EC));
   if (auto EC = ObjectsOrErr.getError()) {
     // Failed to find valid object file.
     Modules.insert(std::make_pair(ModuleName, EC));