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
+
1
9
#include " bolt/Core/AddressMap.h"
2
10
#include " bolt/Core/BinaryContext.h"
3
11
#include " bolt/Core/BinaryFunction.h"
12
+ #include " bolt/Core/BinarySection.h"
4
13
#include " llvm/MC/MCStreamer.h"
5
14
#include " llvm/Support/DataExtractor.h"
6
15
7
16
namespace llvm {
8
17
namespace bolt {
9
18
10
- const char *const AddressMap::SectionName = " .bolt.address_map" ;
19
+ const char *const AddressMap::AddressSectionName = " .bolt.addr2addr_map" ;
20
+ const char *const AddressMap::LabelSectionName = " .bolt.label2addr_map" ;
11
21
12
- static void emitLabel (MCStreamer &Streamer, uint64_t InputAddress,
13
- const MCSymbol *OutputLabel) {
22
+ static void emitAddress (MCStreamer &Streamer, uint64_t InputAddress,
23
+ const MCSymbol *OutputLabel) {
14
24
Streamer.emitIntValue (InputAddress, 8 );
15
25
Streamer.emitSymbolValue (OutputLabel, 8 );
16
26
}
17
27
28
+ static void emitLabel (MCStreamer &Streamer, const MCSymbol *OutputLabel) {
29
+ Streamer.emitIntValue (reinterpret_cast <uint64_t >(OutputLabel), 8 );
30
+ Streamer.emitSymbolValue (OutputLabel, 8 );
31
+ }
32
+
18
33
void AddressMap::emit (MCStreamer &Streamer, BinaryContext &BC) {
19
- Streamer.switchSection (BC.getDataSection (SectionName));
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 ();
20
42
21
43
for (const auto &[BFAddress, BF] : BC.getBinaryFunctions ()) {
22
44
if (!BF.requiresAddressMap ())
@@ -26,37 +48,69 @@ void AddressMap::emit(MCStreamer &Streamer, BinaryContext &BC) {
26
48
if (!BB.getLabel ()->isDefined ())
27
49
continue ;
28
50
29
- emitLabel ( Streamer, BFAddress + BB. getInputAddressRange (). first ,
30
- BB.getLabel ());
51
+ Streamer. switchSection (BC. getDataSection (LabelSectionName));
52
+ emitLabel (Streamer, BB.getLabel ());
31
53
32
54
if (!BB.hasLocSyms ())
33
55
continue ;
34
56
57
+ Streamer.switchSection (BC.getDataSection (AddressSectionName));
35
58
for (auto [Offset, Symbol] : BB.getLocSyms ())
36
- emitLabel (Streamer, BFAddress + Offset, Symbol);
59
+ emitAddress (Streamer, BFAddress + Offset, Symbol);
37
60
}
38
61
}
39
62
}
40
63
41
- AddressMap AddressMap::parse (StringRef Buffer, const BinaryContext &BC) {
42
- const auto EntrySize = 2 * BC.AsmInfo -> getCodePointerSize ( );
43
- assert (Buffer. size () % EntrySize == 0 && " Unexpected address map size " );
64
+ std::optional< AddressMap> AddressMap::parse (BinaryContext &BC) {
65
+ auto AddressMapSection = BC.getUniqueSectionByName (AddressSectionName );
66
+ auto LabelMapSection = BC. getUniqueSectionByName (LabelSectionName );
44
67
45
- DataExtractor DE (Buffer, BC.AsmInfo ->isLittleEndian (),
46
- BC.AsmInfo ->getCodePointerSize ());
47
- DataExtractor::Cursor Cursor (0 );
68
+ if (!AddressMapSection && !LabelMapSection)
69
+ return std::nullopt;
48
70
49
71
AddressMap Parsed;
50
- Parsed.Map .reserve (Buffer.size () / EntrySize);
51
72
52
- while (Cursor && !DE.eof (Cursor)) {
53
- const auto Input = DE.getAddress (Cursor);
54
- const auto Output = DE.getAddress (Cursor);
55
- if (!Parsed.Map .count (Input))
56
- Parsed.Map .insert ({Input, Output});
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 (Cursor)) {
85
+ const uint64_t Input = DE.getAddress (Cursor);
86
+ const uint64_t Output = DE.getAddress (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 (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});
100
+ });
101
+ }
102
+
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});
111
+ });
57
112
}
58
113
59
- assert (Cursor && " Error reading address map section" );
60
114
return Parsed;
61
115
}
62
116
0 commit comments