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,8 @@ BIDFetcher = std::move(Fetcher); } + Error findBinaryFile(StringRef Name); + private: // Bundles together object file with code/data and object file with // corresponding debug info. These objects can be the same. 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 @@ -707,6 +707,16 @@ return Name; } +/// Checks if the given file exists and can be opened as executable/relocatable +/// file. +/// \param BinName Name of the file to search for. +/// \returns Error::success() if the file was successfully opened, error object +/// otherwise. +Error LLVMSymbolizer::findBinaryFile(StringRef BinName) { + Expected BinFile = getOrCreateModuleInfo(BinName.str()); + return BinFile ? Error::success() : BinFile.takeError(); +} + 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/errors.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-symbolizer/errors.test @@ -0,0 +1,3 @@ +RUN: not llvm-addr2line -e %p/Inputs/inexistent 0x12 2>&1 | FileCheck %s --check-prefix=CHECK-INEXISTENT-A2L -DMSG=%errc_ENOENT +RUN: not llvm-addr2line -e %p/Inputs/inexistent 2>&1 | FileCheck %s --check-prefix=CHECK-INEXISTENT-A2L -DMSG=%errc_ENOENT +CHECK-INEXISTENT-A2L: llvm-addr2line{{.*}}: error: '{{.*}}Inputs/inexistent': [[MSG]] 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/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,17 @@ else Printer = std::make_unique(outs(), printError, Config); + StringRef InputFile = Args.getLastArgValue(OPT_obj_EQ); + if (!InputFile.empty() && IsAddr2Line) { + Error Status = Symbolizer.findBinaryFile(InputFile); + if (Status) { + handleAllErrors(std::move(Status), [&](const ErrorInfoBase &EI) { + printError(EI, InputFile); + }); + return EXIT_FAILURE; + } + } + std::vector InputAddresses = Args.getAllArgValues(OPT_INPUT); if (InputAddresses.empty()) { const int kMaxInputStringLength = 1024;