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) { + BIDFetcher = std::move(Fetcher); } private: @@ -211,7 +211,7 @@ Options Opts; - SmallVector> DIFetchers; + std::unique_ptr BIDFetcher; }; // 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,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 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; + /// the resulting file. + 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,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 BuildID; + +/// A reference to a BuildID in binary form. +typedef ArrayRef BuildIDRef; + +class ObjectFile; + +/// Returns the build ID, if any, contained in the given object file. +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; + + /// Returns the path to the debug file with the given build ID. + 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/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -328,6 +328,8 @@ 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; 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" @@ -45,7 +45,9 @@ LLVMSymbolizer::LLVMSymbolizer() = default; -LLVMSymbolizer::LLVMSymbolizer(const Options &Opts) : Opts(Opts) {} +LLVMSymbolizer::LLVMSymbolizer(const Options &Opts) + : Opts(Opts), + BIDFetcher(std::make_unique(Opts.DebugFileDirectory)) {} LLVMSymbolizer::~LLVMSymbolizer() = default; @@ -307,43 +309,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) { @@ -471,29 +438,16 @@ Result = I->second; return true; } - auto recordPath = [&](StringRef Path) { - Result = Path.str(); + if (!BIDFetcher) + return false; + if (Optional Path = BIDFetcher->fetch(BuildID)) { + Result = *Path; auto InsertResult = BuildIDPaths.insert({BuildIDStr, Result}); assert(InsertResult.second); (void)InsertResult; - }; - - Optional Path; - Path = LocalDIFetcher(Opts.DebugFileDirectory).fetchBuildID(BuildID); - if (Path) { - 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 - 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 -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" @@ -43,6 +42,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. @@ -301,16 +303,6 @@ llvm_unreachable("updateForever loop should never end"); } -static bool isDebugBinary(object::ObjectFile *Object) { - // TODO: handle PDB debuginfo - std::unique_ptr 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 @@ if (!Object) continue; - Optional ID = symbolize::getBuildID(Object); + Optional ID = getBuildID(Object); if (!ID) continue; std::string IDString = buildIDToString(ID.value()); - if (isDebugBinary(Object)) { + if (Object->hasDebugInfo()) { std::lock_guard DebugBinariesGuard(DebugBinariesMutex); DebugBinaries[IDString] = FilePath; } else { @@ -485,7 +477,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)); @@ -503,7 +495,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,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 +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/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -96,6 +96,11 @@ bool ObjectFile::isDebugSection(DataRefImpl Sec) const { return false; } +bool ObjectFile::hasDebugInfo() const { + return any_of(sections(), + [](SectionRef Sec) { return Sec.isDebugSection(); }); +} + Expected ObjectFile::getRelocatedSection(DataRefImpl Sec) const { return section_iterator(SectionRef(Sec, this)); 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,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 @@ 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 +92,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 != "") @@ -116,12 +116,12 @@ outs() << Path << "\n"; } -// 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)); +// Find a debug file in local build ID directories and via debuginfod. +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-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" @@ -109,30 +109,31 @@ 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, + std::string &ModuleName, object::BuildID &BuildID, uint64_t &ModuleOffset) { const char kDelimiters[] = " \n\r"; ModuleName = ""; @@ -249,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)) { @@ -266,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); @@ -351,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); @@ -447,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); @@ -468,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)