[NFC] [Object] Create library to fetch debug info by build ID.

This creates a library for fetching debug info by build ID, whether
locally or remotely via debuginfod. The functionality was refactored
out of existing code in the Symboliize library. Existing utilities
were refactored to use this library.

Reviewed By: phosek

Differential Revision: https://reviews.llvm.org/D132504
This commit is contained in:
Daniel Thornburgh
2022-08-23 13:39:33 -07:00
parent 97f919820b
commit e61d89efd7
18 changed files with 227 additions and 237 deletions

View File

@@ -1,51 +0,0 @@
//===-- llvm/DebugInfo/Symbolize/DIFetcher.h --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file declares a DIFetcher abstraction for obtaining debug info from an
/// arbitrary outside source.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_SYMBOLIZE_DIFETCHER_H
#define LLVM_DEBUGINFO_SYMBOLIZE_DIFETCHER_H
#include <cstdint>
#include <string>
#include "llvm/ADT/ArrayRef.h"
namespace llvm {
namespace symbolize {
/// The DIFetcher interface provides arbitrary mechanisms for obtaining debug
/// info from an outside source.
class DIFetcher {
public:
virtual ~DIFetcher() = default;
virtual Optional<std::string>
fetchBuildID(ArrayRef<uint8_t> BuildID) const = 0;
};
/// LocalDIFetcher searches local cache directories for debug info.
class LocalDIFetcher : public DIFetcher {
public:
LocalDIFetcher(ArrayRef<std::string> DebugFileDirectory)
: DebugFileDirectory(DebugFileDirectory){};
virtual ~LocalDIFetcher() = default;
Optional<std::string> fetchBuildID(ArrayRef<uint8_t> BuildID) const override;
private:
const ArrayRef<std::string> DebugFileDirectory;
};
} // end namespace symbolize
} // end namespace llvm
#endif // LLVM_DEBUGINFO_SYMBOLIZE_DIFETCHER_H

View File

@@ -17,8 +17,8 @@
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/simple_ilist.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/Symbolize/DIFetcher.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/BuildID.h"
#include "llvm/Support/Error.h"
#include <algorithm>
#include <cstdint>
@@ -115,8 +115,8 @@ public:
DemangleName(const std::string &Name,
const SymbolizableModule *DbiModuleDescriptor);
void addDIFetcher(std::unique_ptr<DIFetcher> Fetcher) {
DIFetchers.push_back(std::move(Fetcher));
void setBuildIDFetcher(std::unique_ptr<BuildIDFetcher> Fetcher) {
BIDFetcher = std::move(Fetcher);
}
private:
@@ -211,7 +211,7 @@ private:
Options Opts;
SmallVector<std::unique_ptr<DIFetcher>> DIFetchers;
std::unique_ptr<BuildIDFetcher> BIDFetcher;
};
// A binary intrusively linked into a LRU cache list. If the binary is empty,
@@ -243,8 +243,6 @@ private:
std::function<void()> Evictor;
};
Optional<ArrayRef<uint8_t>> getBuildID(const ELFObjectFileBase *Obj);
} // end namespace symbolize
} // end namespace llvm

View File

