Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/GSYM/ObjectFileTransformer.cpp
35266 views
1
//===- ObjectFileTransformer.cpp --------------------------------*- C++ -*-===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include <unordered_set>
10
11
#include "llvm/Object/ELFObjectFile.h"
12
#include "llvm/Object/MachOUniversal.h"
13
#include "llvm/Object/ObjectFile.h"
14
#include "llvm/Support/DataExtractor.h"
15
#include "llvm/Support/raw_ostream.h"
16
17
#include "llvm/DebugInfo/GSYM/GsymCreator.h"
18
#include "llvm/DebugInfo/GSYM/ObjectFileTransformer.h"
19
#include "llvm/DebugInfo/GSYM/OutputAggregator.h"
20
21
using namespace llvm;
22
using namespace gsym;
23
24
constexpr uint32_t NT_GNU_BUILD_ID_TAG = 0x03;
25
26
static std::vector<uint8_t> getUUID(const object::ObjectFile &Obj) {
27
// Extract the UUID from the object file
28
std::vector<uint8_t> UUID;
29
if (auto *MachO = dyn_cast<object::MachOObjectFile>(&Obj)) {
30
const ArrayRef<uint8_t> MachUUID = MachO->getUuid();
31
if (!MachUUID.empty())
32
UUID.assign(MachUUID.data(), MachUUID.data() + MachUUID.size());
33
} else if (isa<object::ELFObjectFileBase>(&Obj)) {
34
const StringRef GNUBuildID(".note.gnu.build-id");
35
for (const object::SectionRef &Sect : Obj.sections()) {
36
Expected<StringRef> SectNameOrErr = Sect.getName();
37
if (!SectNameOrErr) {
38
consumeError(SectNameOrErr.takeError());
39
continue;
40
}
41
StringRef SectName(*SectNameOrErr);
42
if (SectName != GNUBuildID)
43
continue;
44
StringRef BuildIDData;
45
Expected<StringRef> E = Sect.getContents();
46
if (E)
47
BuildIDData = *E;
48
else {
49
consumeError(E.takeError());
50
continue;
51
}
52
DataExtractor Decoder(BuildIDData, Obj.makeTriple().isLittleEndian(), 8);
53
uint64_t Offset = 0;
54
const uint32_t NameSize = Decoder.getU32(&Offset);
55
const uint32_t PayloadSize = Decoder.getU32(&Offset);
56
const uint32_t PayloadType = Decoder.getU32(&Offset);
57
StringRef Name(Decoder.getFixedLengthString(&Offset, NameSize));
58
if (Name == "GNU" && PayloadType == NT_GNU_BUILD_ID_TAG) {
59
Offset = alignTo(Offset, 4);
60
StringRef UUIDBytes(Decoder.getBytes(&Offset, PayloadSize));
61
if (!UUIDBytes.empty()) {
62
auto Ptr = reinterpret_cast<const uint8_t *>(UUIDBytes.data());
63
UUID.assign(Ptr, Ptr + UUIDBytes.size());
64
}
65
}
66
}
67
}
68
return UUID;
69
}
70
71
llvm::Error ObjectFileTransformer::convert(const object::ObjectFile &Obj,
72
OutputAggregator &Out,
73
GsymCreator &Gsym) {
74
using namespace llvm::object;
75
76
const bool IsMachO = isa<MachOObjectFile>(&Obj);
77
const bool IsELF = isa<ELFObjectFileBase>(&Obj);
78
79
// Read build ID.
80
Gsym.setUUID(getUUID(Obj));
81
82
// Parse the symbol table.
83
size_t NumBefore = Gsym.getNumFunctionInfos();
84
for (const object::SymbolRef &Sym : Obj.symbols()) {
85
Expected<SymbolRef::Type> SymType = Sym.getType();
86
if (!SymType) {
87
consumeError(SymType.takeError());
88
continue;
89
}
90
Expected<uint64_t> AddrOrErr = Sym.getValue();
91
if (!AddrOrErr)
92
// TODO: Test this error.
93
return AddrOrErr.takeError();
94
95
if (SymType.get() != SymbolRef::Type::ST_Function ||
96
!Gsym.IsValidTextAddress(*AddrOrErr))
97
continue;
98
// Function size for MachO files will be 0
99
constexpr bool NoCopy = false;
100
const uint64_t size = IsELF ? ELFSymbolRef(Sym).getSize() : 0;
101
Expected<StringRef> Name = Sym.getName();
102
if (!Name) {
103
if (Out.GetOS())
104
logAllUnhandledErrors(Name.takeError(), *Out.GetOS(),
105
"ObjectFileTransformer: ");
106
else
107
consumeError(Name.takeError());
108
continue;
109
}
110
// Remove the leading '_' character in any symbol names if there is one
111
// for mach-o files.
112
if (IsMachO)
113
Name->consume_front("_");
114
Gsym.addFunctionInfo(
115
FunctionInfo(*AddrOrErr, size, Gsym.insertString(*Name, NoCopy)));
116
}
117
size_t FunctionsAddedCount = Gsym.getNumFunctionInfos() - NumBefore;
118
if (Out.GetOS())
119
*Out.GetOS() << "Loaded " << FunctionsAddedCount
120
<< " functions from symbol table.\n";
121
return Error::success();
122
}
123
124