diff --git a/llvm/include/llvm/DebugInfo/Symbolize/DIFetcher.h b/llvm/include/llvm/DebugInfo/Symbolize/DIFetcher.h deleted file mode 100644 --- a/llvm/include/llvm/DebugInfo/Symbolize/DIFetcher.h +++ /dev/null @@ -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 -#include - -#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 - fetchBuildID(ArrayRef BuildID) const = 0; -}; - -/// LocalDIFetcher searches local cache directories for debug info. -class LocalDIFetcher : public DIFetcher { -public: - LocalDIFetcher(ArrayRef DebugFileDirectory) - : DebugFileDirectory(DebugFileDirectory){}; - virtual ~LocalDIFetcher() = default; - - Optional fetchBuildID(ArrayRef BuildID) const override; - -private: - const ArrayRef DebugFileDirectory; -}; - -} // end namespace symbolize -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_SYMBOLIZE_DIFETCHER_H 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 @@ -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 #include @@ -115,8 +115,8 @@ DemangleName(const std::string &Name, const SymbolizableModule *DbiModuleDescriptor); - void addDIFetcher(std::unique_ptr Fetcher) { - DIFetchers.push_back(std::move(Fetcher)); + void setBuildIDFetcher(std::unique_ptr Fetcher) { + BuildIDFetcher = std::move(Fetcher); } private: @@ -211,7 +211,7 @@ Options Opts; - SmallVector> DIFetchers; + std::unique_ptr BuildIDFetcher; }; // A binary intrusively linked into a LRU cache list. If the binary is empty, @@ -243,8 +243,6 @@ std::function Evictor; }; -Optional> getBuildID(const ELFObjectFileBase *Obj); - } // end namespace symbolize } // end namespace llvm diff --git a/llvm/include/llvm/Debuginfod/DIFetcher.h b/llvm/include/llvm/Debuginfod/BuildIDFetcher.h rename from llvm/include/llvm/Debuginfod/DIFetcher.h rename to llvm/include/llvm/Debuginfod/BuildIDFetcher.h --- a/llvm/include/llvm/Debuginfod/DIFetcher.h +++ b/llvm/include/llvm/Debuginfod/BuildIDFetcher.h @@ -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,8 +7,8 @@ //===----------------------------------------------------------------------===// /// /// \file -/// This file declares a DIFetcher implementation for obtaining debug info from -/// debuginfod. +/// This file declares a Build ID fetcher implementation for obtaining debug +/// binaries from debuginfod. /// //===----------------------------------------------------------------------===// @@ -16,17 +16,19 @@ #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 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 fetchBuildID(ArrayRef BuildID) const override; + Optional fetch(object::BuildIDRef BuildID) const override; }; } // namespace llvm diff --git a/llvm/include/llvm/Debuginfod/Debuginfod.h b/llvm/include/llvm/Debuginfod/Debuginfod.h --- a/llvm/include/llvm/Debuginfod/Debuginfod.h +++ b/llvm/include/llvm/Debuginfod/Debuginfod.h @@ -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 BuildIDRef; - -typedef SmallVector BuildID; - /// Finds default array of Debuginfod server URLs by checking DEBUGINFOD_URLS /// environment variable. Expected> getDefaultDebuginfodUrls(); @@ -54,16 +52,16 @@ /// Fetches a specified source file by searching the default local cache /// directory and server URLs. -Expected getCachedOrDownloadSource(BuildIDRef ID, +Expected getCachedOrDownloadSource(object::BuildIDRef ID, StringRef SourceFilePath); /// Fetches an executable by searching the default local cache directory and /// server URLs. -Expected getCachedOrDownloadExecutable(BuildIDRef ID); +Expected getCachedOrDownloadExecutable(object::BuildIDRef ID); /// Fetches a debug binary by searching the default local cache directory and /// server URLs. -Expected getCachedOrDownloadDebuginfo(BuildIDRef ID); +Expected getCachedOrDownloadDebuginfo(object::BuildIDRef ID); /// Fetches any debuginfod artifact using the default local cache directory and /// server URLs. @@ -108,8 +106,8 @@ sys::RWMutex DebugBinariesMutex; StringMap DebugBinaries; Error findBinaries(StringRef Path); - Expected> getDebugBinaryPath(BuildIDRef); - Expected> getBinaryPath(BuildIDRef); + Expected> getDebugBinaryPath(object::BuildIDRef); + Expected> 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 @@ ThreadPool &Pool, double MinInterval); Error update(); Error updateForever(std::chrono::milliseconds Interval); - Expected findDebugBinaryPath(BuildIDRef); - Expected findBinaryPath(BuildIDRef); + Expected findDebugBinaryPath(object::BuildIDRef); + Expected findBinaryPath(object::BuildIDRef); }; struct DebuginfodServer { diff --git a/llvm/include/llvm/Object/BuildID.h b/llvm/include/llvm/Object/BuildID.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Object/BuildID.h @@ -0,0 +1,35 @@ +#ifndef LLVM_DEBUGINFO_OBJECT_BUILDID_H +#define LLVM_DEBUGINFO_OBJECT_BUILDID_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { +namespace object { + +typedef ArrayRef BuildIDRef; +typedef SmallVector BuildID; + +class ObjectFile; + +Optional getBuildID(const ObjectFile *Obj); + +/// BuildIDFetcher searches local cache directories for debug info. +class BuildIDFetcher { +public: + BuildIDFetcher(std::vector DebugFileDirectories) + : DebugFileDirectories(std::move(DebugFileDirectories)){}; + virtual ~BuildIDFetcher() = default; + + virtual Optional fetch(BuildIDRef BuildID) const; + +private: + const std::vector DebugFileDirectories; +}; + +} // namespace object +} // namespace llvm + +#endif // LLVM_DEBUGINFO_OBJECT_BUILDID_H diff --git a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt --- a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt +++ b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt @@ -1,5 +1,4 @@ add_llvm_component_library(LLVMSymbolize - DIFetcher.cpp DIPrinter.cpp Markup.cpp MarkupFilter.cpp diff --git a/llvm/lib/DebugInfo/Symbolize/DIFetcher.cpp b/llvm/lib/DebugInfo/Symbolize/DIFetcher.cpp deleted file mode 100644 --- a/llvm/lib/DebugInfo/Symbolize/DIFetcher.cpp +++ /dev/null @@ -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 -LocalDIFetcher::fetchBuildID(ArrayRef 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 /.build-id/../... - SmallString<128> Path = GetDebugPath(Directory); - if (llvm::sys::fs::exists(Path)) - return std::string(Path); - } - } - return None; -} - -} // namespace symbolize -} // namespace llvm 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 @@ -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" @@ -307,43 +307,8 @@ return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size()); } -template -Optional> getBuildID(const ELFFile &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> getBuildID(const ELFObjectFileBase *Obj) { - Optional> BuildID; - if (auto *O = dyn_cast>(Obj)) - BuildID = getBuildID(O->getELFFile()); - else if (auto *O = dyn_cast>(Obj)) - BuildID = getBuildID(O->getELFFile()); - else if (auto *O = dyn_cast>(Obj)) - BuildID = getBuildID(O->getELFFile()); - else if (auto *O = dyn_cast>(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) { @@ -478,22 +443,11 @@ (void)InsertResult; }; - Optional Path; - Path = LocalDIFetcher(Opts.DebugFileDirectory).fetchBuildID(BuildID); - if (Path) { + if (Optional Path = BuildIDFetcher->fetch(BuildID)) { recordPath(*Path); return true; } - // Try caller-provided debug info fetchers. - for (const std::unique_ptr &Fetcher : DIFetchers) { - Path = Fetcher->fetchBuildID(BuildID); - if (Path) { - recordPath(*Path); - return true; - } - } - return false; } diff --git a/llvm/lib/Debuginfod/DIFetcher.cpp b/llvm/lib/Debuginfod/BuildIDFetcher.cpp rename from llvm/lib/Debuginfod/DIFetcher.cpp rename to llvm/lib/Debuginfod/BuildIDFetcher.cpp --- a/llvm/lib/Debuginfod/DIFetcher.cpp +++ b/llvm/lib/Debuginfod/BuildIDFetcher.cpp @@ -1,4 +1,4 @@ -//===- llvm/DebugInfod/DIFetcher.cpp - Debug info fetcher -----------------===// +//===- llvm/DebugInfod/BuildIDFetcher.cpp - Debug info 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 -DebuginfodDIFetcher::fetchBuildID(ArrayRef BuildID) const { +DebuginfodFetcher::fetch(ArrayRef BuildID) const { + if (Optional Path = BuildIDFetcher::fetch(BuildID)) + return std::move(*Path); + Expected PathOrErr = getCachedOrDownloadDebuginfo(BuildID); if (PathOrErr) return *PathOrErr; diff --git a/llvm/lib/Debuginfod/CMakeLists.txt b/llvm/lib/Debuginfod/CMakeLists.txt --- a/llvm/lib/Debuginfod/CMakeLists.txt +++ b/llvm/lib/Debuginfod/CMakeLists.txt @@ -16,8 +16,8 @@ # 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 diff --git a/llvm/lib/Debuginfod/Debuginfod.cpp b/llvm/lib/Debuginfod/Debuginfod.cpp --- a/llvm/lib/Debuginfod/Debuginfod.cpp +++ b/llvm/lib/Debuginfod/Debuginfod.cpp @@ -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" @@ -42,6 +41,9 @@ #include 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. @@ -369,7 +371,7 @@ if (!Object) continue; - Optional ID = symbolize::getBuildID(Object); + Optional ID = getBuildID(Object); if (!ID) continue; @@ -484,7 +486,7 @@ {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 PathOrErr = Collection.findDebugBinaryPath(ID); if (Error Err = PathOrErr.takeError()) { consumeError(std::move(Err)); @@ -502,7 +504,7 @@ {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 PathOrErr = Collection.findBinaryPath(ID); if (Error Err = PathOrErr.takeError()) { consumeError(std::move(Err)); diff --git a/llvm/lib/Object/BuildID.cpp b/llvm/lib/Object/BuildID.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Object/BuildID.cpp @@ -0,0 +1,80 @@ +#include "llvm/Object/BuildID.h" + +#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +namespace llvm { +namespace object { + +namespace { + +template +Optional getBuildID(const ELFFile &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 getBuildID(const ObjectFile *Obj) { + if (auto *O = dyn_cast>(Obj)) + return getBuildID(O->getELFFile()); + if (auto *O = dyn_cast>(Obj)) + return getBuildID(O->getELFFile()); + if (auto *O = dyn_cast>(Obj)) + return getBuildID(O->getELFFile()); + if (auto *O = dyn_cast>(Obj)) + return getBuildID(O->getELFFile()); + return None; +} + +Optional 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 /.build-id/../... + SmallString<128> Path = GetDebugPath(Directory); + if (llvm::sys::fs::exists(Path)) + return std::string(Path); + } + } + return None; +} + +} // namespace object +} // namespace llvm diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt --- a/llvm/lib/Object/CMakeLists.txt +++ b/llvm/lib/Object/CMakeLists.txt @@ -2,6 +2,7 @@ Archive.cpp ArchiveWriter.cpp Binary.cpp + BuildID.cpp COFFImportFile.cpp COFFModuleDefinition.cpp COFFObjectFile.cpp diff --git a/llvm/tools/llvm-debuginfod-find/CMakeLists.txt b/llvm/tools/llvm-debuginfod-find/CMakeLists.txt --- a/llvm/tools/llvm-debuginfod-find/CMakeLists.txt +++ b/llvm/tools/llvm-debuginfod-find/CMakeLists.txt @@ -1,6 +1,6 @@ set(LLVM_LINK_COMPONENTS + Object Support - Symbolize ) add_llvm_tool(llvm-debuginfod-find llvm-debuginfod-find.cpp diff --git a/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp b/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp --- a/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp +++ b/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp @@ -15,9 +15,10 @@ /// //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/Symbolize/DIFetcher.h" +#include "llvm/Debuginfod/BuildIDFetcher.h" #include "llvm/Debuginfod/Debuginfod.h" #include "llvm/Debuginfod/HTTPClient.h" +#include "llvm/Object/BuildID.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/InitLLVM.h" @@ -67,7 +68,7 @@ ExitOnError ExitOnErr; -static std::string fetchDebugInfo(ArrayRef BuildID); +static std::string fetchDebugInfo(object::BuildIDRef BuildID); int main(int argc, char **argv) { InitLLVM X(argc, argv); @@ -92,7 +93,7 @@ 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 != "") @@ -117,11 +118,11 @@ } // Find a debug binary in local build ID directories and via debuginfod. -std::string fetchDebugInfo(ArrayRef BuildID) { - if (!DebugFileDirectory.empty()) { - symbolize::LocalDIFetcher Fetcher(DebugFileDirectory); - if (Optional LocalPath = Fetcher.fetchBuildID(BuildID)) - return *LocalPath; - } - return ExitOnErr(getCachedOrDownloadDebuginfo(BuildID)); +std::string fetchDebugInfo(object::BuildIDRef BuildID) { + if (Optional Path = + DebuginfodFetcher(DebugFileDirectory).fetch(BuildID)) + return *Path; + errs() << "Build ID " << llvm::toHex(BuildID, /*Lowercase=*/true) + << " could not be found."; + exit(1); } diff --git a/llvm/tools/llvm-objdump/CMakeLists.txt b/llvm/tools/llvm-objdump/CMakeLists.txt --- a/llvm/tools/llvm-objdump/CMakeLists.txt +++ b/llvm/tools/llvm-objdump/CMakeLists.txt @@ -36,6 +36,8 @@ OtoolOptsTableGen ) +target_link_libraries(llvm-objdump PRIVATE LLVMDebuginfod) + if(LLVM_HAVE_LIBXAR) target_link_libraries(llvm-objdump PRIVATE ${XAR_LIB}) endif() diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td --- a/llvm/tools/llvm-objdump/ObjdumpOpts.td +++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td @@ -39,6 +39,10 @@ def demangle : Flag<["--"], "demangle">, HelpText<"Demangle symbol names">; def : Flag<["-"], "C">, Alias, HelpText<"Alias for --demangle">; +defm debug_file_directory : + Eq<"debug-file-directory", "Path to directory where to look for debug files">, + MetaVarName<"">; + def disassemble : Flag<["--"], "disassemble">, HelpText<"Disassemble all executable sections found in the input files">; def : Flag<["-"], "d">, Alias, HelpText<"Alias for --disassemble">; diff --git a/llvm/tools/llvm-objdump/SourcePrinter.h b/llvm/tools/llvm-objdump/SourcePrinter.h --- a/llvm/tools/llvm-objdump/SourcePrinter.h +++ b/llvm/tools/llvm-objdump/SourcePrinter.h @@ -152,7 +152,8 @@ public: SourcePrinter() = default; - SourcePrinter(const object::ObjectFile *Obj, StringRef DefaultArch); + SourcePrinter(const object::ObjectFile *Obj, StringRef DefaultArch, + std::vector DebugFileDirectories); virtual ~SourcePrinter() = default; virtual void printSourceLine(formatted_raw_ostream &OS, object::SectionedAddress Address, diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp b/llvm/tools/llvm-objdump/SourcePrinter.cpp --- a/llvm/tools/llvm-objdump/SourcePrinter.cpp +++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/StringSet.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" +#include "llvm/Debuginfod/BuildIDFetcher.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/FormatVariadic.h" @@ -471,7 +472,8 @@ } SourcePrinter::SourcePrinter(const object::ObjectFile *Obj, - StringRef DefaultArch) + StringRef DefaultArch, + std::vector DebugFileDirectories) : Obj(Obj) { symbolize::LLVMSymbolizer::Options SymbolizerOpts; SymbolizerOpts.PrintFunctions = @@ -479,6 +481,8 @@ SymbolizerOpts.Demangle = Demangle; SymbolizerOpts.DefaultArch = std::string(DefaultArch); Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); + Symbolizer->setBuildIDFetcher( + std::make_unique(std::move(DebugFileDirectories))); } } // namespace objdump diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -36,6 +36,9 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" #include "llvm/DebugInfo/Symbolize/Symbolize.h" +#include "llvm/Debuginfod/BuildIDFetcher.h" +#include "llvm/Debuginfod/Debuginfod.h" +#include "llvm/Debuginfod/HTTPClient.h" #include "llvm/Demangle/Demangle.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -51,6 +54,8 @@ #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/BuildID.h" #include "llvm/Object/COFF.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ELFObjectFile.h" @@ -67,6 +72,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" @@ -181,6 +187,7 @@ static bool AllHeaders; static std::string ArchName; bool objdump::ArchiveHeaders; +static std::vector DebugFileDirectories; bool objdump::Demangle; bool objdump::Disassemble; bool objdump::DisassembleAll; @@ -1375,8 +1382,20 @@ std::unique_ptr DICtx; LiveVariablePrinter LVP(*Ctx.getRegisterInfo(), *STI); + OwningBinary DebugBinary; if (DbgVariables != DVDisabled) { DICtx = DWARFContext::create(Obj); + if (DICtx->compile_units().empty()) { + Optional BuildID = getBuildID(&Obj); + if (BuildID) { + if (Optional Path = + DebuginfodFetcher{DebugFileDirectories}.fetch(*BuildID)) { + DebugBinary = unwrapOrError(createBinary(*Path), *Path); + if (auto *O = dyn_cast(DebugBinary.getBinary())) + DICtx = DWARFContext::create(*O); + } + } + } for (const std::unique_ptr &CU : DICtx->compile_units()) LVP.addCompileUnit(CU->getUnitDIE(false)); } @@ -1903,7 +1922,7 @@ IP->setMCInstrAnalysis(MIA.get()); PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName)); - SourcePrinter SP(Obj, TheTarget->getName()); + SourcePrinter SP(Obj, TheTarget->getName(), DebugFileDirectories); for (StringRef Opt : DisassemblerOptions) if (!IP->applyTargetSpecificCLOption(Opt)) @@ -2775,6 +2794,7 @@ AllHeaders = InputArgs.hasArg(OBJDUMP_all_headers); ArchName = InputArgs.getLastArgValue(OBJDUMP_arch_name_EQ).str(); ArchiveHeaders = InputArgs.hasArg(OBJDUMP_archive_headers); + DebugFileDirectories = InputArgs.getAllArgValues(OBJDUMP_debug_file_directory_eq); Demangle = InputArgs.hasArg(OBJDUMP_demangle); Disassemble = InputArgs.hasArg(OBJDUMP_disassemble); DisassembleAll = InputArgs.hasArg(OBJDUMP_disassemble_all); @@ -2926,6 +2946,7 @@ InitializeAllTargetInfos(); InitializeAllTargetMCs(); InitializeAllDisassemblers(); + HTTPClient::initialize(); if (InputArgs.hasArg(VersionFlag)) { cl::PrintVersionMessage(); 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 @@ -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" @@ -108,30 +108,32 @@ 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()); + Symbolizer.setBuildIDFetcher(std::make_unique( + Args.getAllArgValues(OPT_debug_file_directory_EQ))); // The HTTPClient must be initialized for use by the debuginfod client. HTTPClient::initialize(); } -static SmallVector parseBuildID(StringRef Str) { +static object::BuildID parseBuildID(StringRef Str) { std::string Bytes; if (!tryGetFromHex(Str, Bytes)) return {}; ArrayRef BuildID(reinterpret_cast(Bytes.data()), Bytes.size()); - return SmallVector(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 &BuildID, + object::BuildID &BuildID, uint64_t &ModuleOffset) { const char kDelimiters[] = " \n\r"; ModuleName = ""; @@ -248,13 +250,13 @@ } static void symbolizeInput(const opt::InputArgList &Args, - ArrayRef IncomingBuildID, + object::BuildIDRef IncomingBuildID, uint64_t AdjustVMA, bool IsAddr2Line, OutputStyle Style, StringRef InputString, LLVMSymbolizer &Symbolizer, DIPrinter &Printer) { Command Cmd; std::string ModuleName; - SmallVector 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)) { @@ -265,7 +267,7 @@ 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); @@ -350,14 +352,13 @@ return None; } -static SmallVector 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 BuildID = parseBuildID(V); + object::BuildID BuildID = parseBuildID(V); if (BuildID.empty()) { errs() << A->getSpelling() + ": expected a build ID, but got '" + V + "'\n"; exit(1); @@ -446,7 +447,7 @@ !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); @@ -467,7 +468,7 @@ errs() << "error: cannot specify both --build-id and --obj\n"; return EXIT_FAILURE; } - SmallVector BuildID = parseBuildIDArg(Args, OPT_build_id_EQ); + object::BuildID BuildID = parseBuildIDArg(Args, OPT_build_id_EQ); std::unique_ptr Printer; if (Style == OutputStyle::GNU)