@@ -1,4 +1,4 @@
//===- llvm/DebugInfod/DIFetcher.h - Debug info fetcher----------*- C++ -*-===//
//===- llvm/DebugInfod/BuildIDFetcher.h - Build ID fetcher ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,26 +7,27 @@
//===----------------------------------------------------------------------===//
///
/// \file
/// This file declares a DIFetcher implementation for obtaining debug info from
/// debuginfod.
/// This file declares a Build ID fetcher implementation for obtaining debug
/// info from debuginfod.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFOD_DIFETCHER_H
#define LLVM_DEBUGINFOD_DIFETCHER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/Symbolize/DIFetcher.h"
#include "llvm/Object/BuildID.h"
namespace llvm {
class DebuginfodDIFetcher : public symbolize::DIFetcher {
class DebuginfodFetcher : public object::BuildIDFetcher {
public:
virtual ~DebuginfodDIFetcher() = default;
DebuginfodFetcher(std::vector<std::string> DebugFileDirectories)
: BuildIDFetcher(std::move(DebugFileDirectories)) {}
virtual ~DebuginfodFetcher() = default;
/// Fetches the given Build ID using debuginfod and returns a local path to
/// the resulting debug binary.
Optional<std::string> fetchBuildID(ArrayRef<uint8_t> BuildID) const override;
/// the resulting file.
Optional<std::string> fetch(object::BuildIDRef BuildID) const override;
};
} // namespace llvm

View File

@@ -20,10 +20,12 @@
#ifndef LLVM_DEBUGINFOD_DEBUGINFOD_H
#define LLVM_DEBUGINFOD_DEBUGINFOD_H
#include "HTTPServer.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Debuginfod/HTTPServer.h"
#include "llvm/Object/BuildID.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
@@ -36,10 +38,6 @@
namespace llvm {
typedef ArrayRef<uint8_t> BuildIDRef;
typedef SmallVector<uint8_t, 10> BuildID;
/// Finds default array of Debuginfod server URLs by checking DEBUGINFOD_URLS
/// environment variable.
Expected<SmallVector<StringRef>> getDefaultDebuginfodUrls();
@@ -54,16 +52,16 @@ std::chrono::milliseconds getDefaultDebuginfodTimeout();
/// Fetches a specified source file by searching the default local cache
/// directory and server URLs.
Expected<std::string> getCachedOrDownloadSource(BuildIDRef ID,
Expected<std::string> getCachedOrDownloadSource(object::BuildIDRef ID,
StringRef SourceFilePath);
/// Fetches an executable by searching the default local cache directory and
/// server URLs.
Expected<std::string> getCachedOrDownloadExecutable(BuildIDRef ID);
Expected<std::string> getCachedOrDownloadExecutable(object::BuildIDRef ID);
/// Fetches a debug binary by searching the default local cache directory and
/// server URLs.
Expected<std::string> getCachedOrDownloadDebuginfo(BuildIDRef ID);
Expected<std::string> getCachedOrDownloadDebuginfo(object::BuildIDRef ID);
/// Fetches any debuginfod artifact using the default local cache directory and
/// server URLs.
@@ -108,8 +106,8 @@ class DebuginfodCollection {
sys::RWMutex DebugBinariesMutex;
StringMap<std::string> DebugBinaries;
Error findBinaries(StringRef Path);
Expected<Optional<std::string>> getDebugBinaryPath(BuildIDRef);
Expected<Optional<std::string>> getBinaryPath(BuildIDRef);
Expected<Optional<std::string>> getDebugBinaryPath(object::BuildIDRef);
Expected<Optional<std::string>> getBinaryPath(object::BuildIDRef);
// If the collection has not been updated since MinInterval, call update() and
// return true. Otherwise return false. If update returns an error, return the
// error.
@@ -128,8 +126,8 @@ public:
ThreadPool &Pool, double MinInterval);
Error update();
Error updateForever(std::chrono::milliseconds Interval);
Expected<std::string> findDebugBinaryPath(BuildIDRef);
Expected<std::string> findBinaryPath(BuildIDRef);
Expected<std::string> findDebugBinaryPath(object::BuildIDRef);
Expected<std::string> findBinaryPath(object::BuildIDRef);
};
struct DebuginfodServer {

View File

@@ -0,0 +1,52 @@
//===- llvm/Object/BuildID.h - Build ID -------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file declares a library for handling Build IDs and using them to find
/// debug info.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_OBJECT_BUILDID_H
#define LLVM_DEBUGINFO_OBJECT_BUILDID_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
namespace llvm {
namespace object {
/// A build ID in binary form.
typedef SmallVector<uint8_t, 10> BuildID;
/// A reference to a BuildID in binary form.
typedef ArrayRef<uint8_t> BuildIDRef;
class ObjectFile;
/// Returns the build ID, if any, contained in the given object file.
Optional<BuildIDRef> getBuildID(const ObjectFile *Obj);
/// BuildIDFetcher searches local cache directories for debug info.
class BuildIDFetcher {
public:
BuildIDFetcher(std::vector<std::string> DebugFileDirectories)
: DebugFileDirectories(std::move(DebugFileDirectories)) {}
virtual ~BuildIDFetcher() = default;
/// Returns the path to the debug file with the given build ID.
virtual Optional<std::string> fetch(BuildIDRef BuildID) const;
private:
const std::vector<std::string> DebugFileDirectories;
};
} // namespace object
} // namespace llvm
#endif // LLVM_DEBUGINFO_OBJECT_BUILDID_H

View File

@@ -328,6 +328,8 @@ public:
return section_iterator_range(section_begin(), section_end());
}
virtual bool hasDebugInfo() const;
/// The number of bytes used to represent an address in this object
/// file format.
virtual uint8_t getBytesInAddress() const = 0;

View File

@@ -1,5 +1,4 @@
add_llvm_component_library(LLVMSymbolize
DIFetcher.cpp
DIPrinter.cpp
Markup.cpp
MarkupFilter.cpp

View File

@@ -1,57 +0,0 @@
//===-- lib/DebugInfo/Symbolize/DIFetcher.cpp -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines the implementation of the local debug info fetcher, which
/// searches cache directories.
///
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/Symbolize/DIFetcher.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
namespace llvm {
namespace symbolize {
Optional<std::string>
LocalDIFetcher::fetchBuildID(ArrayRef<uint8_t> BuildID) const {
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))
return std::string(Path);
} else {
for (const auto &Directory : DebugFileDirectory) {
// Try <debug-file-directory>/.build-id/../...
SmallString<128> Path = GetDebugPath(Directory);
if (llvm::sys::fs::exists(Path))
return std::string(Path);
}
}
return None;
}
} // namespace symbolize
} // namespace llvm

