diff --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h --- a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -119,7 +119,12 @@ BIDFetcher = std::move(Fetcher); } - Error checkFileExists(StringRef Name); + /// 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); private: // Bundles together object file with code/data and object file with @@ -142,12 +147,6 @@ symbolizeFrameCommon(const T &ModuleSpecifier, object::SectionedAddress ModuleOffset); - /// 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); Expected getOrCreateModuleInfo(const ObjectFile &Obj); /// Returns a SymbolizableModule or an error if loading debug info failed. @@ -190,11 +189,6 @@ /// Update the LRU cache order when a binary is accessed. void recordAccess(CachedBinary &Bin); - /// Split binary file name into file and architecture parts. For example, - /// the name 'macho-universal:i386', will be split into 'macho-universal' and - /// 'i386'. - std::pair splitBinaryFileName(StringRef Name); - std::map, std::less<>> Modules; StringMap BuildIDPaths; diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -550,24 +550,19 @@ return InsertResult.first->second.get(); } -std::pair -LLVMSymbolizer::splitBinaryFileName(StringRef Name) { - StringRef BinaryName = Name; +Expected +LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { + std::string BinaryName = ModuleName; std::string ArchName = Opts.DefaultArch; - size_t ColonPos = Name.find_last_of(':'); - if (ColonPos != StringRef::npos) { - StringRef ArchStr = Name.substr(ColonPos + 1); + size_t ColonPos = ModuleName.find_last_of(':'); + // Verify that substring after colon form a valid arch name. + if (ColonPos != std::string::npos) { + std::string ArchStr = ModuleName.substr(ColonPos + 1); if (Triple(ArchStr).getArch() != Triple::UnknownArch) { - BinaryName = Name.substr(0, ColonPos); + BinaryName = ModuleName.substr(0, ColonPos); ArchName = ArchStr; } } - return std::make_pair(BinaryName.str(), ArchName); -} - -Expected -LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { - auto [BinaryName, ArchName] = splitBinaryFileName(ModuleName); auto I = Modules.find(ModuleName); if (I != Modules.end()) { @@ -712,15 +707,6 @@ return Name; } -Error LLVMSymbolizer::checkFileExists(StringRef BinName) { - auto [BinaryName, ArchName] = splitBinaryFileName(BinName); - sys::fs::file_status Stat; - std::error_code EC = sys::fs::status(BinaryName, Stat); - if (!EC && sys::fs::is_directory(Stat)) - EC = errc::is_a_directory; - return errorCodeToError(EC); -} - void LLVMSymbolizer::recordAccess(CachedBinary &Bin) { if (Bin->getBinary()) LRUBinaries.splice(LRUBinaries.end(), LRUBinaries, Bin.getIterator()); diff --git a/llvm/test/tools/llvm-symbolizer/errors.test b/llvm/test/tools/llvm-symbolizer/input-file-err.test rename from llvm/test/tools/llvm-symbolizer/errors.test rename to llvm/test/tools/llvm-symbolizer/input-file-err.test --- a/llvm/test/tools/llvm-symbolizer/errors.test +++ b/llvm/test/tools/llvm-symbolizer/input-file-err.test @@ -5,3 +5,6 @@ RUN: not llvm-addr2line -e %p/Inputs 0x12 2>&1 | FileCheck %s --check-prefix=CHECK-DIRECTORY-A2L -DMSG=%errc_EISDIR RUN: not llvm-addr2line -e %p/Inputs 2>&1 | FileCheck %s --check-prefix=CHECK-DIRECTORY-A2L -DMSG=%errc_EISDIR CHECK-DIRECTORY-A2L: llvm-addr2line{{.*}}: error: '{{.*}}Inputs': [[MSG]] + +not llvm-addr2line --output-style=JSON -e %p/Inputs/nonexistent 2>&1 | FileCheck %s --check-prefix=NONEXIST-JSON -DMSG=%errc_ENOENT +NONEXIST-JSON: {"Address":"0x0","Error":{"Message":"[[MSG]]"},"ModuleName":"{{.*}}nonexistent"} diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -478,12 +478,15 @@ else Printer = std::make_unique(outs(), printError, Config); - StringRef InputFile = Args.getLastArgValue(OPT_obj_EQ); - if (!InputFile.empty() && IsAddr2Line) { - Error Status = Symbolizer.checkFileExists(InputFile); - if (Status) { - handleAllErrors(std::move(Status), [&](const ErrorInfoBase &EI) { - printError(EI, InputFile); + // When an input file is specified, exit immediately if the file cannot be + // read. If getOrCreateModuleInfo succeeds, symbolizeInput will reuse the + // cached file handle. + if (auto *Arg = Args.getLastArg(OPT_obj_EQ); Arg && IsAddr2Line) { + auto Status = Symbolizer.getOrCreateModuleInfo(Arg->getValue()); + if (!Status) { + Request SymRequest = {Arg->getValue(), 0}; + handleAllErrors(Status.takeError(), [&](const ErrorInfoBase &EI) { + Printer->printError(SymRequest, EI); }); return EXIT_FAILURE; }