1 //===- bolt/Core/AddressMap.cpp - Input-output Address Map ----------------===//
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 //===----------------------------------------------------------------------===//
9 #include "bolt/Core/AddressMap.h"
10 #include "bolt/Core/BinaryContext.h"
11 #include "bolt/Core/BinaryFunction.h"
12 #include "bolt/Core/BinarySection.h"
13 #include "llvm/MC/MCStreamer.h"
14 #include "llvm/Support/DataExtractor.h"
19 const char *const AddressMap::AddressSectionName
= ".bolt.addr2addr_map";
20 const char *const AddressMap::LabelSectionName
= ".bolt.label2addr_map";
22 static void emitAddress(MCStreamer
&Streamer
, uint64_t InputAddress
,
23 const MCSymbol
*OutputLabel
) {
24 Streamer
.emitIntValue(InputAddress
, 8);
25 Streamer
.emitSymbolValue(OutputLabel
, 8);
28 static void emitLabel(MCStreamer
&Streamer
, const MCSymbol
*OutputLabel
) {
29 Streamer
.emitIntValue(reinterpret_cast<uint64_t>(OutputLabel
), 8);
30 Streamer
.emitSymbolValue(OutputLabel
, 8);
33 void AddressMap::emit(MCStreamer
&Streamer
, BinaryContext
&BC
) {
34 // Mark map sections as link-only to avoid allocation in the output file.
35 const unsigned Flags
= BinarySection::getFlags(/*IsReadOnly*/ true,
37 /*IsAllocatable*/ true);
38 BC
.registerOrUpdateSection(AddressSectionName
, ELF::SHT_PROGBITS
, Flags
)
40 BC
.registerOrUpdateSection(LabelSectionName
, ELF::SHT_PROGBITS
, Flags
)
43 for (const auto &[BFAddress
, BF
] : BC
.getBinaryFunctions()) {
44 if (!BF
.requiresAddressMap())
47 for (const auto &BB
: BF
) {
48 if (!BB
.getLabel()->isDefined())
51 Streamer
.switchSection(BC
.getDataSection(LabelSectionName
));
52 emitLabel(Streamer
, BB
.getLabel());
57 Streamer
.switchSection(BC
.getDataSection(AddressSectionName
));
58 for (auto [Offset
, Symbol
] : BB
.getLocSyms())
59 emitAddress(Streamer
, BFAddress
+ Offset
, Symbol
);
64 std::optional
<AddressMap
> AddressMap::parse(BinaryContext
&BC
) {
65 auto AddressMapSection
= BC
.getUniqueSectionByName(AddressSectionName
);
66 auto LabelMapSection
= BC
.getUniqueSectionByName(LabelSectionName
);
68 if (!AddressMapSection
&& !LabelMapSection
)
73 const size_t EntrySize
= 2 * BC
.AsmInfo
->getCodePointerSize();
75 [&](BinarySection
&Section
,
76 function_ref
<void(uint64_t, uint64_t)> InsertCallback
) {
77 StringRef Buffer
= Section
.getOutputContents();
78 assert(Buffer
.size() % EntrySize
== 0 && "Unexpected address map size");
80 DataExtractor
DE(Buffer
, BC
.AsmInfo
->isLittleEndian(),
81 BC
.AsmInfo
->getCodePointerSize());
82 DataExtractor::Cursor
Cursor(0);
84 while (Cursor
&& !DE
.eof(Cursor
)) {
85 const uint64_t Input
= DE
.getAddress(Cursor
);
86 const uint64_t Output
= DE
.getAddress(Cursor
);
87 InsertCallback(Input
, Output
);
90 assert(Cursor
&& "Error reading address map section");
91 BC
.deregisterSection(Section
);
94 if (AddressMapSection
) {
95 Parsed
.Address2AddressMap
.reserve(AddressMapSection
->getOutputSize() /
97 parseSection(*AddressMapSection
, [&](uint64_t Input
, uint64_t Output
) {
98 if (!Parsed
.Address2AddressMap
.count(Input
))
99 Parsed
.Address2AddressMap
.insert({Input
, Output
});
103 if (LabelMapSection
) {
104 Parsed
.Label2AddrMap
.reserve(LabelMapSection
->getOutputSize() / EntrySize
);
105 parseSection(*LabelMapSection
, [&](uint64_t Input
, uint64_t Output
) {
106 assert(!Parsed
.Label2AddrMap
.count(
107 reinterpret_cast<const MCSymbol
*>(Input
)) &&
108 "Duplicate label entry detected.");
109 Parsed
.Label2AddrMap
.insert(
110 {reinterpret_cast<const MCSymbol
*>(Input
), Output
});