123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- //===- 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>
- std::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
- std::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 std::nullopt;
- }
- std::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 std::nullopt;
- }
- } // namespace object
- } // namespace llvm
|