119 lines · cpp
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-exception6//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(InputAddress, 8);25 Streamer.emitSymbolValue(OutputLabel, 8);26}27 28static void emitLabel(MCStreamer &Streamer, const MCSymbol *OutputLabel) {29 Streamer.emitIntValue(reinterpret_cast<uint64_t>(OutputLabel), 8);30 Streamer.emitSymbolValue(OutputLabel, 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(AddressSectionName, ELF::SHT_PROGBITS, Flags)39 .setLinkOnly();40 BC.registerOrUpdateSection(LabelSectionName, ELF::SHT_PROGBITS, 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(BC.getDataSection(LabelSectionName));52 emitLabel(Streamer, BB.getLabel());53 54 if (!BB.hasLocSyms())55 continue;56 57 Streamer.switchSection(BC.getDataSection(AddressSectionName));58 for (auto [Offset, Symbol] : BB.getLocSyms())59 emitAddress(Streamer, BFAddress + Offset, Symbol);60 }61 }62}63 64std::optional<AddressMap> AddressMap::parse(BinaryContext &BC) {65 auto AddressMapSection = BC.getUniqueSectionByName(AddressSectionName);66 auto LabelMapSection = BC.getUniqueSectionByName(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(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 });112 }113 114 return Parsed;115}116 117} // namespace bolt118} // namespace llvm119