forked from OSchip/llvm-project
94 lines
2.8 KiB
C++
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 std::nullopt;
|
|
}
|
|
|
|
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
|