View File

@@ -16,9 +16,9 @@
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/DebugInfo/PDB/PDBContext.h"
#include "llvm/DebugInfo/Symbolize/DIFetcher.h"
#include "llvm/DebugInfo/Symbolize/SymbolizableObjectFile.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Object/BuildID.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
@@ -45,7 +45,9 @@ namespace symbolize {
LLVMSymbolizer::LLVMSymbolizer() = default;
LLVMSymbolizer::LLVMSymbolizer(const Options &Opts) : Opts(Opts) {}
LLVMSymbolizer::LLVMSymbolizer(const Options &Opts)
: Opts(Opts),
BIDFetcher(std::make_unique<BuildIDFetcher>(Opts.DebugFileDirectory)) {}
LLVMSymbolizer::~LLVMSymbolizer() = default;
@@ -307,43 +309,8 @@ 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) {
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();
consumeError(std::move(Err));
}
return {};
}
} // end anonymous namespace
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;
}
ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
const MachOObjectFile *MachExeObj,
const std::string &ArchName) {
@@ -471,29 +438,16 @@ bool LLVMSymbolizer::getOrFindDebugBinary(const ArrayRef<uint8_t> BuildID,
Result = I->second;
return true;
}
auto recordPath = [&](StringRef Path) {
Result = Path.str();
if (!BIDFetcher)
return false;
if (Optional<std::string> Path = BIDFetcher->fetch(BuildID)) {
Result = *Path;
auto InsertResult = BuildIDPaths.insert({BuildIDStr, Result});
assert(InsertResult.second);
(void)InsertResult;
};
Optional<std::string> Path;
Path = LocalDIFetcher(Opts.DebugFileDirectory).fetchBuildID(BuildID);
if (Path) {
recordPath(*Path);
return true;
}
// Try caller-provided debug info fetchers.
for (const std::unique_ptr<DIFetcher> &Fetcher : DIFetchers) {
Path = Fetcher->fetchBuildID(BuildID);
if (Path) {
recordPath(*Path);
return true;
}
}
return false;
}

View File

@@ -1,4 +1,4 @@
//===- llvm/DebugInfod/DIFetcher.cpp - Debug info fetcher -----------------===//
//===- llvm/DebugInfod/BuildIDFetcher.cpp - Build ID fetcher --------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -12,14 +12,17 @@
///
//===----------------------------------------------------------------------===//
#include "llvm/Debuginfod/DIFetcher.h"
#include "llvm/Debuginfod/BuildIDFetcher.h"
#include "llvm/Debuginfod/Debuginfod.h"
using namespace llvm;
Optional<std::string>
DebuginfodDIFetcher::fetchBuildID(ArrayRef<uint8_t> BuildID) const {
DebuginfodFetcher::fetch(ArrayRef<uint8_t> BuildID) const {
if (Optional<std::string> Path = BuildIDFetcher::fetch(BuildID))
return std::move(*Path);
Expected<std::string> PathOrErr = getCachedOrDownloadDebuginfo(BuildID);
if (PathOrErr)
return *PathOrErr;

View File

@@ -16,8 +16,8 @@ endif()
# Note: This isn't a component, since that could potentially add a libcurl
# dependency to libLLVM.
add_llvm_library(LLVMDebuginfod
BuildIDFetcher.cpp
Debuginfod.cpp
DIFetcher.cpp
HTTPClient.cpp
HTTPServer.cpp

View File

@@ -27,9 +27,8 @@
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include "llvm/Debuginfod/HTTPClient.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/BuildID.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CachePruning.h"
#include "llvm/Support/Caching.h"
#include "llvm/Support/Errc.h"
@@ -43,6 +42,9 @@
#include <thread>
namespace llvm {
using llvm::object::BuildIDRef;
static std::string uniqueKey(llvm::StringRef S) { return utostr(xxHash64(S)); }
// Returns a binary BuildID as a normalized hex string.
@@ -301,16 +303,6 @@ Error DebuginfodCollection::updateForever(std::chrono::milliseconds Interval) {
llvm_unreachable("updateForever loop should never end");
}
static bool isDebugBinary(object::ObjectFile *Object) {
// TODO: handle PDB debuginfo
std::unique_ptr<DWARFContext> Context = DWARFContext::create(
*Object, DWARFContext::ProcessDebugRelocations::Process);
const DWARFObject &DObj = Context->getDWARFObj();
unsigned NumSections = 0;
DObj.forEachInfoSections([&](const DWARFSection &S) { NumSections++; });
return NumSections;
}
static bool hasELFMagic(StringRef FilePath) {
file_magic Type;
std::error_code EC = identify_magic(FilePath, Type);
@@ -370,12 +362,12 @@ Error DebuginfodCollection::findBinaries(StringRef Path) {
if (!Object)
continue;
Optional<BuildIDRef> ID = symbolize::getBuildID(Object);
Optional<BuildIDRef> ID = getBuildID(Object);
if (!ID)
continue;
std::string IDString = buildIDToString(ID.value());
if (isDebugBinary(Object)) {
if (Object->hasDebugInfo()) {
std::lock_guard<sys::RWMutex> DebugBinariesGuard(DebugBinariesMutex);
DebugBinaries[IDString] = FilePath;
} else {
@@ -485,7 +477,7 @@ DebuginfodServer::DebuginfodServer(DebuginfodLog &Log,
{404, "text/plain", "Build ID is not a hex string\n"});
return;
}
BuildID ID(IDString.begin(), IDString.end());
object::BuildID ID(IDString.begin(), IDString.end());
Expected<std::string> PathOrErr = Collection.findDebugBinaryPath(ID);
if (Error Err = PathOrErr.takeError()) {
consumeError(std::move(Err));
@@ -503,7 +495,7 @@ DebuginfodServer::DebuginfodServer(DebuginfodLog &Log,
{404, "text/plain", "Build ID is not a hex string\n"});
return;
}
BuildID ID(IDString.begin(), IDString.end());
object::BuildID ID(IDString.begin(), IDString.end());
Expected<std::string> PathOrErr = Collection.findBinaryPath(ID);
if (Error Err = PathOrErr.takeError()) {
consumeError(std::move(Err));

View File

@@ -0,0 +1,93 @@
//===- llvm/Object/BuildID.cpp - Build ID ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines a library for handling Build IDs and using them to find
/// debug info.
///
//===----------------------------------------------------------------------===//
#include "llvm/Object/BuildID.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
namespace llvm {
namespace object {
namespace {
template <typename ELFT>
Optional<BuildIDRef> getBuildID(const ELFFile<ELFT> &Obj) {
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();
consumeError(std::move(Err));
}
return {};
}
} // namespace
Optional<BuildIDRef> getBuildID(const ObjectFile *Obj) {
if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Obj))
return getBuildID(O->getELFFile());
if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Obj))
return getBuildID(O->getELFFile());
if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Obj))
return getBuildID(O->getELFFile());
if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Obj))
return getBuildID(O->getELFFile());
return None;
}
Optional<std::string> BuildIDFetcher::fetch(BuildIDRef BuildID) const {
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 (DebugFileDirectories.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))
return std::string(Path);
} else {
for (const auto &Directory : DebugFileDirectories) {
// Try <debug-file-directory>/.build-id/../...
SmallString<128> Path = GetDebugPath(Directory);
if (llvm::sys::fs::exists(Path))
return std::string(Path);
}
}
return None;
}
} // namespace object
} // namespace llvm

