brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.1 KiB · efa376d Raw
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