brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.5 KiB · d1ee597 Raw
113 lines · cpp
1//===- llvm/Object/BuildID.cpp - Build ID ---------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file defines a library for handling Build IDs and using them to find11/// debug info.12///13//===----------------------------------------------------------------------===//14 15#include "llvm/Object/BuildID.h"16 17#include "llvm/Object/ELFObjectFile.h"18#include "llvm/Support/FileSystem.h"19#include "llvm/Support/Path.h"20 21using namespace llvm;22using namespace llvm::object;23 24namespace {25 26template <typename ELFT> BuildIDRef getBuildID(const ELFFile<ELFT> &Obj) {27  auto findBuildID = [&Obj](const auto &ShdrOrPhdr,28                            uint64_t Alignment) -> std::optional<BuildIDRef> {29    Error Err = Error::success();30    for (auto N : Obj.notes(ShdrOrPhdr, Err))31      if (N.getType() == ELF::NT_GNU_BUILD_ID &&32          N.getName() == ELF::ELF_NOTE_GNU)33        return N.getDesc(Alignment);34    consumeError(std::move(Err));35    return std::nullopt;36  };37 38  auto Sections = cantFail(Obj.sections());39  for (const auto &S : Sections) {40    if (S.sh_type != ELF::SHT_NOTE)41      continue;42    if (std::optional<BuildIDRef> ShdrRes = findBuildID(S, S.sh_addralign))43      return ShdrRes.value();44  }45  auto PhdrsOrErr = Obj.program_headers();46  if (!PhdrsOrErr) {47    consumeError(PhdrsOrErr.takeError());48    return {};49  }50  for (const auto &P : *PhdrsOrErr) {51    if (P.p_type != ELF::PT_NOTE)52      continue;53    if (std::optional<BuildIDRef> PhdrRes = findBuildID(P, P.p_align))54      return PhdrRes.value();55  }56  return {};57}58 59} // namespace60 61BuildID llvm::object::parseBuildID(StringRef Str) {62  std::string Bytes;63  if (!tryGetFromHex(Str, Bytes))64    return {};65  ArrayRef<uint8_t> BuildID(reinterpret_cast<const uint8_t *>(Bytes.data()),66                            Bytes.size());67  return SmallVector<uint8_t>(BuildID);68}69 70BuildIDRef llvm::object::getBuildID(const ObjectFile *Obj) {71  if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Obj))72    return ::getBuildID(O->getELFFile());73  if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Obj))74    return ::getBuildID(O->getELFFile());75  if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Obj))76    return ::getBuildID(O->getELFFile());77  if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Obj))78    return ::getBuildID(O->getELFFile());79  return {};80}81 82std::optional<std::string> BuildIDFetcher::fetch(BuildIDRef BuildID) const {83  auto GetDebugPath = [&](StringRef Directory) {84    SmallString<128> Path{Directory};85    sys::path::append(Path, ".build-id",86                      llvm::toHex(BuildID[0], /*LowerCase=*/true),87                      llvm::toHex(BuildID.slice(1), /*LowerCase=*/true));88    Path += ".debug";89    return Path;90  };91  if (DebugFileDirectories.empty()) {92    SmallString<128> Path = GetDebugPath(93#if defined(__NetBSD__)94        // Try /usr/libdata/debug/.build-id/../...95        "/usr/libdata/debug"96#else97        // Try /usr/lib/debug/.build-id/../...98        "/usr/lib/debug"99#endif100    );101    if (llvm::sys::fs::exists(Path))102      return std::string(Path);103  } else {104    for (const auto &Directory : DebugFileDirectories) {105      // Try <debug-file-directory>/.build-id/../...106      SmallString<128> Path = GetDebugPath(Directory);107      if (llvm::sys::fs::exists(Path))108        return std::string(Path);109    }110  }111  return std::nullopt;112}113