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,6 +119,13 @@ BIDFetcher = std::move(Fetcher); } + /// 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 // corresponding debug info. These objects can be the same. @@ -140,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. diff --git a/llvm/test/tools/llvm-symbolizer/input-base.test b/llvm/test/tools/llvm-symbolizer/input-base.test --- a/llvm/test/tools/llvm-symbolizer/input-base.test +++ b/llvm/test/tools/llvm-symbolizer/input-base.test @@ -11,14 +11,14 @@ RUN: llvm-symbolizer -e /dev/null -a 0O1234 | FileCheck %s --check-prefix=INVALID-NOT-OCTAL-UPPER # llvm-addr2line always requires hexadecimal, but accepts an optional 0x prefix. -RUN: llvm-addr2line -e /dev/null -a 0x1234 | FileCheck %s -RUN: llvm-addr2line -e /dev/null -a 0X1234 | FileCheck %s -RUN: llvm-addr2line -e /dev/null -a 1234 | FileCheck %s -RUN: llvm-addr2line -e /dev/null -a 01234 | FileCheck %s -RUN: llvm-addr2line -e /dev/null -a 0b1010 | FileCheck %s --check-prefix=HEXADECIMAL-NOT-BINARY -RUN: llvm-addr2line -e /dev/null -a 0B1010 | FileCheck %s --check-prefix=HEXADECIMAL-NOT-BINARY -RUN: llvm-addr2line -e /dev/null -a 0o1234 | FileCheck %s --check-prefix=INVALID-NOT-OCTAL-LOWER -RUN: llvm-addr2line -e /dev/null -a 0O1234 | FileCheck %s --check-prefix=INVALID-NOT-OCTAL-UPPER +RUN: llvm-addr2line -e %p/Inputs/addr.exe -a 0x1234 | FileCheck %s +RUN: llvm-addr2line -e %p/Inputs/addr.exe -a 0X1234 | FileCheck %s +RUN: llvm-addr2line -e %p/Inputs/addr.exe -a 1234 | FileCheck %s +RUN: llvm-addr2line -e %p/Inputs/addr.exe -a 01234 | FileCheck %s +RUN: llvm-addr2line -e %p/Inputs/addr.exe -a 0b1010 | FileCheck %s --check-prefix=HEXADECIMAL-NOT-BINARY +RUN: llvm-addr2line -e %p/Inputs/addr.exe -a 0B1010 | FileCheck %s --check-prefix=HEXADECIMAL-NOT-BINARY +RUN: llvm-addr2line -e %p/Inputs/addr.exe -a 0o1234 | FileCheck %s --check-prefix=INVALID-NOT-OCTAL-LOWER +RUN: llvm-addr2line -e %p/Inputs/addr.exe -a 0O1234 | FileCheck %s --check-prefix=INVALID-NOT-OCTAL-UPPER CHECK: 0x1234 CHECK-NEXT: ?? diff --git a/llvm/test/tools/llvm-symbolizer/input-file-err.test b/llvm/test/tools/llvm-symbolizer/input-file-err.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-symbolizer/input-file-err.test @@ -0,0 +1,9 @@ +RUN: not llvm-addr2line -e %p/Inputs/nonexistent 0x12 2>&1 | FileCheck %s --check-prefix=NONEXIST-A2L -DMSG=%errc_ENOENT +RUN: not llvm-addr2line -e %p/Inputs/nonexistent 2>&1 | FileCheck %s --check-prefix=NONEXIST-A2L -DMSG=%errc_ENOENT +NONEXIST-A2L: error: '{{.*}}Inputs/nonexistent': [[MSG]] + +RUN: not llvm-addr2line -e %p/Inputs 2>&1 | FileCheck %s --check-prefix=DIRECTORY-A2L -DMSG=%errc_EISDIR +DIRECTORY-A2L: error: '{{.*}}Inputs': [[MSG]] + +RUN: 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,6 +478,20 @@ else Printer = std::make_unique(outs(), printError, Config); + // When an input file is specified, exit immediately if the file cannot be + // read. If getOrCreateModuleInfo suceeds, symbolizeInput will reuse the + // cached file handle. + if (auto *Arg = Args.getLastArg(OPT_obj_EQ); Arg && IsAddr2Line) { + auto ModuleOrErr = Symbolizer.getOrCreateModuleInfo(Arg->getValue()); + if (!ModuleOrErr) { + Request SymRequest = {Arg->getValue(), 0}; + handleAllErrors(ModuleOrErr.takeError(), [&](const ErrorInfoBase &EI) { + Printer->printError(SymRequest, EI); + }); + return 1; + } + } + std::vector InputAddresses = Args.getAllArgValues(OPT_INPUT); if (InputAddresses.empty()) { const int kMaxInputStringLength = 1024;