blob: ef21458060abd6c239bb7e9f00299d5b55e1b77e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
//===- 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.begin(), BuildID.end());
}
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::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;
}
|