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

Daniel Thornburgh via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 28 13:35:43 PDT 2022


Author: Daniel Thornburgh
Date: 2022-09-28T13:35:35-07:00
New Revision: e61d89efd78b17f4969c9a394f480367307c7132

URL: https://github.com/llvm/llvm-project/commit/e61d89efd78b17f4969c9a394f480367307c7132
DIFF: https://github.com/llvm/llvm-project/commit/e61d89efd78b17f4969c9a394f480367307c7132.diff

LOG: [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

Added: 
    llvm/include/llvm/Debuginfod/BuildIDFetcher.h
    llvm/include/llvm/Object/BuildID.h
    llvm/lib/Debuginfod/BuildIDFetcher.cpp
    llvm/lib/Object/BuildID.cpp

Modified: 
    llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
    llvm/include/llvm/Debuginfod/Debuginfod.h
    llvm/include/llvm/Object/ObjectFile.h
    llvm/lib/DebugInfo/Symbolize/CMakeLists.txt
    llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
    llvm/lib/Debuginfod/CMakeLists.txt
    llvm/lib/Debuginfod/Debuginfod.cpp
    llvm/lib/Object/CMakeLists.txt
    llvm/lib/Object/ObjectFile.cpp
    llvm/tools/llvm-debuginfod-find/CMakeLists.txt
    llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp
    llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp

Removed: 
    llvm/include/llvm/DebugInfo/Symbolize/DIFetcher.h
    llvm/include/llvm/Debuginfod/DIFetcher.h
    llvm/lib/DebugInfo/Symbolize/DIFetcher.cpp
    llvm/lib/Debuginfod/DIFetcher.cpp


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/Symbolize/DIFetcher.h b/llvm/include/llvm/DebugInfo/Symbolize/DIFetcher.h
deleted file mode 100644
index c5340b5f04609..0000000000000
--- 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 <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

diff  --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
index f233a183912b2..c633c894a44e9 100644
--- 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 <algorithm>
 #include <cstdint>
@@ -115,8 +115,8 @@ class LLVMSymbolizer {
   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 @@ class LLVMSymbolizer {
 
   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 @@ class CachedBinary : public ilist_node<CachedBinary> {
   std::function<void()> Evictor;
 };
 
-Optional<ArrayRef<uint8_t>> 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
similarity index 55%
rename from llvm/include/llvm/Debuginfod/DIFetcher.h
rename to llvm/include/llvm/Debuginfod/BuildIDFetcher.h
index d398fd900051d..505db58383bae 100644
--- 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<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

diff  --git a/llvm/include/llvm/Debuginfod/Debuginfod.h b/llvm/include/llvm/Debuginfod/Debuginfod.h
index 496b24cfa37e5..df7fd9fb0cfd5 100644
--- 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<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 @@ class DebuginfodCollection {
                        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 {

diff  --git a/llvm/include/llvm/Object/BuildID.h b/llvm/include/llvm/Object/BuildID.h
new file mode 100644
index 0000000000000..22f2b9a09099e
--- /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<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

diff  --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h
index 8754c229bd4b9..7d81bc8c1056a 100644
--- a/llvm/include/llvm/Object/ObjectFile.h
+++ b/llvm/include/llvm/Object/ObjectFile.h
@@ -328,6 +328,8 @@ class ObjectFile : public SymbolicFile {
     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
index 47cb4243ef9a2..1d39cc6e55a15 100644
--- 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
index 119830de595ac..0000000000000
--- 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<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

diff  --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index c239d4c260ec9..497b24ab58e3b 100644
--- 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 @@ 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;
 }
 

diff  --git a/llvm/lib/Debuginfod/DIFetcher.cpp b/llvm/lib/Debuginfod/BuildIDFetcher.cpp
similarity index 74%
rename from llvm/lib/Debuginfod/DIFetcher.cpp
rename to llvm/lib/Debuginfod/BuildIDFetcher.cpp
index f0c134654534f..3b74877500b85 100644
--- 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<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;

diff  --git a/llvm/lib/Debuginfod/CMakeLists.txt b/llvm/lib/Debuginfod/CMakeLists.txt
index 0bd6ad15a29dd..b1329bd2d077e 100644
--- a/llvm/lib/Debuginfod/CMakeLists.txt
+++ b/llvm/lib/Debuginfod/CMakeLists.txt
@@ -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
 

diff  --git a/llvm/lib/Debuginfod/Debuginfod.cpp b/llvm/lib/Debuginfod/Debuginfod.cpp
index 29fdd6ffb48bc..ee5cc5141f74f 100644
--- 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 <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));

diff  --git a/llvm/lib/Object/BuildID.cpp b/llvm/lib/Object/BuildID.cpp
new file mode 100644
index 0000000000000..68b6f439db4a1
--- /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 <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

diff  --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
index 3dce08340a079..57421765647bf 100644
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -2,6 +2,7 @@ add_llvm_component_library(LLVMObject
   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
index bc8e602f5a744..56a1d09097d42 100644
--- a/llvm/lib/Object/ObjectFile.cpp
+++ b/llvm/lib/Object/ObjectFile.cpp
@@ -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));

diff  --git a/llvm/tools/llvm-debuginfod-find/CMakeLists.txt b/llvm/tools/llvm-debuginfod-find/CMakeLists.txt
index a0455604c04cc..b98c431c1839b 100644
--- 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
index 373353c226f60..86b4b22f6822e 100644
--- 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 @@ 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);
 }

diff  --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 138b069cf5674..a59364ade11ae 100644
--- 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 @@ 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)


        


More information about the llvm-commits mailing list