[nfc][Driver] Remove {{(.exe)?}} from sanitizer test (#121160)
[llvm-project.git] / bolt / lib / Core / AddressMap.cpp
blobefa376d408db882b2fb3b937cab287063b5c79fc
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 //===----------------------------------------------------------------------===//
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"
16 namespace llvm {
17 namespace bolt {
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,
36 /*IsText*/ false,
37 /*IsAllocatable*/ true);
38 BC.registerOrUpdateSection(AddressSectionName, ELF::SHT_PROGBITS, Flags)
39 .setLinkOnly();
40 BC.registerOrUpdateSection(LabelSectionName, ELF::SHT_PROGBITS, Flags)
41 .setLinkOnly();
43 for (const auto &[BFAddress, BF] : BC.getBinaryFunctions()) {
44 if (!BF.requiresAddressMap())
45 continue;
47 for (const auto &BB : BF) {
48 if (!BB.getLabel()->isDefined())
49 continue;
51 Streamer.switchSection(BC.getDataSection(LabelSectionName));
52 emitLabel(Streamer, BB.getLabel());
54 if (!BB.hasLocSyms())
55 continue;
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)
69 return std::nullopt;
71 AddressMap Parsed;
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");
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() /
96 EntrySize);
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});
114 return Parsed;
117 } // namespace bolt
118 } // namespace llvm