-
Notifications
You must be signed in to change notification settings - Fork 13.3k
/
Copy pathAddressMap.cpp
118 lines (96 loc) · 4.15 KB
/
AddressMap.cpp
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//===- bolt/Core/AddressMap.cpp - Input-output Address Map ----------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "bolt/Core/AddressMap.h"
#include "bolt/Core/BinaryContext.h"
#include "bolt/Core/BinaryFunction.h"
#include "bolt/Core/BinarySection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/DataExtractor.h"
namespace llvm {
namespace bolt {
const char *const AddressMap::AddressSectionName = ".bolt.addr2addr_map";
const char *const AddressMap::LabelSectionName = ".bolt.label2addr_map";
static void emitAddress(MCStreamer &Streamer, uint64_t InputAddress,
const MCSymbol *OutputLabel) {
Streamer.emitIntValue(InputAddress, 8);
Streamer.emitSymbolValue(OutputLabel, 8);
}
static void emitLabel(MCStreamer &Streamer, const MCSymbol *OutputLabel) {
Streamer.emitIntValue(reinterpret_cast<uint64_t>(OutputLabel), 8);
Streamer.emitSymbolValue(OutputLabel, 8);
}
void AddressMap::emit(MCStreamer &Streamer, BinaryContext &BC) {
// Mark map sections as link-only to avoid allocation in the output file.
const unsigned Flags = BinarySection::getFlags(/*IsReadOnly*/ true,
/*IsText*/ false,
/*IsAllocatable*/ true);
BC.registerOrUpdateSection(AddressSectionName, ELF::SHT_PROGBITS, Flags)
.setLinkOnly();
BC.registerOrUpdateSection(LabelSectionName, ELF::SHT_PROGBITS, Flags)
.setLinkOnly();
for (const auto &[BFAddress, BF] : BC.getBinaryFunctions()) {
if (!BF.requiresAddressMap())
continue;
for (const auto &BB : BF) {
if (!BB.getLabel()->isDefined())
continue;
Streamer.switchSection(BC.getDataSection(LabelSectionName));
emitLabel(Streamer, BB.getLabel());
if (!BB.hasLocSyms())
continue;
Streamer.switchSection(BC.getDataSection(AddressSectionName));
for (auto [Offset, Symbol] : BB.getLocSyms())
emitAddress(Streamer, BFAddress + Offset, Symbol);
}
}
}
std::optional<AddressMap> AddressMap::parse(BinaryContext &BC) {
auto AddressMapSection = BC.getUniqueSectionByName(AddressSectionName);
auto LabelMapSection = BC.getUniqueSectionByName(LabelSectionName);
if (!AddressMapSection && !LabelMapSection)
return std::nullopt;
AddressMap Parsed;
const size_t EntrySize = 2 * BC.AsmInfo->getCodePointerSize();
auto parseSection =
[&](BinarySection &Section,
function_ref<void(uint64_t, uint64_t)> InsertCallback) {
StringRef Buffer = Section.getOutputContents();
assert(Buffer.size() % EntrySize == 0 && "Unexpected address map size");
DataExtractor DE(Buffer, BC.AsmInfo->isLittleEndian(),
BC.AsmInfo->getCodePointerSize());
DataExtractor::Cursor Cursor(0);
while (Cursor && !DE.eof(Cursor)) {
const uint64_t Input = DE.getAddress(Cursor);
const uint64_t Output = DE.getAddress(Cursor);
InsertCallback(Input, Output);
}
assert(Cursor && "Error reading address map section");
BC.deregisterSection(Section);
};
if (AddressMapSection) {
Parsed.Address2AddressMap.reserve(AddressMapSection->getOutputSize() /
EntrySize);
parseSection(*AddressMapSection, [&](uint64_t Input, uint64_t Output) {
if (!Parsed.Address2AddressMap.count(Input))
Parsed.Address2AddressMap.insert({Input, Output});
});
}
if (LabelMapSection) {
Parsed.Label2AddrMap.reserve(LabelMapSection->getOutputSize() / EntrySize);
parseSection(*LabelMapSection, [&](uint64_t Input, uint64_t Output) {
assert(!Parsed.Label2AddrMap.count(
reinterpret_cast<const MCSymbol *>(Input)) &&
"Duplicate label entry detected.");
Parsed.Label2AddrMap.insert(
{reinterpret_cast<const MCSymbol *>(Input), Output});
});
}
return Parsed;
}
} // namespace bolt
} // namespace llvm