summaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/Symbolize
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/Symbolize')
-rw-r--r--llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp15
-rw-r--r--llvm/lib/DebugInfo/Symbolize/Symbolize.cpp94
2 files changed, 107 insertions, 2 deletions
diff --git a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
index b1a80cbc4580..2f3a2500c293 100644
--- a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
@@ -118,21 +118,32 @@ DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
}
DIPrinter &DIPrinter::operator<<(const DILocal &Local) {
- OS << Local.FunctionName << '\n';
- OS << Local.Name << '\n';
+ if (Local.FunctionName.empty())
+ OS << "??\n";
+ else
+ OS << Local.FunctionName << '\n';
+
+ if (Local.Name.empty())
+ OS << "??\n";
+ else
+ OS << Local.Name << '\n';
+
if (Local.DeclFile.empty())
OS << "??";
else
OS << Local.DeclFile;
OS << ':' << Local.DeclLine << '\n';
+
if (Local.FrameOffset)
OS << *Local.FrameOffset << ' ';
else
OS << "?? ";
+
if (Local.Size)
OS << *Local.Size << ' ';
else
OS << "?? ";
+
if (Local.TagOffset)
OS << *Local.TagOffset << '\n';
else
diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index be79d9e637c1..35e3ead6317b 100644
--- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -284,6 +284,79 @@ bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj,
return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
}
+template <typename ELFT>
+Optional<ArrayRef<uint8_t>> getBuildID(const ELFFile<ELFT> *Obj) {
+ if (!Obj)
+ return {};
+ auto PhdrsOrErr = Obj->program_headers();
+ if (!PhdrsOrErr) {
+ consumeError(PhdrsOrErr.takeError());
+ return {};
+ }
+ for (const auto &P : *PhdrsOrErr) {
+ if (P.p_type != ELF::PT_NOTE)
+ continue;
+ Error Err = Error::success();
+ for (auto N : Obj->notes(P, Err))
+ if (N.getType() == ELF::NT_GNU_BUILD_ID && N.getName() == ELF::ELF_NOTE_GNU)
+ return N.getDesc();
+ }
+ return {};
+}
+
+Optional<ArrayRef<uint8_t>> getBuildID(const ELFObjectFileBase *Obj) {
+ Optional<ArrayRef<uint8_t>> BuildID;
+ if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Obj))
+ BuildID = getBuildID(O->getELFFile());
+ else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Obj))
+ BuildID = getBuildID(O->getELFFile());
+ else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Obj))
+ BuildID = getBuildID(O->getELFFile());
+ else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Obj))
+ BuildID = getBuildID(O->getELFFile());
+ else
+ llvm_unreachable("unsupported file format");
+ return BuildID;
+}
+
+bool findDebugBinary(const std::vector<std::string> &DebugFileDirectory,
+ const ArrayRef<uint8_t> BuildID,
+ std::string &Result) {
+ auto getDebugPath = [&](StringRef Directory) {
+ SmallString<128> Path{Directory};
+ sys::path::append(Path, ".build-id",
+ llvm::toHex(BuildID[0], /*LowerCase=*/true),
+ llvm::toHex(BuildID.slice(1), /*LowerCase=*/true));
+ Path += ".debug";
+ return Path;
+ };
+ if (DebugFileDirectory.empty()) {
+ SmallString<128> Path = getDebugPath(
+#if defined(__NetBSD__)
+ // Try /usr/libdata/debug/.build-id/../...
+ "/usr/libdata/debug"
+#else
+ // Try /usr/lib/debug/.build-id/../...
+ "/usr/lib/debug"
+#endif
+ );
+ if (llvm::sys::fs::exists(Path)) {
+ Result = Path.str();
+ return true;
+ }
+ } else {
+ for (const auto &Directory : DebugFileDirectory) {
+ // Try <debug-file-directory>/.build-id/../...
+ SmallString<128> Path = getDebugPath(Directory);
+ if (llvm::sys::fs::exists(Path)) {
+ Result = Path.str();
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
} // end anonymous namespace
ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
@@ -335,6 +408,25 @@ ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path,
return DbgObjOrErr.get();
}
+ObjectFile *LLVMSymbolizer::lookUpBuildIDObject(const std::string &Path,
+ const ELFObjectFileBase *Obj,
+ const std::string &ArchName) {
+ auto BuildID = getBuildID(Obj);
+ if (!BuildID)
+ return nullptr;
+ if (BuildID->size() < 2)
+ return nullptr;
+ std::string DebugBinaryPath;
+ if (!findDebugBinary(Opts.DebugFileDirectory, *BuildID, DebugBinaryPath))
+ return nullptr;
+ auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
+ if (!DbgObjOrErr) {
+ consumeError(DbgObjOrErr.takeError());
+ return nullptr;
+ }
+ return DbgObjOrErr.get();
+}
+
Expected<LLVMSymbolizer::ObjectPair>
LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
const std::string &ArchName) {
@@ -355,6 +447,8 @@ LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
+ else if (auto ELFObj = dyn_cast<const ELFObjectFileBase>(Obj))
+ DbgObj = lookUpBuildIDObject(Path, ELFObj, ArchName);
if (!DbgObj)
DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
if (!DbgObj)