From f27f3f8491dfc7aa41f6cd8a95763acc677d379c Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 3 Jun 2016 20:25:09 +0000 Subject: [PATCH] [Symbolize] Check if the PE file has a PDB and emit an error if we can't load it Summary: Previously we would try to load PDBs for every PE executable we tried to symbolize. If that failed, we would fall back to DWARF. If there wasn't any DWARF, we'd print mostly useless symbol information using the export table. With this change, we only try to load PDBs for executables that claim to have them. If that fails, we can now print an error rather than falling back silently. This should make it a lot easier to diagnose and fix common symbolization issues, such as not having DIA or not having a PDB. Reviewers: zturner, eugenis Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D20982 llvm-svn: 271725 --- .../llvm/DebugInfo/Symbolize/Symbolize.h | 31 ++-- llvm/include/llvm/Object/COFF.h | 8 + llvm/lib/DebugInfo/Symbolize/Symbolize.cpp | 154 ++++++++++-------- llvm/lib/Object/COFFObjectFile.cpp | 11 ++ .../pdb/Inputs/missing_pdb.exe | Bin 0 -> 32256 bytes .../llvm-symbolizer/pdb/missing_pdb.test | 17 ++ .../tools/llvm-symbolizer/llvm-symbolizer.cpp | 14 +- llvm/tools/sancov/sancov.cc | 6 + llvm/tools/sanstats/sanstats.cpp | 6 +- 9 files changed, 161 insertions(+), 86 deletions(-) create mode 100644 llvm/test/tools/llvm-symbolizer/pdb/Inputs/missing_pdb.exe create mode 100644 llvm/test/tools/llvm-symbolizer/pdb/missing_pdb.test diff --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h index 1c487aafc573..9253adf7eedd 100644 --- a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -49,12 +49,12 @@ public: flush(); } - 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); + Expected symbolizeCode(const std::string &ModuleName, + uint64_t ModuleOffset); + Expected symbolizeInlinedCode(const std::string &ModuleName, + uint64_t ModuleOffset); + Expected symbolizeData(const std::string &ModuleName, + uint64_t ModuleOffset); void flush(); static std::string DemangleName(const std::string &Name, const SymbolizableModule *ModInfo); @@ -64,8 +64,13 @@ private: // corresponding debug info. These objects can be the same. typedef std::pair ObjectPair; - ErrorOr + /// Returns a SymbolizableModule or an error if loading debug info failed. + /// Only one attempt is made to load a module, and errors during loading are + /// only reported once. Subsequent calls to get module info for a module that + /// failed to load will return nullptr. + Expected getOrCreateModuleInfo(const std::string &ModuleName); + ObjectFile *lookUpDsymFile(const std::string &Path, const MachOObjectFile *ExeObj, const std::string &ArchName); @@ -74,27 +79,27 @@ private: const std::string &ArchName); /// \brief Returns pair of pointers to object and debug object. - ErrorOr getOrCreateObjectPair(const std::string &Path, + Expected getOrCreateObjectPair(const std::string &Path, const std::string &ArchName); /// \brief Return a pointer to object file at specified path, for a specified /// architecture (e.g. if path refers to a Mach-O universal binary, only one /// object file from it will be returned). - ErrorOr getOrCreateObject(const std::string &Path, + Expected getOrCreateObject(const std::string &Path, const std::string &ArchName); - std::map>> Modules; + std::map> Modules; /// \brief Contains cached results of getOrCreateObjectPair(). - std::map, ErrorOr> + std::map, ObjectPair> ObjectPairForPathArch; /// \brief Contains parsed binary for each path, or parsing error. - std::map>> BinaryForPath; + std::map> BinaryForPath; /// \brief Parsed object file for path/architecture pair, where "path" refers /// to Mach-O universal binary. - std::map, ErrorOr>> + std::map, std::unique_ptr> ObjectForUBPathAndArch; Options Opts; diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h index f859b7dea1a0..4578ce10f1ce 100644 --- a/llvm/include/llvm/Object/COFF.h +++ b/llvm/include/llvm/Object/COFF.h @@ -870,10 +870,18 @@ public: std::error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + /// Get PDB information out of a codeview debug directory entry. std::error_code getDebugPDBInfo(const debug_directory *DebugDir, const debug_pdb_info *&Info, StringRef &PDBFileName) const; + /// Get PDB information from an executable. If the information is not present, + /// Info will be set to nullptr and PDBFileName will be empty. An error is + /// returned only on corrupt object files. Convenience accessor that can be + /// used if the debug directory is not already handy. + std::error_code getDebugPDBInfo(const debug_pdb_info *&Info, + StringRef &PDBFileName) const; + bool isRelocatableObject() const override; bool is64() const { return PE32PlusHeader; } diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index 9c12169fb673..e2732bf819eb 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -50,12 +50,18 @@ namespace llvm { namespace symbolize { -ErrorOr LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, +Expected LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, uint64_t ModuleOffset) { - auto InfoOrErr = getOrCreateModuleInfo(ModuleName); - if (auto EC = InfoOrErr.getError()) - return EC; - SymbolizableModule *Info = InfoOrErr.get(); + SymbolizableModule *Info; + if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) + Info = InfoOrErr.get(); + else + return InfoOrErr.takeError(); + + // A null module means an error has already been reported. Return an empty + // result. + if (!Info) + return DILineInfo(); // 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. @@ -69,13 +75,19 @@ ErrorOr LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, return LineInfo; } -ErrorOr +Expected LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, uint64_t ModuleOffset) { - auto InfoOrErr = getOrCreateModuleInfo(ModuleName); - if (auto EC = InfoOrErr.getError()) - return EC; - SymbolizableModule *Info = InfoOrErr.get(); + SymbolizableModule *Info; + if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) + Info = InfoOrErr.get(); + else + return InfoOrErr.takeError(); + + // A null module means an error has already been reported. Return an empty + // result. + if (!Info) + return DIInliningInfo(); // 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. @@ -93,12 +105,18 @@ LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, return InlinedContext; } -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(); +Expected LLVMSymbolizer::symbolizeData(const std::string &ModuleName, + uint64_t ModuleOffset) { + SymbolizableModule *Info; + if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName)) + Info = InfoOrErr.get(); + else + return InfoOrErr.takeError(); + + // A null module means an error has already been reported. Return an empty + // result. + if (!Info) + return DIGlobal(); // 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,9 +250,14 @@ ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath, } for (const auto &Path : DsymPaths) { auto DbgObjOrErr = getOrCreateObject(Path, ArchName); - if (!DbgObjOrErr) + if (!DbgObjOrErr) { + // Ignore errors, the file might not exist. + consumeError(DbgObjOrErr.takeError()); continue; + } ObjectFile *DbgObj = DbgObjOrErr.get(); + if (!DbgObj) + continue; const MachOObjectFile *MachDbgObj = dyn_cast(DbgObj); if (!MachDbgObj) continue; @@ -255,23 +278,27 @@ ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path, if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) return nullptr; auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName); - if (!DbgObjOrErr) + if (!DbgObjOrErr) { + // Ignore errors, the file might not exist. + consumeError(DbgObjOrErr.takeError()); return nullptr; + } return DbgObjOrErr.get(); } -ErrorOr +Expected LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path, const std::string &ArchName) { const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName)); - if (I != ObjectPairForPathArch.end()) + if (I != ObjectPairForPathArch.end()) { return I->second; + } auto ObjOrErr = getOrCreateObject(Path, ArchName); - if (auto EC = ObjOrErr.getError()) { - ObjectPairForPathArch.insert( - std::make_pair(std::make_pair(Path, ArchName), EC)); - return EC; + if (!ObjOrErr) { + ObjectPairForPathArch.insert(std::make_pair(std::make_pair(Path, ArchName), + ObjectPair(nullptr, nullptr))); + return ObjOrErr.takeError(); } ObjectFile *Obj = ObjOrErr.get(); @@ -290,7 +317,7 @@ LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path, return Res; } -ErrorOr +Expected LLVMSymbolizer::getOrCreateObject(const std::string &Path, const std::string &ArchName) { const auto &I = BinaryForPath.find(Path); @@ -298,34 +325,29 @@ LLVMSymbolizer::getOrCreateObject(const std::string &Path, if (I == BinaryForPath.end()) { Expected> BinOrErr = createBinary(Path); if (!BinOrErr) { - auto EC = errorToErrorCode(BinOrErr.takeError()); - BinaryForPath.insert(std::make_pair(Path, EC)); - return EC; + BinaryForPath.insert({Path, OwningBinary()}); + return BinOrErr.takeError(); } 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(); + Bin = I->second.getBinary(); } - assert(Bin != nullptr); + if (!Bin) + return static_cast(nullptr); - if (MachOUniversalBinary *UB = dyn_cast(Bin)) { + if (MachOUniversalBinary *UB = dyn_cast_or_null(Bin)) { 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(); + return I->second.get(); } Expected> ObjOrErr = UB->getObjectForArch(ArchName); if (!ObjOrErr) { - auto EC = errorToErrorCode(ObjOrErr.takeError()); - ObjectForUBPathAndArch.insert( - std::make_pair(std::make_pair(Path, ArchName), EC)); - return EC; + ObjectForUBPathAndArch.insert(std::make_pair( + std::make_pair(Path, ArchName), std::unique_ptr())); + return ObjOrErr.takeError(); } ObjectFile *Res = ObjOrErr->get(); ObjectForUBPathAndArch.insert(std::make_pair(std::make_pair(Path, ArchName), @@ -335,17 +357,14 @@ LLVMSymbolizer::getOrCreateObject(const std::string &Path, if (Bin->isObject()) { return cast(Bin); } - return object_error::arch_not_found; + return errorCodeToError(object_error::arch_not_found); } -ErrorOr +Expected LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { const auto &I = Modules.find(ModuleName); if (I != Modules.end()) { - auto &InfoOrErr = I->second; - if (auto EC = InfoOrErr.getError()) - return EC; - return InfoOrErr->get(); + return I->second.get(); } std::string BinaryName = ModuleName; std::string ArchName = Opts.DefaultArch; @@ -359,27 +378,31 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { } } auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName); - if (auto EC = ObjectsOrErr.getError()) { + if (!ObjectsOrErr) { // Failed to find valid object file. - Modules.insert(std::make_pair(ModuleName, EC)); - return EC; + Modules.insert( + std::make_pair(ModuleName, std::unique_ptr())); + return ObjectsOrErr.takeError(); } ObjectPair Objects = ObjectsOrErr.get(); std::unique_ptr Context; + // If this is a COFF object containing PDB info, use a PDBContext to + // symbolize. Otherwise, use DWARF. if (auto CoffObject = dyn_cast(Objects.first)) { - using namespace pdb; - // If this is a COFF object, assume it contains PDB debug information. If - // we don't find any we will fall back to the DWARF case. - std::unique_ptr Session; - auto Error = loadDataForEXE( - PDB_ReaderType::DIA, Objects.first->getFileName(), Session); - if (!Error) { + const debug_pdb_info *PDBInfo; + StringRef PDBFileName; + auto EC = CoffObject->getDebugPDBInfo(PDBInfo, PDBFileName); + if (!EC && PDBInfo != nullptr) { + using namespace pdb; + std::unique_ptr Session; + if (auto Err = loadDataForEXE(PDB_ReaderType::DIA, + Objects.first->getFileName(), Session)) { + Modules.insert( + std::make_pair(ModuleName, std::unique_ptr())); + return std::move(Err); + } Context.reset(new PDBContext(*CoffObject, std::move(Session))); - } else { - // Drop error - handleAllErrors(std::move(Error), - [](const ErrorInfoBase &) { return Error::success(); }); } } if (!Context) @@ -387,12 +410,15 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { assert(Context); auto InfoOrErr = SymbolizableObjectFile::create(Objects.first, std::move(Context)); + std::unique_ptr SymMod; + if (InfoOrErr) + SymMod = std::move(InfoOrErr.get()); auto InsertResult = - Modules.insert(std::make_pair(ModuleName, std::move(InfoOrErr))); + Modules.insert(std::make_pair(ModuleName, std::move(SymMod))); assert(InsertResult.second); - if (auto EC = InsertResult.first->second.getError()) - return EC; - return InsertResult.first->second->get(); + if (auto EC = InfoOrErr.getError()) + return errorCodeToError(EC); + return InsertResult.first->second.get(); } namespace { diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index 8390edda3bff..28627cd1d42a 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -505,6 +505,17 @@ std::error_code COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, return std::error_code(); } +std::error_code COFFObjectFile::getDebugPDBInfo(const debug_pdb_info *&PDBInfo, + StringRef &PDBFileName) const { + for (const debug_directory &D : debug_directories()) + if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) + return getDebugPDBInfo(&D, PDBInfo, PDBFileName); + // If we get here, there is no PDB info to return. + PDBInfo = nullptr; + PDBFileName = StringRef(); + return std::error_code(); +} + // Find the import table. std::error_code COFFObjectFile::initImportTablePtr() { // First, we get the RVA of the import table. If the file lacks a pointer to diff --git a/llvm/test/tools/llvm-symbolizer/pdb/Inputs/missing_pdb.exe b/llvm/test/tools/llvm-symbolizer/pdb/Inputs/missing_pdb.exe new file mode 100644 index 0000000000000000000000000000000000000000..320e1f30e582c6f2ea99773990e51dbbff74e6a0 GIT binary patch literal 32256 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 Wt=-CE_}ey_wU}Fo>Cd+pf&T;3o9+hy literal 0 HcmV?d00001 diff --git a/llvm/test/tools/llvm-symbolizer/pdb/missing_pdb.test b/llvm/test/tools/llvm-symbolizer/pdb/missing_pdb.test new file mode 100644 index 000000000000..0478dfbc05eb --- /dev/null +++ b/llvm/test/tools/llvm-symbolizer/pdb/missing_pdb.test @@ -0,0 +1,17 @@ +RUN: grep '^ADDR:' %s | sed -s 's/ADDR: //' \ +RUN: | llvm-symbolizer -obj="%p/Inputs/missing_pdb.exe" 2>%t.err \ +RUN: | FileCheck %s +RUN: FileCheck --check-prefix=ERROR %s < %t.err + +ADDR: 0x401000 +ADDR: 0x401001 + +llvm-symbolizer should print one error and two unknown line info records. + +ERROR: LLVMSymbolizer: error reading file: PDB Error: Unable to load PDB. Make sure the file exists and is readable. +ERROR-NOT: error reading file + +CHECK: ?? +CHECK: ??:0:0 +CHECK: ?? +CHECK: ??:0:0 diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp index 950349377bf7..4a3a7b3d2f36 100644 --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -86,10 +86,12 @@ static cl::opt ClPrintSourceContextLines( "print-source-context-lines", cl::init(0), cl::desc("Print N number of source file context")); -static bool error(std::error_code ec) { - if (!ec) +template +static bool error(Expected &ResOrErr) { + if (ResOrErr) return false; - errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n"; + logAllUnhandledErrors(ResOrErr.takeError(), errs(), + "LLVMSymbolizer: error reading file: "); return true; } @@ -185,14 +187,14 @@ int main(int argc, char **argv) { } if (IsData) { auto ResOrErr = Symbolizer.symbolizeData(ModuleName, ModuleOffset); - Printer << (error(ResOrErr.getError()) ? DIGlobal() : ResOrErr.get()); + Printer << (error(ResOrErr) ? DIGlobal() : ResOrErr.get()); } else if (ClPrintInlining) { auto ResOrErr = Symbolizer.symbolizeInlinedCode(ModuleName, ModuleOffset); - Printer << (error(ResOrErr.getError()) ? DIInliningInfo() + Printer << (error(ResOrErr) ? DIInliningInfo() : ResOrErr.get()); } else { auto ResOrErr = Symbolizer.symbolizeCode(ModuleName, ModuleOffset); - Printer << (error(ResOrErr.getError()) ? DILineInfo() : ResOrErr.get()); + Printer << (error(ResOrErr) ? DILineInfo() : ResOrErr.get()); } outs() << "\n"; outs().flush(); diff --git a/llvm/tools/sancov/sancov.cc b/llvm/tools/sancov/sancov.cc index efeb46a1faac..e4e83b0bbc8f 100644 --- a/llvm/tools/sancov/sancov.cc +++ b/llvm/tools/sancov/sancov.cc @@ -135,6 +135,12 @@ template static void FailIfError(const ErrorOr &E) { FailIfError(E.getError()); } +template static void FailIfError(Expected &E) { + if (E) + return; + logAllUnhandledErrors(E.takeError(), errs(), "Error: "); +} + static void FailIfNotEmpty(const llvm::Twine &E) { if (E.str().empty()) return; diff --git a/llvm/tools/sanstats/sanstats.cpp b/llvm/tools/sanstats/sanstats.cpp index 3a8cc9aea8ce..b2216eab119e 100644 --- a/llvm/tools/sanstats/sanstats.cpp +++ b/llvm/tools/sanstats/sanstats.cpp @@ -76,12 +76,12 @@ const char *ReadModule(char SizeofPtr, const char *Begin, const char *End) { if (Begin == End) return nullptr; - ErrorOr LineInfo = Symbolizer.symbolizeCode(Filename, Addr); - if (LineInfo) { + if (Expected LineInfo = + Symbolizer.symbolizeCode(Filename, Addr)) { llvm::outs() << LineInfo->FileName << ':' << LineInfo->Line << ' ' << LineInfo->FunctionName << ' '; } else { - llvm::outs() << " "; + logAllUnhandledErrors(LineInfo.takeError(), llvm::outs(), " "); } switch (KindFromData(Data, SizeofPtr)) {