Files
clang-p2996/llvm/lib/Object/BuildID.cpp
Daniel Thornburgh e61d89efd7 [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
2022-09-28 13:35:35 -07:00

94 lines
2.8 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"
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