1 //===- llvm/Object/BuildID.cpp - Build ID ---------------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
10 /// This file defines a library for handling Build IDs and using them to find
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/BuildID.h"
17 #include "llvm/Object/ELFObjectFile.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/Path.h"
22 using namespace llvm::object
;
26 template <typename ELFT
> BuildIDRef
getBuildID(const ELFFile
<ELFT
> &Obj
) {
27 auto PhdrsOrErr
= Obj
.program_headers();
29 consumeError(PhdrsOrErr
.takeError());
32 for (const auto &P
: *PhdrsOrErr
) {
33 if (P
.p_type
!= ELF::PT_NOTE
)
35 Error Err
= Error::success();
36 for (auto N
: Obj
.notes(P
, Err
))
37 if (N
.getType() == ELF::NT_GNU_BUILD_ID
&&
38 N
.getName() == ELF::ELF_NOTE_GNU
)
39 return N
.getDesc(P
.p_align
);
40 consumeError(std::move(Err
));
47 BuildID
llvm::object::parseBuildID(StringRef Str
) {
49 if (!tryGetFromHex(Str
, Bytes
))
51 ArrayRef
<uint8_t> BuildID(reinterpret_cast<const uint8_t *>(Bytes
.data()),
53 return SmallVector
<uint8_t>(BuildID
.begin(), BuildID
.end());
56 BuildIDRef
llvm::object::getBuildID(const ObjectFile
*Obj
) {
57 if (auto *O
= dyn_cast
<ELFObjectFile
<ELF32LE
>>(Obj
))
58 return ::getBuildID(O
->getELFFile());
59 if (auto *O
= dyn_cast
<ELFObjectFile
<ELF32BE
>>(Obj
))
60 return ::getBuildID(O
->getELFFile());
61 if (auto *O
= dyn_cast
<ELFObjectFile
<ELF64LE
>>(Obj
))
62 return ::getBuildID(O
->getELFFile());
63 if (auto *O
= dyn_cast
<ELFObjectFile
<ELF64BE
>>(Obj
))
64 return ::getBuildID(O
->getELFFile());
68 std::optional
<std::string
> BuildIDFetcher::fetch(BuildIDRef BuildID
) const {
69 auto GetDebugPath
= [&](StringRef Directory
) {
70 SmallString
<128> Path
{Directory
};
71 sys::path::append(Path
, ".build-id",
72 llvm::toHex(BuildID
[0], /*LowerCase=*/true),
73 llvm::toHex(BuildID
.slice(1), /*LowerCase=*/true));
77 if (DebugFileDirectories
.empty()) {
78 SmallString
<128> Path
= GetDebugPath(
79 #if defined(__NetBSD__)
80 // Try /usr/libdata/debug/.build-id/../...
83 // Try /usr/lib/debug/.build-id/../...
87 if (llvm::sys::fs::exists(Path
))
88 return std::string(Path
);
90 for (const auto &Directory
: DebugFileDirectories
) {
91 // Try <debug-file-directory>/.build-id/../...
92 SmallString
<128> Path
= GetDebugPath(Directory
);
93 if (llvm::sys::fs::exists(Path
))
94 return std::string(Path
);