mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 15:46:45 +00:00

It is almost always simpler to use {} instead of std::nullopt to initialize an empty ArrayRef. This patch changes all occurrences I could find in LLVM itself. In future the ArrayRef(std::nullopt_t) constructor could be deprecated or removed.
99 lines
3.0 KiB
C++
99 lines
3.0 KiB
C++
//===- 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"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::object;
|
|
|
|
namespace {
|
|
|
|
template <typename ELFT> 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(P.p_align);
|
|
consumeError(std::move(Err));
|
|
}
|
|
return {};
|
|
}
|
|
|
|
} // namespace
|
|
|
|
BuildID llvm::object::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);
|
|
}
|
|
|
|
BuildIDRef llvm::object::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::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;
|
|
}
|