1//===- bolt/Core/AddressMap.cpp - Input-output Address Map ----------------===//
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 "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"
15
16namespace llvm {
17namespace bolt {
18
19const char *const AddressMap::AddressSectionName = ".bolt.addr2addr_map";
20const char *const AddressMap::LabelSectionName = ".bolt.label2addr_map";
21
22static void emitAddress(MCStreamer &Streamer, uint64_t InputAddress,
23 const MCSymbol *OutputLabel) {
24 Streamer.emitIntValue(Value: InputAddress, Size: 8);
25 Streamer.emitSymbolValue(Sym: OutputLabel, Size: 8);
26}
27
28static void emitLabel(MCStreamer &Streamer, const MCSymbol *OutputLabel) {
29 Streamer.emitIntValue(Value: reinterpret_cast<uint64_t>(OutputLabel), Size: 8);
30 Streamer.emitSymbolValue(Sym: OutputLabel, Size: 8);
31}
32
33void 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,
36 /*IsText*/ false,
37 /*IsAllocatable*/ true);
38 BC.registerOrUpdateSection(Name: AddressSectionName, ELFType: ELF::SHT_PROGBITS, ELFFlags: Flags)
39 .setLinkOnly();
40 BC.registerOrUpdateSection(Name: LabelSectionName, ELFType: ELF::SHT_PROGBITS, ELFFlags: Flags)
41 .setLinkOnly();
42
43 for (const auto &[BFAddress, BF] : BC.getBinaryFunctions()) {
44 if (!BF.requiresAddressMap())
45 continue;
46
47 for (const auto &BB : BF) {
48 if (!BB.getLabel()->isDefined())
49 continue;
50
51 Streamer.switchSection(Section: BC.getDataSection(SectionName: LabelSectionName));
52 emitLabel(Streamer, OutputLabel: BB.getLabel());
53
54 if (!BB.hasLocSyms())
55 continue;
56
57 Streamer.switchSection(Section: BC.getDataSection(SectionName: AddressSectionName));
58 for (auto [Offset, Symbol] : BB.getLocSyms())
59 emitAddress(Streamer, InputAddress: BFAddress + Offset, OutputLabel: Symbol);
60 }
61 }
62}
63
64std::optional<AddressMap> AddressMap::parse(BinaryContext &BC) {
65 auto AddressMapSection = BC.getUniqueSectionByName(SectionName: AddressSectionName);
66 auto LabelMapSection = BC.getUniqueSectionByName(SectionName: LabelSectionName);
67
68 if (!AddressMapSection && !LabelMapSection)
69 return std::nullopt;
70
71 AddressMap Parsed;
72
73 const size_t EntrySize = 2 * BC.AsmInfo->getCodePointerSize();
74 auto parseSection =
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");
79
80 DataExtractor DE(Buffer, BC.AsmInfo->isLittleEndian(),
81 BC.AsmInfo->getCodePointerSize());
82 DataExtractor::Cursor Cursor(0);
83
84 while (Cursor && !DE.eof(C: Cursor)) {
85 const uint64_t Input = DE.getAddress(C&: Cursor);
86 const uint64_t Output = DE.getAddress(C&: Cursor);
87 InsertCallback(Input, Output);
88 }
89
90 assert(Cursor && "Error reading address map section");
91 BC.deregisterSection(Section);
92 };
93
94 if (AddressMapSection) {
95 Parsed.Address2AddressMap.reserve(n: AddressMapSection->getOutputSize() /
96 EntrySize);
97 parseSection(*AddressMapSection, [&](uint64_t Input, uint64_t Output) {
98 if (!Parsed.Address2AddressMap.count(x: Input))
99 Parsed.Address2AddressMap.insert(x: {Input, Output});
100 });
101 }
102
103 if (LabelMapSection) {
104 Parsed.Label2AddrMap.reserve(NumEntries: 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 KV: {reinterpret_cast<const MCSymbol *>(Input), Output});
111 });
112 }
113
114 return Parsed;
115}
116
117} // namespace bolt
118} // namespace llvm
119

source code of bolt/lib/Core/AddressMap.cpp