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+
19#include " bolt/Core/AddressMap.h"
210#include " bolt/Core/BinaryContext.h"
311#include " bolt/Core/BinaryFunction.h"
12+ #include " bolt/Core/BinarySection.h"
413#include " llvm/MC/MCStreamer.h"
514#include " llvm/Support/DataExtractor.h"
615
716namespace llvm {
817namespace bolt {
918
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" ;
1121
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) {
1424 Streamer.emitIntValue (InputAddress, 8 );
1525 Streamer.emitSymbolValue (OutputLabel, 8 );
1626}
1727
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+
1833void 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 ();
2042
2143 for (const auto &[BFAddress, BF] : BC.getBinaryFunctions ()) {
2244 if (!BF.requiresAddressMap ())
@@ -26,37 +48,69 @@ void AddressMap::emit(MCStreamer &Streamer, BinaryContext &BC) {
2648 if (!BB.getLabel ()->isDefined ())
2749 continue ;
2850
29- emitLabel ( Streamer, BFAddress + BB. getInputAddressRange (). first ,
30- BB.getLabel ());
51+ Streamer. switchSection (BC. getDataSection (LabelSectionName));
52+ emitLabel (Streamer, BB.getLabel ());
3153
3254 if (!BB.hasLocSyms ())
3355 continue ;
3456
57+ Streamer.switchSection (BC.getDataSection (AddressSectionName));
3558 for (auto [Offset, Symbol] : BB.getLocSyms ())
36- emitLabel (Streamer, BFAddress + Offset, Symbol);
59+ emitAddress (Streamer, BFAddress + Offset, Symbol);
3760 }
3861 }
3962}
4063
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 );
4467
45- DataExtractor DE (Buffer, BC.AsmInfo ->isLittleEndian (),
46- BC.AsmInfo ->getCodePointerSize ());
47- DataExtractor::Cursor Cursor (0 );
68+ if (!AddressMapSection && !LabelMapSection)
69+ return std::nullopt ;
4870
4971 AddressMap Parsed;
50- Parsed.Map .reserve (Buffer.size () / EntrySize);
5172
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+ });
57112 }
58113
59- assert (Cursor && " Error reading address map section" );
60114 return Parsed;
61115}
62116
0 commit comments