BIDFetcher = std::move(Fetcher);
}
+ Error checkFileExists(StringRef Name);
+
private:
// Bundles together object file with code/data and object file with
// corresponding debug info. These objects can be the same.
/// 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<std::string, std::string> splitBinaryFileName(StringRef Name);
+
std::map<std::string, std::unique_ptr<SymbolizableModule>, std::less<>>
Modules;
StringMap<std::string> BuildIDPaths;
return InsertResult.first->second.get();
}
-Expected<SymbolizableModule *>
-LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
- std::string BinaryName = ModuleName;
+std::pair<std::string, std::string>
+LLVMSymbolizer::splitBinaryFileName(StringRef Name) {
+ StringRef BinaryName = Name;
std::string ArchName = Opts.DefaultArch;
- 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);
+ size_t ColonPos = Name.find_last_of(':');
+ if (ColonPos != StringRef::npos) {
+ StringRef ArchStr = Name.substr(ColonPos + 1);
if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
- BinaryName = ModuleName.substr(0, ColonPos);
+ BinaryName = Name.substr(0, ColonPos);
ArchName = ArchStr;
}
}
+ return std::make_pair(BinaryName.str(), ArchName);
+}
+
+Expected<SymbolizableModule *>
+LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
+ auto [BinaryName, ArchName] = splitBinaryFileName(ModuleName);
auto I = Modules.find(ModuleName);
if (I != Modules.end()) {
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());
--- /dev/null
+RUN: not llvm-addr2line -e %p/Inputs/nonexistent 0x12 2>&1 | FileCheck %s --check-prefix=CHECK-NONEXISTENT-A2L -DMSG=%errc_ENOENT
+RUN: not llvm-addr2line -e %p/Inputs/nonexistent 2>&1 | FileCheck %s --check-prefix=CHECK-NONEXISTENT-A2L -DMSG=%errc_ENOENT
+CHECK-NONEXISTENT-A2L: llvm-addr2line{{.*}}: error: '{{.*}}Inputs/nonexistent': [[MSG]]
+
+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]]
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: ??
else
Printer = std::make_unique<LLVMPrinter>(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);
+ });
+ return EXIT_FAILURE;
+ }
+ }
+
std::vector<std::string> InputAddresses = Args.getAllArgValues(OPT_INPUT);
if (InputAddresses.empty()) {
const int kMaxInputStringLength = 1024;