From: Alexey Samsonov Date: Wed, 4 Nov 2015 00:30:24 +0000 (+0000) Subject: [LLVMSymbolize] Properly propagate object parsing errors from the library. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d2c42d439ab8a5a78f40ffdb503e67c1ae407347;p=oota-llvm.git [LLVMSymbolize] Properly propagate object parsing errors from the library. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252021 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/DebugInfo/Symbolize/Symbolize.h b/include/llvm/DebugInfo/Symbolize/Symbolize.h index 281d4cd3949..7871a2653a5 100644 --- a/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ b/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -18,6 +18,7 @@ #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include #include @@ -51,11 +52,12 @@ public: flush(); } - DILineInfo symbolizeCode(const std::string &ModuleName, - uint64_t ModuleOffset); - DIInliningInfo symbolizeInlinedCode(const std::string &ModuleName, - uint64_t ModuleOffset); - DIGlobal symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset); + ErrorOr symbolizeCode(const std::string &ModuleName, + uint64_t ModuleOffset); + ErrorOr symbolizeInlinedCode(const std::string &ModuleName, + uint64_t ModuleOffset); + ErrorOr symbolizeData(const std::string &ModuleName, + uint64_t ModuleOffset); void flush(); static std::string DemangleName(const std::string &Name, const SymbolizableModule *ModInfo); @@ -63,17 +65,19 @@ public: private: typedef std::pair ObjectPair; - SymbolizableModule *getOrCreateModuleInfo(const std::string &ModuleName); + ErrorOr + getOrCreateModuleInfo(const std::string &ModuleName); ObjectFile *lookUpDsymFile(const std::string &Path, const MachOObjectFile *ExeObj, const std::string &ArchName); /// \brief Returns pair of pointers to object and debug object. - ObjectPair getOrCreateObjects(const std::string &Path, - const std::string &ArchName); + ErrorOr getOrCreateObjects(const std::string &Path, + const std::string &ArchName); /// \brief Returns a parsed object file for a given architecture in a /// universal binary (or the binary itself if it is an object file). - ObjectFile *getObjectFileFromBinary(Binary *Bin, const std::string &ArchName); + ErrorOr getObjectFileFromBinary(Binary *Bin, + const std::string &ArchName); // Owns all the parsed binaries and object files. SmallVector, 4> ParsedBinariesAndObjects; @@ -86,10 +90,10 @@ private: MemoryBuffers.push_back(std::move(MemBuf)); } - std::map> Modules; - std::map, ObjectFile *> - ObjectFileForArch; - std::map, ObjectPair> + std::map>> Modules; + std::map, + ErrorOr> ObjectFileForArch; + std::map, ErrorOr> ObjectPairForPathArch; Options Opts; diff --git a/lib/DebugInfo/Symbolize/Symbolize.cpp b/lib/DebugInfo/Symbolize/Symbolize.cpp index 348c2b00bbe..b0e17cfd3ff 100644 --- a/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -46,19 +46,12 @@ namespace llvm { namespace symbolize { -// FIXME: Move this to llvm-symbolizer tool. -static bool error(std::error_code ec) { - if (!ec) - return false; - errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n"; - return true; -} - -DILineInfo LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, - uint64_t ModuleOffset) { - SymbolizableModule *Info = getOrCreateModuleInfo(ModuleName); - if (!Info) - return DILineInfo(); +ErrorOr LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, + uint64_t ModuleOffset) { + auto InfoOrErr = getOrCreateModuleInfo(ModuleName); + if (auto EC = InfoOrErr.getError()) + return EC; + SymbolizableModule *Info = InfoOrErr.get(); // If the user is giving us relative addresses, add the preferred base of the // object to the offset before we do the query. It's what DIContext expects. @@ -72,12 +65,13 @@ DILineInfo LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, return LineInfo; } -DIInliningInfo +ErrorOr LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, uint64_t ModuleOffset) { - SymbolizableModule *Info = getOrCreateModuleInfo(ModuleName); - if (!Info) - return DIInliningInfo(); + auto InfoOrErr = getOrCreateModuleInfo(ModuleName); + if (auto EC = InfoOrErr.getError()) + return EC; + SymbolizableModule *Info = InfoOrErr.get(); // If the user is giving us relative addresses, add the preferred base of the // object to the offset before we do the query. It's what DIContext expects. @@ -95,13 +89,12 @@ LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, return InlinedContext; } -DIGlobal LLVMSymbolizer::symbolizeData(const std::string &ModuleName, - uint64_t ModuleOffset) { - if (!Opts.UseSymbolTable) - return DIGlobal(); - SymbolizableModule *Info = getOrCreateModuleInfo(ModuleName); - if (!Info) - return DIGlobal(); +ErrorOr LLVMSymbolizer::symbolizeData(const std::string &ModuleName, + uint64_t ModuleOffset) { + auto InfoOrErr = getOrCreateModuleInfo(ModuleName); + if (auto EC = InfoOrErr.getError()) + return EC; + SymbolizableModule *Info = InfoOrErr.get(); // If the user is giving us relative addresses, add the preferred base of // the object to the offset before we do the query. It's what DIContext @@ -232,72 +225,87 @@ ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath, } for (const auto &path : DsymPaths) { ErrorOr> BinaryOrErr = createBinary(path); - std::error_code EC = BinaryOrErr.getError(); - if (EC != errc::no_such_file_or_directory && !error(EC)) { - OwningBinary B = std::move(BinaryOrErr.get()); - ObjectFile *DbgObj = - getObjectFileFromBinary(B.getBinary(), ArchName); - const MachOObjectFile *MachDbgObj = - dyn_cast(DbgObj); - if (!MachDbgObj) continue; - if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj)) { - addOwningBinary(std::move(B)); - return DbgObj; - } + if (!BinaryOrErr) + continue; + OwningBinary &B = BinaryOrErr.get(); + auto DbgObjOrErr = getObjectFileFromBinary(B.getBinary(), ArchName); + if (!DbgObjOrErr) + continue; + ObjectFile *DbgObj = DbgObjOrErr.get(); + const MachOObjectFile *MachDbgObj = + dyn_cast(DbgObj); + if (!MachDbgObj) + continue; + if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj)) { + addOwningBinary(std::move(B)); + return DbgObj; } } return nullptr; } -LLVMSymbolizer::ObjectPair +ErrorOr LLVMSymbolizer::getOrCreateObjects(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; - ObjectFile *Obj = nullptr; - ObjectFile *DbgObj = nullptr; + ErrorOr> BinaryOrErr = createBinary(Path); - if (!error(BinaryOrErr.getError())) { - OwningBinary &B = BinaryOrErr.get(); - Obj = getObjectFileFromBinary(B.getBinary(), ArchName); - if (!Obj) { - ObjectPair Res = std::make_pair(nullptr, nullptr); - ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res; - return Res; - } - addOwningBinary(std::move(B)); - if (auto MachObj = dyn_cast(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)) { - BinaryOrErr = createBinary(DebugBinaryPath); - if (!error(BinaryOrErr.getError())) { - OwningBinary B = std::move(BinaryOrErr.get()); - DbgObj = getObjectFileFromBinary(B.getBinary(), ArchName); - addOwningBinary(std::move(B)); + if (auto EC = BinaryOrErr.getError()) { + ObjectPairForPathArch.insert( + std::make_pair(std::make_pair(Path, ArchName), EC)); + return EC; + } + OwningBinary &B = BinaryOrErr.get(); + + auto ObjOrErr = getObjectFileFromBinary(B.getBinary(), ArchName); + 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 *DbgObj = nullptr; + + if (auto MachObj = dyn_cast(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> DebugBinaryOrErr = + createBinary(DebugBinaryPath); + if (DebugBinaryOrErr) { + OwningBinary &DB = DebugBinaryOrErr.get(); + auto DbgObjOrErr = getObjectFileFromBinary(DB.getBinary(), ArchName); + if (DbgObjOrErr) { + DbgObj = DbgObjOrErr.get(); + assert(DbgObj != nullptr); + addOwningBinary(std::move(DB)); } } } } + if (!DbgObj) DbgObj = Obj; ObjectPair Res = std::make_pair(Obj, DbgObj); - ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res; + ObjectPairForPathArch.insert( + std::make_pair(std::make_pair(Path, ArchName), Res)); return Res; } -ObjectFile * +ErrorOr LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) { - if (!Bin) - return nullptr; - ObjectFile *Res = nullptr; + assert(Bin != nullptr); if (MachOUniversalBinary *UB = dyn_cast(Bin)) { const auto &I = ObjectFileForArch.find( std::make_pair(UB, ArchName)); @@ -305,22 +313,31 @@ LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, return I->second; ErrorOr> ParsedObj = UB->getObjectForArch(ArchName); - if (ParsedObj) { - Res = ParsedObj.get().get(); - ParsedBinariesAndObjects.push_back(std::move(ParsedObj.get())); + if (auto EC = ParsedObj.getError()) { + ObjectFileForArch.insert( + std::make_pair(std::make_pair(UB, ArchName), EC)); + return EC; } - ObjectFileForArch[std::make_pair(UB, ArchName)] = Res; - } else if (Bin->isObject()) { - Res = cast(Bin); + ObjectFile *Res = ParsedObj.get().get(); + ParsedBinariesAndObjects.push_back(std::move(ParsedObj.get())); + ObjectFileForArch.insert(std::make_pair(std::make_pair(UB, ArchName), Res)); + return Res; } - return Res; + if (Bin->isObject()) { + return cast(Bin); + } + return object_error::arch_not_found; } -SymbolizableModule * +ErrorOr LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { const auto &I = Modules.find(ModuleName); - if (I != Modules.end()) - return I->second.get(); + if (I != Modules.end()) { + auto &InfoOrErr = I->second; + if (auto EC = InfoOrErr.getError()) + return EC; + return InfoOrErr->get(); + } std::string BinaryName = ModuleName; std::string ArchName = Opts.DefaultArch; size_t ColonPos = ModuleName.find_last_of(':'); @@ -332,13 +349,14 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { ArchName = ArchStr; } } - ObjectPair Objects = getOrCreateObjects(BinaryName, ArchName); - - if (!Objects.first) { + auto ObjectsOrErr = getOrCreateObjects(BinaryName, ArchName); + if (auto EC = ObjectsOrErr.getError()) { // Failed to find valid object file. - Modules.insert(std::make_pair(ModuleName, nullptr)); - return nullptr; + Modules.insert(std::make_pair(ModuleName, EC)); + return EC; } + ObjectPair Objects = ObjectsOrErr.get(); + std::unique_ptr Context; if (auto CoffObject = dyn_cast(Objects.first)) { // If this is a COFF object, assume it contains PDB debug information. If @@ -353,15 +371,14 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { if (!Context) Context.reset(new DWARFContextInMemory(*Objects.second)); assert(Context); - auto ErrOrInfo = + auto InfoOrErr = SymbolizableObjectFile::create(Objects.first, std::move(Context)); - if (error(ErrOrInfo.getError())) { - Modules.insert(std::make_pair(ModuleName, nullptr)); - return nullptr; - } - SymbolizableModule *Res = ErrOrInfo.get().get(); - Modules.insert(std::make_pair(ModuleName, std::move(ErrOrInfo.get()))); - return Res; + auto InsertResult = + Modules.insert(std::make_pair(ModuleName, std::move(InfoOrErr))); + assert(InsertResult.second); + if (auto EC = InsertResult.first->second.getError()) + return EC; + return InsertResult.first->second->get(); } // Undo these various manglings for Win32 extern "C" functions: diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp index 99afa6db53a..d0ef51e6f17 100644 --- a/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -78,6 +78,13 @@ static cl::opt ClPrintAddress("print-address", cl::init(false), cl::desc("Show address before line information")); +static bool error(std::error_code ec) { + if (!ec) + return false; + errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n"; + return true; +} + static bool parseCommand(bool &IsData, std::string &ModuleName, uint64_t &ModuleOffset) { const char *kDataCmd = "DATA "; @@ -158,11 +165,15 @@ int main(int argc, char **argv) { outs() << "\n"; } if (IsData) { - Printer << Symbolizer.symbolizeData(ModuleName, ModuleOffset); + auto ResOrErr = Symbolizer.symbolizeData(ModuleName, ModuleOffset); + Printer << (error(ResOrErr.getError()) ? DIGlobal() : ResOrErr.get()); } else if (ClPrintInlining) { - Printer << Symbolizer.symbolizeInlinedCode(ModuleName, ModuleOffset); + auto ResOrErr = Symbolizer.symbolizeInlinedCode(ModuleName, ModuleOffset); + Printer << (error(ResOrErr.getError()) ? DIInliningInfo() + : ResOrErr.get()); } else { - Printer << Symbolizer.symbolizeCode(ModuleName, ModuleOffset); + auto ResOrErr = Symbolizer.symbolizeCode(ModuleName, ModuleOffset); + Printer << (error(ResOrErr.getError()) ? DILineInfo() : ResOrErr.get()); } outs() << "\n"; outs().flush();