brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · 6f588d2 Raw
130 lines · cpp
1//===- bolt/Core/JumpTable.cpp - Jump table at low-level IR ---------------===//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// This file implements the JumpTable class.10//11//===----------------------------------------------------------------------===//12 13#include "bolt/Core/JumpTable.h"14#include "bolt/Core/BinaryFunction.h"15#include "bolt/Core/BinarySection.h"16#include "llvm/Support/CommandLine.h"17 18#define DEBUG_TYPE "bolt"19 20using namespace llvm;21using namespace bolt;22 23using JumpTable = bolt::JumpTable;24 25namespace opts {26extern cl::opt<JumpTableSupportLevel> JumpTables;27extern cl::opt<unsigned> Verbosity;28} // namespace opts29 30bolt::JumpTable::JumpTable(MCSymbol &Symbol, uint64_t Address, size_t EntrySize,31                           JumpTableType Type, LabelMapType &&Labels,32                           BinarySection &Section)33    : BinaryData(Symbol, Address, 0, EntrySize, Section), EntrySize(EntrySize),34      OutputEntrySize(EntrySize), Type(Type), Labels(Labels) {}35 36std::pair<size_t, size_t>37bolt::JumpTable::getEntriesForAddress(const uint64_t Addr) const {38  // Check if this is not an address, but a cloned JT id39  if ((int64_t)Addr < 0ll)40    return std::make_pair(0, Entries.size());41 42  const uint64_t InstOffset = Addr - getAddress();43  size_t StartIndex = 0, EndIndex = 0;44  uint64_t Offset = 0;45 46  for (size_t I = 0; I < Entries.size(); ++I) {47    auto LI = Labels.find(Offset);48    if (LI != Labels.end()) {49      const auto NextLI = std::next(LI);50      const uint64_t NextOffset =51          NextLI == Labels.end() ? getSize() : NextLI->first;52      if (InstOffset >= LI->first && InstOffset < NextOffset) {53        StartIndex = I;54        EndIndex = I;55        while (Offset < NextOffset) {56          ++EndIndex;57          Offset += EntrySize;58        }59        break;60      }61    }62    Offset += EntrySize;63  }64 65  return std::make_pair(StartIndex, EndIndex);66}67 68bool bolt::JumpTable::replaceDestination(uint64_t JTAddress,69                                         const MCSymbol *OldDest,70                                         MCSymbol *NewDest) {71  bool Patched = false;72  const std::pair<size_t, size_t> Range = getEntriesForAddress(JTAddress);73  for (auto I = Range.first; I != Range.second; ++I) {74    if (Entries[I] == OldDest) {75      Patched = true;76      Entries[I] = NewDest;77    }78  }79  return Patched;80}81 82void bolt::JumpTable::updateOriginal() {83  BinaryContext &BC = getSection().getBinaryContext();84  const uint64_t BaseOffset = getAddress() - getSection().getAddress();85  uint64_t EntryOffset = BaseOffset;86  for (MCSymbol *Entry : Entries) {87    const uint32_t RelType =88        Type == JTT_NORMAL ? ELF::R_X86_64_64 : ELF::R_X86_64_PC32;89    const uint64_t RelAddend =90        Type == JTT_NORMAL ? 0 : EntryOffset - BaseOffset;91    // Replace existing relocation with the new one to allow any modifications92    // to the original jump table.93    if (BC.HasRelocations)94      getOutputSection().removeRelocationAt(EntryOffset);95    getOutputSection().addRelocation(EntryOffset, Entry, RelType, RelAddend);96    EntryOffset += EntrySize;97  }98}99 100void bolt::JumpTable::print(raw_ostream &OS) const {101  uint64_t Offset = 0;102  if (Type == JTT_PIC)103    OS << "PIC ";104  ListSeparator LS;105 106  OS << "Jump table " << getName() << " for function ";107  for (BinaryFunction *Frag : Parents)108    OS << LS << *Frag;109  OS << " at 0x" << Twine::utohexstr(getAddress()) << " with a total count of "110     << Count << ":\n";111  for (const uint64_t EntryAddress : EntriesAsAddress)112    OS << "  absolute offset: 0x" << Twine::utohexstr(EntryAddress) << '\n';113  for (const MCSymbol *Entry : Entries) {114    auto LI = Labels.find(Offset);115    if (Offset && LI != Labels.end()) {116      OS << "Jump Table " << LI->second->getName() << " at 0x"117         << Twine::utohexstr(getAddress() + Offset)118         << " (possibly part of larger jump table):\n";119    }120    OS << format("  0x%04" PRIx64 " : ", Offset) << Entry->getName();121    if (!Counts.empty()) {122      OS << " : " << Counts[Offset / EntrySize].Mispreds << "/"123         << Counts[Offset / EntrySize].Count;124    }125    OS << '\n';126    Offset += EntrySize;127  }128  OS << "\n\n";129}130