View File

@@ -2,6 +2,7 @@ add_llvm_component_library(LLVMObject
Archive.cpp
ArchiveWriter.cpp
Binary.cpp
BuildID.cpp
COFFImportFile.cpp
COFFModuleDefinition.cpp
COFFObjectFile.cpp

View File

@@ -96,6 +96,11 @@ bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const {
bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; }
bool ObjectFile::hasDebugInfo() const {
return any_of(sections(),
[](SectionRef Sec) { return Sec.isDebugSection(); });
}
Expected<section_iterator>
ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
return section_iterator(SectionRef(Sec, this));

View File

@@ -1,6 +1,6 @@
set(LLVM_LINK_COMPONENTS
Object
Support
Symbolize
)
add_llvm_tool(llvm-debuginfod-find
llvm-debuginfod-find.cpp

View File

@@ -15,7 +15,7 @@
///
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/Symbolize/DIFetcher.h"
#include "llvm/Debuginfod/BuildIDFetcher.h"
#include "llvm/Debuginfod/Debuginfod.h"
#include "llvm/Debuginfod/HTTPClient.h"
#include "llvm/Support/CommandLine.h"
@@ -67,7 +67,7 @@ static cl::list<std::string> DebugFileDirectory(
ExitOnError ExitOnErr;
static std::string fetchDebugInfo(ArrayRef<uint8_t> BuildID);
static std::string fetchDebugInfo(object::BuildIDRef BuildID);
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
@@ -92,7 +92,7 @@ int main(int argc, char **argv) {
errs() << "Build ID " << InputBuildID << " is not a hex string.\n";
exit(1);
}
BuildID ID(IDString.begin(), IDString.end());
object::BuildID ID(IDString.begin(), IDString.end());
std::string Path;
if (FetchSource != "")
@@ -116,12 +116,12 @@ int main(int argc, char **argv) {
outs() << Path << "\n";
}
// Find a debug binary in local build ID directories and via debuginfod.
std::string fetchDebugInfo(ArrayRef<uint8_t> BuildID) {
if (!DebugFileDirectory.empty()) {
symbolize::LocalDIFetcher Fetcher(DebugFileDirectory);
if (Optional<std::string> LocalPath = Fetcher.fetchBuildID(BuildID))
return *LocalPath;
}
return ExitOnErr(getCachedOrDownloadDebuginfo(BuildID));
// Find a debug file in local build ID directories and via debuginfod.
std::string fetchDebugInfo(object::BuildIDRef BuildID) {
if (Optional<std::string> Path =
DebuginfodFetcher(DebugFileDirectory).fetch(BuildID))
return *Path;
errs() << "Build ID " << llvm::toHex(BuildID, /*Lowercase=*/true)
<< " could not be found.";
exit(1);
}

View File

@@ -23,7 +23,7 @@
#include "llvm/DebugInfo/Symbolize/MarkupFilter.h"
#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include "llvm/Debuginfod/DIFetcher.h"
#include "llvm/Debuginfod/BuildIDFetcher.h"
#include "llvm/Debuginfod/Debuginfod.h"
#include "llvm/Debuginfod/HTTPClient.h"
#include "llvm/Option/Arg.h"
@@ -109,30 +109,31 @@ enum class Command {
Frame,
};
static void enableDebuginfod(LLVMSymbolizer &Symbolizer) {
static void enableDebuginfod(LLVMSymbolizer &Symbolizer,
const opt::ArgList &Args) {
static bool IsEnabled = false;
if (IsEnabled)
return;
IsEnabled = true;
// Look up symbols using the debuginfod client.
Symbolizer.addDIFetcher(std::make_unique<DebuginfodDIFetcher>());
Symbolizer.setBuildIDFetcher(std::make_unique<DebuginfodFetcher>(
Args.getAllArgValues(OPT_debug_file_directory_EQ)));
// The HTTPClient must be initialized for use by the debuginfod client.
HTTPClient::initialize();
}
static SmallVector<uint8_t> parseBuildID(StringRef Str) {
static object::BuildID parseBuildID(StringRef Str) {
std::string Bytes;
if (!tryGetFromHex(Str, Bytes))
return {};
ArrayRef<uint8_t> BuildID(reinterpret_cast<const uint8_t *>(Bytes.data()),
Bytes.size());
return SmallVector<uint8_t>(BuildID.begin(), BuildID.end());
return object::BuildID(BuildID.begin(), BuildID.end());
}
static bool parseCommand(StringRef BinaryName, bool IsAddr2Line,
StringRef InputString, Command &Cmd,
std::string &ModuleName,
SmallVectorImpl<uint8_t> &BuildID,
std::string &ModuleName, object::BuildID &BuildID,
uint64_t &ModuleOffset) {
const char kDelimiters[] = " \n\r";
ModuleName = "";
@@ -249,13 +250,13 @@ void executeCommand(StringRef ModuleName, const T &ModuleSpec, Command Cmd,
}
static void symbolizeInput(const opt::InputArgList &Args,
ArrayRef<uint8_t> IncomingBuildID,
object::BuildIDRef IncomingBuildID,
uint64_t AdjustVMA, bool IsAddr2Line,
OutputStyle Style, StringRef InputString,
LLVMSymbolizer &Symbolizer, DIPrinter &Printer) {
Command Cmd;
std::string ModuleName;
SmallVector<uint8_t> BuildID(IncomingBuildID.begin(), IncomingBuildID.end());
object::BuildID BuildID(IncomingBuildID.begin(), IncomingBuildID.end());
uint64_t Offset = 0;
if (!parseCommand(Args.getLastArgValue(OPT_obj_EQ), IsAddr2Line,
StringRef(InputString), Cmd, ModuleName, BuildID, Offset)) {
@@ -266,7 +267,7 @@ static void symbolizeInput(const opt::InputArgList &Args,
if (!BuildID.empty()) {
assert(ModuleName.empty());
if (!Args.hasArg(OPT_no_debuginfod))
enableDebuginfod(Symbolizer);
enableDebuginfod(Symbolizer, Args);
std::string BuildIDStr = toHex(BuildID);
executeCommand(BuildIDStr, BuildID, Cmd, Offset, AdjustVMA, ShouldInline,
Style, Symbolizer, Printer);
@@ -351,14 +352,13 @@ static Optional<bool> parseColorArg(const opt::InputArgList &Args) {
return None;
}
static SmallVector<uint8_t> parseBuildIDArg(const opt::InputArgList &Args,
int ID) {
static object::BuildID parseBuildIDArg(const opt::InputArgList &Args, int ID) {
const opt::Arg *A = Args.getLastArg(ID);
if (!A)
return {};
StringRef V(A->getValue());
SmallVector<uint8_t> BuildID = parseBuildID(V);
object::BuildID BuildID = parseBuildID(V);
if (BuildID.empty()) {
errs() << A->getSpelling() + ": expected a build ID, but got '" + V + "'\n";
exit(1);
@@ -447,7 +447,7 @@ int main(int argc, char **argv) {
!ExitOnErr(getDefaultDebuginfodUrls()).empty();
if (Args.hasFlag(OPT_debuginfod, OPT_no_debuginfod,
ShouldUseDebuginfodByDefault))
enableDebuginfod(Symbolizer);
enableDebuginfod(Symbolizer, Args);
if (Args.hasArg(OPT_filter_markup)) {
filterMarkup(Args, Symbolizer);
@@ -468,7 +468,7 @@ int main(int argc, char **argv) {
errs() << "error: cannot specify both --build-id and --obj\n";
return EXIT_FAILURE;
}
SmallVector<uint8_t> BuildID = parseBuildIDArg(Args, OPT_build_id_EQ);
object::BuildID BuildID = parseBuildIDArg(Args, OPT_build_id_EQ);
std::unique_ptr<DIPrinter> Printer;
if (Style == OutputStyle::GNU)