brintos

brintos / llvm-project-archived public Read only

0
0
Text · 234.5 KiB · 1c6244b Raw
6422 lines · cpp
1//===- bolt/Rewrite/RewriteInstance.cpp - ELF rewriter --------------------===//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/Rewrite/RewriteInstance.h"10#include "bolt/Core/AddressMap.h"11#include "bolt/Core/BinaryContext.h"12#include "bolt/Core/BinaryEmitter.h"13#include "bolt/Core/BinaryFunction.h"14#include "bolt/Core/DebugData.h"15#include "bolt/Core/Exceptions.h"16#include "bolt/Core/FunctionLayout.h"17#include "bolt/Core/MCPlusBuilder.h"18#include "bolt/Core/ParallelUtilities.h"19#include "bolt/Core/Relocation.h"20#include "bolt/Passes/BinaryPasses.h"21#include "bolt/Passes/CacheMetrics.h"22#include "bolt/Passes/IdenticalCodeFolding.h"23#include "bolt/Passes/PAuthGadgetScanner.h"24#include "bolt/Passes/ReorderFunctions.h"25#include "bolt/Profile/BoltAddressTranslation.h"26#include "bolt/Profile/DataAggregator.h"27#include "bolt/Profile/DataReader.h"28#include "bolt/Profile/YAMLProfileReader.h"29#include "bolt/Profile/YAMLProfileWriter.h"30#include "bolt/Rewrite/BinaryPassManager.h"31#include "bolt/Rewrite/DWARFRewriter.h"32#include "bolt/Rewrite/ExecutableFileMemoryManager.h"33#include "bolt/Rewrite/JITLinkLinker.h"34#include "bolt/Rewrite/MetadataRewriters.h"35#include "bolt/RuntimeLibs/HugifyRuntimeLibrary.h"36#include "bolt/RuntimeLibs/InstrumentationRuntimeLibrary.h"37#include "bolt/Utils/CommandLineOpts.h"38#include "bolt/Utils/Utils.h"39#include "llvm/ADT/AddressRanges.h"40#include "llvm/ADT/STLExtras.h"41#include "llvm/DebugInfo/DWARF/DWARFContext.h"42#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"43#include "llvm/MC/MCAsmBackend.h"44#include "llvm/MC/MCAsmInfo.h"45#include "llvm/MC/MCDisassembler/MCDisassembler.h"46#include "llvm/MC/MCObjectStreamer.h"47#include "llvm/MC/MCStreamer.h"48#include "llvm/MC/MCSymbol.h"49#include "llvm/MC/TargetRegistry.h"50#include "llvm/Object/ObjectFile.h"51#include "llvm/Support/Alignment.h"52#include "llvm/Support/Casting.h"53#include "llvm/Support/CommandLine.h"54#include "llvm/Support/DataExtractor.h"55#include "llvm/Support/Errc.h"56#include "llvm/Support/Error.h"57#include "llvm/Support/FileSystem.h"58#include "llvm/Support/ManagedStatic.h"59#include "llvm/Support/Timer.h"60#include "llvm/Support/ToolOutputFile.h"61#include "llvm/Support/raw_ostream.h"62#include <algorithm>63#include <fstream>64#include <memory>65#include <optional>66#include <system_error>67 68#undef  DEBUG_TYPE69#define DEBUG_TYPE "bolt"70 71using namespace llvm;72using namespace object;73using namespace bolt;74 75extern cl::opt<uint32_t> X86AlignBranchBoundary;76extern cl::opt<bool> X86AlignBranchWithin32BBoundaries;77 78namespace opts {79 80extern cl::list<std::string> HotTextMoveSections;81extern cl::opt<bool> Hugify;82extern cl::opt<bool> Instrument;83extern cl::opt<bool> KeepNops;84extern cl::opt<bool> Lite;85extern cl::list<std::string> PrintOnly;86extern cl::opt<std::string> PrintOnlyFile;87extern cl::list<std::string> ReorderData;88extern cl::opt<bolt::ReorderFunctions::ReorderType> ReorderFunctions;89extern cl::opt<bool> TerminalHLT;90extern cl::opt<bool> TerminalTrap;91extern cl::opt<bool> TimeBuild;92extern cl::opt<bool> TimeRewrite;93extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,94               llvm::bolt::DeprecatedICFNumericOptionParser>95    ICF;96 97static cl::opt<bool>98    AllowStripped("allow-stripped",99                  cl::desc("allow processing of stripped binaries"), cl::Hidden,100                  cl::cat(BoltCategory));101 102static cl::opt<bool> ForceToDataRelocations(103    "force-data-relocations",104    cl::desc("force relocations to data sections to always be processed"),105 106    cl::Hidden, cl::cat(BoltCategory));107 108static cl::opt<std::string>109    BoltID("bolt-id",110           cl::desc("add any string to tag this execution in the "111                    "output binary via bolt info section"),112           cl::cat(BoltCategory));113 114cl::opt<bool> DumpDotAll(115    "dump-dot-all",116    cl::desc("dump function CFGs to graphviz format after each stage;"117             "enable '-print-loops' for color-coded blocks"),118    cl::Hidden, cl::cat(BoltCategory));119 120cl::list<std::string> DumpDotFunc(121    "dump-dot-func", cl::CommaSeparated,122    cl::desc(123        "dump function CFGs to graphviz format for specified functions only;"124        "takes function name patterns (regex supported)"),125    cl::value_desc("func1,func2,func3,..."), cl::Hidden, cl::cat(BoltCategory));126 127bool shouldDumpDot(const bolt::BinaryFunction &Function) {128  // If dump-dot-all is enabled, dump all functions129  if (DumpDotAll)130    return !Function.isIgnored();131 132  // If no specific functions specified in dump-dot-func, don't dump any133  if (DumpDotFunc.empty())134    return false;135 136  if (Function.isIgnored())137    return false;138 139  // Check if function matches any of the specified patterns140  for (const std::string &Name : DumpDotFunc) {141    if (Function.hasNameRegex(Name)) {142      return true;143    }144  }145 146  return false;147}148 149static cl::list<std::string>150ForceFunctionNames("funcs",151  cl::CommaSeparated,152  cl::desc("limit optimizations to functions from the list"),153  cl::value_desc("func1,func2,func3,..."),154  cl::Hidden,155  cl::cat(BoltCategory));156 157static cl::opt<std::string>158FunctionNamesFile("funcs-file",159  cl::desc("file with list of functions to optimize"),160  cl::Hidden,161  cl::cat(BoltCategory));162 163static cl::list<std::string> ForceFunctionNamesNR(164    "funcs-no-regex", cl::CommaSeparated,165    cl::desc("limit optimizations to functions from the list (non-regex)"),166    cl::value_desc("func1,func2,func3,..."), cl::Hidden, cl::cat(BoltCategory));167 168static cl::opt<std::string> FunctionNamesFileNR(169    "funcs-file-no-regex",170    cl::desc("file with list of functions to optimize (non-regex)"), cl::Hidden,171    cl::cat(BoltCategory));172 173cl::opt<bool>174KeepTmp("keep-tmp",175  cl::desc("preserve intermediate .o file"),176  cl::Hidden,177  cl::cat(BoltCategory));178 179static cl::opt<unsigned>180LiteThresholdPct("lite-threshold-pct",181  cl::desc("threshold (in percent) for selecting functions to process in lite "182            "mode. Higher threshold means fewer functions to process. E.g "183            "threshold of 90 means only top 10 percent of functions with "184            "profile will be processed."),185  cl::init(0),186  cl::ZeroOrMore,187  cl::Hidden,188  cl::cat(BoltOptCategory));189 190static cl::opt<unsigned> LiteThresholdCount(191    "lite-threshold-count",192    cl::desc("similar to '-lite-threshold-pct' but specify threshold using "193             "absolute function call count. I.e. limit processing to functions "194             "executed at least the specified number of times."),195    cl::init(0), cl::Hidden, cl::cat(BoltOptCategory));196 197static cl::opt<unsigned>198    MaxFunctions("max-funcs",199                 cl::desc("maximum number of functions to process"), cl::Hidden,200                 cl::cat(BoltCategory));201 202static cl::opt<unsigned> MaxDataRelocations(203    "max-data-relocations",204    cl::desc("maximum number of data relocations to process"), cl::Hidden,205    cl::cat(BoltCategory));206 207cl::opt<bool> PrintAll("print-all",208                       cl::desc("print functions after each stage"), cl::Hidden,209                       cl::cat(BoltCategory));210 211static cl::opt<bool>212    PrintProfile("print-profile",213                 cl::desc("print functions after attaching profile"),214                 cl::Hidden, cl::cat(BoltCategory));215 216cl::opt<bool> PrintCFG("print-cfg",217                       cl::desc("print functions after CFG construction"),218                       cl::Hidden, cl::cat(BoltCategory));219 220cl::opt<bool> PrintDisasm("print-disasm",221                          cl::desc("print function after disassembly"),222                          cl::Hidden, cl::cat(BoltCategory));223 224static cl::opt<bool>225    PrintGlobals("print-globals",226                 cl::desc("print global symbols after disassembly"), cl::Hidden,227                 cl::cat(BoltCategory));228 229extern cl::opt<bool> PrintSections;230 231static cl::opt<bool> PrintLoopInfo("print-loops",232                                   cl::desc("print loop related information"),233                                   cl::Hidden, cl::cat(BoltCategory));234 235static cl::opt<cl::boolOrDefault> RelocationMode(236    "relocs", cl::desc("use relocations in the binary (default=autodetect)"),237    cl::cat(BoltCategory));238 239extern cl::opt<std::string> SaveProfile;240 241static cl::list<std::string>242SkipFunctionNames("skip-funcs",243  cl::CommaSeparated,244  cl::desc("list of functions to skip"),245  cl::value_desc("func1,func2,func3,..."),246  cl::Hidden,247  cl::cat(BoltCategory));248 249static cl::opt<std::string>250SkipFunctionNamesFile("skip-funcs-file",251  cl::desc("file with list of functions to skip"),252  cl::Hidden,253  cl::cat(BoltCategory));254 255static cl::opt<bool> TrapOldCode(256    "trap-old-code",257    cl::desc("insert traps in old function bodies (relocation mode)"),258    cl::Hidden, cl::cat(BoltCategory));259 260static cl::opt<std::string> DWPPathName("dwp",261                                        cl::desc("Path and name to DWP file."),262                                        cl::Hidden, cl::init(""),263                                        cl::cat(BoltCategory));264 265static cl::opt<bool>266UseGnuStack("use-gnu-stack",267  cl::desc("use GNU_STACK program header for new segment (workaround for "268           "issues with strip/objcopy)"),269  cl::ZeroOrMore,270  cl::cat(BoltCategory));271 272static cl::opt<uint64_t> CustomAllocationVMA(273    "custom-allocation-vma",274    cl::desc("use a custom address at which new code will be put, "275             "bypassing BOLT's logic to detect where to put code"),276    cl::Hidden, cl::cat(BoltCategory));277 278static cl::opt<bool>279SequentialDisassembly("sequential-disassembly",280  cl::desc("performs disassembly sequentially"),281  cl::init(false),282  cl::cat(BoltOptCategory));283 284static cl::opt<bool> WriteBoltInfoSection(285    "bolt-info", cl::desc("write bolt info section in the output binary"),286    cl::init(true), cl::Hidden, cl::cat(BoltOutputCategory));287 288cl::bits<GadgetScannerKind> GadgetScannersToRun(289    "scanners", cl::desc("which gadget scanners to run"),290    cl::values(291        clEnumValN(GS_PACRET, "pacret",292                   "pac-ret: return address protection (subset of \"pauth\")"),293        clEnumValN(GS_PAUTH, "pauth", "All Pointer Authentication scanners"),294        clEnumValN(GS_ALL, "all", "All implemented scanners")),295    cl::ZeroOrMore, cl::CommaSeparated, cl::cat(BinaryAnalysisCategory));296 297// Primary targets for hooking runtime library initialization hooking298// with fallback to next item in case if current item is not available299// in the input binary.300enum RuntimeLibInitHookTarget : char {301  RLIH_ENTRY_POINT = 0, /// Use ELF Header Entry Point302  RLIH_INIT = 1,        /// Use ELF DT_INIT entry303  RLIH_INIT_ARRAY = 2,  /// Use ELF .init_array entry304};305 306cl::opt<RuntimeLibInitHookTarget> RuntimeLibInitHook(307    "runtime-lib-init-hook",308    cl::desc("Primary target for hooking runtime library initialization, used "309             "in fallback order of availabiliy in input binary (entry_point -> "310             "init -> init_array) (default: entry_point)"),311    cl::Hidden, cl::init(RLIH_ENTRY_POINT),312    cl::values(clEnumValN(RLIH_ENTRY_POINT, "entry_point",313                          "use ELF Header Entry Point"),314               clEnumValN(RLIH_INIT, "init", "use ELF DT_INIT entry"),315               clEnumValN(RLIH_INIT_ARRAY, "init_array",316                          "use ELF .init_array entry")),317    cl::ZeroOrMore, cl::cat(BoltOptCategory));318 319} // namespace opts320 321// FIXME: implement a better way to mark sections for replacement.322std::vector<std::string> RewriteInstance::DebugSectionsToOverwrite = {323    ".debug_abbrev", ".debug_aranges",  ".debug_line",   ".debug_line_str",324    ".debug_loc",    ".debug_loclists", ".debug_ranges", ".debug_rnglists",325    ".gdb_index",    ".debug_addr",     ".debug_abbrev", ".debug_info",326    ".debug_types",  ".pseudo_probe"};327 328const char RewriteInstance::TimerGroupName[] = "rewrite";329const char RewriteInstance::TimerGroupDesc[] = "Rewrite passes";330 331namespace llvm {332namespace bolt {333 334extern const char *BoltRevision;335 336// Weird location for createMCPlusBuilder, but this is here to avoid a337// cyclic dependency of libCore (its natural place) and libTarget. libRewrite338// can depend on libTarget, but not libCore. Since libRewrite is the only339// user of this function, we define it here.340MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch,341                                   const MCInstrAnalysis *Analysis,342                                   const MCInstrInfo *Info,343                                   const MCRegisterInfo *RegInfo,344                                   const MCSubtargetInfo *STI) {345#ifdef X86_AVAILABLE346  if (Arch == Triple::x86_64)347    return createX86MCPlusBuilder(Analysis, Info, RegInfo, STI);348#endif349 350#ifdef AARCH64_AVAILABLE351  if (Arch == Triple::aarch64)352    return createAArch64MCPlusBuilder(Analysis, Info, RegInfo, STI);353#endif354 355#ifdef RISCV_AVAILABLE356  if (Arch == Triple::riscv64)357    return createRISCVMCPlusBuilder(Analysis, Info, RegInfo, STI);358#endif359 360  llvm_unreachable("architecture unsupported by MCPlusBuilder");361}362 363} // namespace bolt364} // namespace llvm365 366using ELF64LEPhdrTy = ELF64LEFile::Elf_Phdr;367 368namespace {369 370bool refersToReorderedSection(ErrorOr<BinarySection &> Section) {371  return llvm::any_of(opts::ReorderData, [&](const std::string &SectionName) {372    return Section && Section->getName() == SectionName;373  });374}375 376} // anonymous namespace377 378Expected<std::unique_ptr<RewriteInstance>>379RewriteInstance::create(ELFObjectFileBase *File, const int Argc,380                        const char *const *Argv, StringRef ToolPath,381                        raw_ostream &Stdout, raw_ostream &Stderr) {382  Error Err = Error::success();383  auto RI = std::make_unique<RewriteInstance>(File, Argc, Argv, ToolPath,384                                              Stdout, Stderr, Err);385  if (Err)386    return std::move(Err);387  return std::move(RI);388}389 390RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc,391                                 const char *const *Argv, StringRef ToolPath,392                                 raw_ostream &Stdout, raw_ostream &Stderr,393                                 Error &Err)394    : InputFile(File), Argc(Argc), Argv(Argv), ToolPath(ToolPath),395      SHStrTab(StringTableBuilder::ELF) {396  ErrorAsOutParameter EAO(&Err);397  auto ELF64LEFile = dyn_cast<ELF64LEObjectFile>(InputFile);398  if (!ELF64LEFile) {399    Err = createStringError(errc::not_supported,400                            "Only 64-bit LE ELF binaries are supported");401    return;402  }403 404  bool IsPIC = false;405  const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();406  if (Obj.getHeader().e_type != ELF::ET_EXEC) {407    Stdout << "BOLT-INFO: shared object or position-independent executable "408              "detected\n";409    IsPIC = true;410  }411 412  // Make sure we don't miss any output on core dumps.413  Stdout.SetUnbuffered();414  Stderr.SetUnbuffered();415  LLVM_DEBUG(dbgs().SetUnbuffered());416 417  // Read RISCV subtarget features from input file418  std::unique_ptr<SubtargetFeatures> Features;419  Triple TheTriple = File->makeTriple();420  if (TheTriple.getArch() == llvm::Triple::riscv64) {421    Expected<SubtargetFeatures> FeaturesOrErr = File->getFeatures();422    if (auto E = FeaturesOrErr.takeError()) {423      Err = std::move(E);424      return;425    } else {426      Features.reset(new SubtargetFeatures(*FeaturesOrErr));427    }428  }429 430  Relocation::Arch = TheTriple.getArch();431  auto BCOrErr = BinaryContext::createBinaryContext(432      TheTriple, std::make_shared<orc::SymbolStringPool>(), File->getFileName(),433      Features.get(), IsPIC,434      DWARFContext::create(*File, DWARFContext::ProcessDebugRelocations::Ignore,435                           nullptr, opts::DWPPathName,436                           WithColor::defaultErrorHandler,437                           WithColor::defaultWarningHandler),438      JournalingStreams{Stdout, Stderr});439  if (Error E = BCOrErr.takeError()) {440    Err = std::move(E);441    return;442  }443  BC = std::move(BCOrErr.get());444  BC->initializeTarget(std::unique_ptr<MCPlusBuilder>(445      createMCPlusBuilder(BC->TheTriple->getArch(), BC->MIA.get(),446                          BC->MII.get(), BC->MRI.get(), BC->STI.get())));447 448  BAT = std::make_unique<BoltAddressTranslation>();449 450  if (opts::UpdateDebugSections)451    DebugInfoRewriter = std::make_unique<DWARFRewriter>(*BC);452 453  if (opts::Instrument)454    BC->setRuntimeLibrary(std::make_unique<InstrumentationRuntimeLibrary>());455  else if (opts::Hugify)456    BC->setRuntimeLibrary(std::make_unique<HugifyRuntimeLibrary>());457}458 459RewriteInstance::~RewriteInstance() {}460 461Error RewriteInstance::setProfile(StringRef Filename) {462  if (!sys::fs::exists(Filename))463    return errorCodeToError(make_error_code(errc::no_such_file_or_directory));464 465  if (ProfileReader) {466    // Already exists467    return make_error<StringError>(Twine("multiple profiles specified: ") +468                                       ProfileReader->getFilename() + " and " +469                                       Filename,470                                   inconvertibleErrorCode());471  }472 473  // Spawn a profile reader based on file contents.474  if (DataAggregator::checkPerfDataMagic(Filename))475    ProfileReader = std::make_unique<DataAggregator>(Filename);476  else if (YAMLProfileReader::isYAML(Filename))477    ProfileReader = std::make_unique<YAMLProfileReader>(Filename);478  else479    ProfileReader = std::make_unique<DataReader>(Filename);480 481  return Error::success();482}483 484/// Return true if the function \p BF should be disassembled.485static bool shouldDisassemble(const BinaryFunction &BF) {486  if (BF.isPseudo())487    return false;488 489  if (opts::processAllFunctions())490    return true;491 492  return !BF.isIgnored();493}494 495// Return if a section stored in the image falls into a segment address space.496// If not, Set \p Overlap to true if there's a partial overlap.497template <class ELFT>498static bool checkOffsets(const typename ELFT::Phdr &Phdr,499                         const typename ELFT::Shdr &Sec, bool &Overlap) {500  // SHT_NOBITS sections don't need to have an offset inside the segment.501  if (Sec.sh_type == ELF::SHT_NOBITS)502    return true;503 504  // Only non-empty sections can be at the end of a segment.505  uint64_t SectionSize = Sec.sh_size ? Sec.sh_size : 1ull;506  AddressRange SectionAddressRange((uint64_t)Sec.sh_offset,507                                   Sec.sh_offset + SectionSize);508  AddressRange SegmentAddressRange(Phdr.p_offset,509                                   Phdr.p_offset + Phdr.p_filesz);510  if (SegmentAddressRange.contains(SectionAddressRange))511    return true;512 513  Overlap = SegmentAddressRange.intersects(SectionAddressRange);514  return false;515}516 517// Check that an allocatable section belongs to a virtual address518// space of a segment.519template <class ELFT>520static bool checkVMA(const typename ELFT::Phdr &Phdr,521                     const typename ELFT::Shdr &Sec, bool &Overlap) {522  // Only non-empty sections can be at the end of a segment.523  uint64_t SectionSize = Sec.sh_size ? Sec.sh_size : 1ull;524  AddressRange SectionAddressRange((uint64_t)Sec.sh_addr,525                                   Sec.sh_addr + SectionSize);526  AddressRange SegmentAddressRange(Phdr.p_vaddr, Phdr.p_vaddr + Phdr.p_memsz);527 528  if (SegmentAddressRange.contains(SectionAddressRange))529    return true;530  Overlap = SegmentAddressRange.intersects(SectionAddressRange);531  return false;532}533 534void RewriteInstance::markGnuRelroSections() {535  using ELFT = ELF64LE;536  using ELFShdrTy = typename ELFObjectFile<ELFT>::Elf_Shdr;537  auto ELF64LEFile = cast<ELF64LEObjectFile>(InputFile);538  const ELFFile<ELFT> &Obj = ELF64LEFile->getELFFile();539 540  auto handleSection = [&](const ELFT::Phdr &Phdr, SectionRef SecRef) {541    BinarySection *BinarySection = BC->getSectionForSectionRef(SecRef);542    // If the section is non-allocatable, ignore it for GNU_RELRO purposes:543    // it can't be made read-only after runtime relocations processing.544    if (!BinarySection || !BinarySection->isAllocatable())545      return;546    const ELFShdrTy *Sec = cantFail(Obj.getSection(SecRef.getIndex()));547    bool ImageOverlap{false}, VMAOverlap{false};548    bool ImageContains = checkOffsets<ELFT>(Phdr, *Sec, ImageOverlap);549    bool VMAContains = checkVMA<ELFT>(Phdr, *Sec, VMAOverlap);550    if (ImageOverlap) {551      if (opts::Verbosity >= 1)552        BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial file offset "553                   << "overlap with section " << BinarySection->getName()554                   << '\n';555      return;556    }557    if (VMAOverlap) {558      if (opts::Verbosity >= 1)559        BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial VMA overlap "560                   << "with section " << BinarySection->getName() << '\n';561      return;562    }563    if (!ImageContains || !VMAContains)564      return;565    BinarySection->setRelro();566    if (opts::Verbosity >= 1)567      BC->outs() << "BOLT-INFO: marking " << BinarySection->getName()568                 << " as GNU_RELRO\n";569  };570 571  for (const ELFT::Phdr &Phdr : cantFail(Obj.program_headers()))572    if (Phdr.p_type == ELF::PT_GNU_RELRO)573      for (SectionRef SecRef : InputFile->sections())574        handleSection(Phdr, SecRef);575}576 577Error RewriteInstance::discoverStorage() {578  NamedRegionTimer T("discoverStorage", "discover storage", TimerGroupName,579                     TimerGroupDesc, opts::TimeRewrite);580 581  auto ELF64LEFile = cast<ELF64LEObjectFile>(InputFile);582  const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();583 584  BC->StartFunctionAddress = Obj.getHeader().e_entry;585 586  NextAvailableAddress = 0;587  uint64_t NextAvailableOffset = 0;588  Expected<ELF64LE::PhdrRange> PHsOrErr = Obj.program_headers();589  if (Error E = PHsOrErr.takeError())590    return E;591 592  ELF64LE::PhdrRange PHs = PHsOrErr.get();593  for (const ELF64LE::Phdr &Phdr : PHs) {594    switch (Phdr.p_type) {595    case ELF::PT_LOAD:596      BC->FirstAllocAddress = std::min(BC->FirstAllocAddress,597                                       static_cast<uint64_t>(Phdr.p_vaddr));598      NextAvailableAddress = std::max(NextAvailableAddress,599                                      Phdr.p_vaddr + Phdr.p_memsz);600      NextAvailableOffset = std::max(NextAvailableOffset,601                                     Phdr.p_offset + Phdr.p_filesz);602 603      BC->SegmentMapInfo[Phdr.p_vaddr] =604          SegmentInfo{Phdr.p_vaddr,605                      Phdr.p_memsz,606                      Phdr.p_offset,607                      Phdr.p_filesz,608                      Phdr.p_align,609                      (Phdr.p_flags & ELF::PF_X) != 0,610                      (Phdr.p_flags & ELF::PF_W) != 0};611      if (BC->TheTriple->getArch() == llvm::Triple::x86_64 &&612          Phdr.p_vaddr >= BinaryContext::KernelStartX86_64)613        BC->IsLinuxKernel = true;614      break;615    case ELF::PT_INTERP:616      BC->HasInterpHeader = true;617      break;618    }619  }620 621  if (BC->IsLinuxKernel)622    BC->outs() << "BOLT-INFO: Linux kernel binary detected\n";623 624  for (const SectionRef &Section : InputFile->sections()) {625    Expected<StringRef> SectionNameOrErr = Section.getName();626    if (Error E = SectionNameOrErr.takeError())627      return E;628    StringRef SectionName = SectionNameOrErr.get();629    if (SectionName == BC->getMainCodeSectionName()) {630      BC->OldTextSectionAddress = Section.getAddress();631      BC->OldTextSectionSize = Section.getSize();632 633      Expected<StringRef> SectionContentsOrErr = Section.getContents();634      if (Error E = SectionContentsOrErr.takeError())635        return E;636      StringRef SectionContents = SectionContentsOrErr.get();637      BC->OldTextSectionOffset =638          SectionContents.data() - InputFile->getData().data();639    }640 641    if (!opts::HeatmapMode &&642        !(opts::AggregateOnly && BAT->enabledFor(InputFile)) &&643        (SectionName.starts_with(getOrgSecPrefix()) ||644         SectionName == getBOLTTextSectionName()))645      return createStringError(646          errc::function_not_supported,647          "BOLT-ERROR: input file was processed by BOLT. Cannot re-optimize");648  }649 650  if (!NextAvailableAddress || !NextAvailableOffset)651    return createStringError(errc::executable_format_error,652                             "no PT_LOAD pheader seen");653 654  BC->outs() << "BOLT-INFO: first alloc address is 0x"655             << Twine::utohexstr(BC->FirstAllocAddress) << '\n';656 657  FirstNonAllocatableOffset = NextAvailableOffset;658 659  if (opts::CustomAllocationVMA) {660    // If user specified a custom address where we should start writing new661    // data, honor that.662    NextAvailableAddress = opts::CustomAllocationVMA;663    // Sanity check the user-supplied address and emit warnings if something664    // seems off.665    for (const ELF64LE::Phdr &Phdr : PHs) {666      switch (Phdr.p_type) {667      case ELF::PT_LOAD:668        if (NextAvailableAddress >= Phdr.p_vaddr &&669            NextAvailableAddress < Phdr.p_vaddr + Phdr.p_memsz) {670          BC->errs() << "BOLT-WARNING: user-supplied allocation vma 0x"671                     << Twine::utohexstr(NextAvailableAddress)672                     << " conflicts with ELF segment at 0x"673                     << Twine::utohexstr(Phdr.p_vaddr) << "\n";674        }675      }676    }677  }678  NextAvailableAddress = alignTo(NextAvailableAddress, BC->PageAlign);679  NextAvailableOffset = alignTo(NextAvailableOffset, BC->PageAlign);680 681  // Hugify: Additional huge page from left side due to682  // weird ASLR mapping addresses (4KB aligned)683  if (opts::Hugify && !BC->HasFixedLoadAddress) {684    NextAvailableAddress += BC->PageAlign;685  }686 687  NewTextSegmentAddress = NextAvailableAddress;688  NewTextSegmentOffset = NextAvailableOffset;689 690  if (!opts::UseGnuStack && !BC->IsLinuxKernel) {691    // This is where the black magic happens. Creating PHDR table in a segment692    // other than that containing ELF header is tricky. Some loaders and/or693    // parts of loaders will apply e_phoff from ELF header assuming both are in694    // the same segment, while others will do the proper calculation.695    // We create the new PHDR table in such a way that both of the methods696    // of loading and locating the table work. There's a slight file size697    // overhead because of that.698    //699    // NB: bfd's strip command cannot do the above and will corrupt the700    //     binary during the process of stripping non-allocatable sections.701    if (NextAvailableOffset <= NextAvailableAddress - BC->FirstAllocAddress)702      NextAvailableOffset = NextAvailableAddress - BC->FirstAllocAddress;703    else704      NextAvailableAddress = NextAvailableOffset + BC->FirstAllocAddress;705 706    assert(NextAvailableOffset ==707               NextAvailableAddress - BC->FirstAllocAddress &&708           "PHDR table address calculation error");709 710    BC->outs() << "BOLT-INFO: creating new program header table at address 0x"711               << Twine::utohexstr(NextAvailableAddress) << ", offset 0x"712               << Twine::utohexstr(NextAvailableOffset) << '\n';713 714    PHDRTableAddress = NextAvailableAddress;715    PHDRTableOffset = NextAvailableOffset;716    NewTextSegmentAddress = NextAvailableAddress;717    NewTextSegmentOffset = NextAvailableOffset;718 719    // Reserve space for 3 extra pheaders.720    unsigned Phnum = Obj.getHeader().e_phnum;721    Phnum += 3;722 723    // Reserve two more pheaders to avoid having writeable and executable724    // segment in instrumented binary.725    if (opts::Instrument)726      Phnum += 2;727 728    NextAvailableAddress += Phnum * sizeof(ELF64LEPhdrTy);729    NextAvailableOffset += Phnum * sizeof(ELF64LEPhdrTy);730 731    // Align at cache line.732    NextAvailableAddress = alignTo(NextAvailableAddress, 64);733    NextAvailableOffset = alignTo(NextAvailableOffset, 64);734  }735 736  BC->LayoutStartAddress = NextAvailableAddress;737 738  // Tools such as objcopy can strip section contents but leave header739  // entries. Check that at least .text is mapped in the file.740  if (!getFileOffsetForAddress(BC->OldTextSectionAddress))741    return createStringError(errc::executable_format_error,742                             "BOLT-ERROR: input binary is not a valid ELF "743                             "executable as its text section is not "744                             "mapped to a valid segment");745  return Error::success();746}747 748Error RewriteInstance::run() {749  assert(BC && "failed to create a binary context");750 751  BC->outs() << "BOLT-INFO: Target architecture: "752             << Triple::getArchTypeName(753                    (llvm::Triple::ArchType)InputFile->getArch())754             << "\n";755  BC->outs() << "BOLT-INFO: BOLT version: " << BoltRevision << "\n";756 757  selectFunctionsToPrint();758 759  if (Error E = discoverStorage())760    return E;761  if (Error E = readSpecialSections())762    return E;763  adjustCommandLineOptions();764  discoverFileObjects();765 766  if (opts::Instrument && !BC->IsStaticExecutable) {767    if (Error E = discoverRtInitAddress())768      return E;769    if (Error E = discoverRtFiniAddress())770      return E;771  }772 773  preprocessProfileData();774 775  selectFunctionsToProcess();776 777  readDebugInfo();778 779  disassembleFunctions();780 781  processMetadataPreCFG();782 783  buildFunctionsCFG();784 785  processProfileData();786 787  // Save input binary metadata if BAT section needs to be emitted788  if (opts::EnableBAT)789    BAT->saveMetadata(*BC);790 791  postProcessFunctions();792 793  processMetadataPostCFG();794 795  if (opts::DiffOnly)796    return Error::success();797 798  if (opts::BinaryAnalysisMode) {799    runBinaryAnalyses();800    return Error::success();801  }802 803  preregisterSections();804 805  runOptimizationPasses();806 807  finalizeMetadataPreEmit();808 809  emitAndLink();810 811  updateMetadata();812 813  if (opts::Instrument && !BC->IsStaticExecutable) {814    if (Error E = updateRtInitReloc())815      return E;816    if (Error E = updateRtFiniReloc())817      return E;818  }819 820  if (opts::OutputFilename == "/dev/null") {821    BC->outs() << "BOLT-INFO: skipping writing final binary to disk\n";822    return Error::success();823  } else if (BC->IsLinuxKernel) {824    BC->errs() << "BOLT-WARNING: Linux kernel support is experimental\n";825  }826 827  // Rewrite allocatable contents and copy non-allocatable parts with mods.828  rewriteFile();829  return Error::success();830}831 832void RewriteInstance::discoverFileObjects() {833  NamedRegionTimer T("discoverFileObjects", "discover file objects",834                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);835 836  // For local symbols we want to keep track of associated FILE symbol name for837  // disambiguation by combined name.838  for (const ELFSymbolRef &Symbol : InputFile->symbols()) {839    Expected<StringRef> NameOrError = Symbol.getName();840    if (NameOrError && NameOrError->starts_with("__asan_init")) {841      BC->errs()842          << "BOLT-ERROR: input file was compiled or linked with sanitizer "843             "support. Cannot optimize.\n";844      exit(1);845    }846    if (NameOrError && NameOrError->starts_with("__llvm_coverage_mapping")) {847      BC->errs()848          << "BOLT-ERROR: input file was compiled or linked with coverage "849             "support. Cannot optimize.\n";850      exit(1);851    }852 853    if (cantFail(Symbol.getFlags()) & SymbolRef::SF_Undefined)854      continue;855 856    if (cantFail(Symbol.getType()) == SymbolRef::ST_File)857      FileSymbols.emplace_back(Symbol);858  }859 860  // Sort symbols in the file by value. Ignore symbols from non-allocatable861  // sections. We memoize getAddress(), as it has rather high overhead.862  struct SymbolInfo {863    uint64_t Address;864    SymbolRef Symbol;865  };866  std::vector<SymbolInfo> SortedSymbols;867  auto isSymbolInMemory = [this](const SymbolRef &Sym) {868    if (cantFail(Sym.getType()) == SymbolRef::ST_File)869      return false;870    if (cantFail(Sym.getFlags()) & SymbolRef::SF_Absolute)871      return true;872    if (cantFail(Sym.getFlags()) & SymbolRef::SF_Undefined)873      return false;874    BinarySection Section(*BC, *cantFail(Sym.getSection()));875    return Section.isAllocatable();876  };877  auto checkSymbolInSection = [this](const SymbolInfo &S) {878    // Sometimes, we encounter symbols with addresses outside their section. If879    // such symbols happen to fall into another section, they can interfere with880    // disassembly. Notably, this occurs with AArch64 marker symbols ($d and $t)881    // that belong to .eh_frame, but end up pointing into .text.882    // As a workaround, we ignore all symbols that lie outside their sections.883    auto Section = cantFail(S.Symbol.getSection());884 885    // Accept all absolute symbols.886    if (Section == InputFile->section_end())887      return true;888 889    uint64_t SecStart = Section->getAddress();890    uint64_t SecEnd = SecStart + Section->getSize();891    uint64_t SymEnd = S.Address + ELFSymbolRef(S.Symbol).getSize();892    if (S.Address >= SecStart && SymEnd <= SecEnd)893      return true;894 895    auto SymType = cantFail(S.Symbol.getType());896    // Skip warnings for common benign cases.897    if (opts::Verbosity < 1 && SymType == SymbolRef::ST_Other)898      return false; // E.g. ELF::STT_TLS.899 900    auto SymName = S.Symbol.getName();901    auto SecName = cantFail(S.Symbol.getSection())->getName();902    BC->errs() << "BOLT-WARNING: ignoring symbol "903               << (SymName ? *SymName : "[unnamed]") << " at 0x"904               << Twine::utohexstr(S.Address) << ", which lies outside "905               << (SecName ? *SecName : "[unnamed]") << "\n";906 907    return false;908  };909  for (const SymbolRef &Symbol : InputFile->symbols())910    if (isSymbolInMemory(Symbol)) {911      SymbolInfo SymInfo{cantFail(Symbol.getAddress()), Symbol};912      if (checkSymbolInSection(SymInfo))913        SortedSymbols.push_back(SymInfo);914    }915 916  auto CompareSymbols = [this](const SymbolInfo &A, const SymbolInfo &B) {917    if (A.Address != B.Address)918      return A.Address < B.Address;919 920    const bool AMarker = BC->isMarker(A.Symbol);921    const bool BMarker = BC->isMarker(B.Symbol);922    if (AMarker || BMarker) {923      return AMarker && !BMarker;924    }925 926    const auto AType = cantFail(A.Symbol.getType());927    const auto BType = cantFail(B.Symbol.getType());928    if (AType == SymbolRef::ST_Function && BType != SymbolRef::ST_Function)929      return true;930    if (BType == SymbolRef::ST_Debug && AType != SymbolRef::ST_Debug)931      return true;932 933    return false;934  };935  llvm::stable_sort(SortedSymbols, CompareSymbols);936 937  auto LastSymbol = SortedSymbols.end();938  if (!SortedSymbols.empty())939    --LastSymbol;940 941  // For aarch64, the ABI defines mapping symbols so we identify data in the942  // code section (see IHI0056B). $d identifies data contents.943  // Compilers usually merge multiple data objects in a single $d-$x interval,944  // but we need every data object to be marked with $d. Because of that we945  // keep track of marker symbols with all locations of data objects.946 947  DenseMap<uint64_t, MarkerSymType> MarkerSymbols;948  auto addExtraDataMarkerPerSymbol = [&]() {949    bool IsData = false;950    uint64_t LastAddr = 0;951    for (const auto &SymInfo : SortedSymbols) {952      MarkerSymType MarkerType = BC->getMarkerType(SymInfo.Symbol);953 954      // Treat ST_Function as code.955      Expected<object::SymbolRef::Type> TypeOrError = SymInfo.Symbol.getType();956      consumeError(TypeOrError.takeError());957      if (TypeOrError && *TypeOrError == SymbolRef::ST_Function) {958        if (IsData) {959          Expected<StringRef> NameOrError = SymInfo.Symbol.getName();960          consumeError(NameOrError.takeError());961          if (LastAddr == SymInfo.Address) {962            BC->errs() << "BOLT-WARNING: ignoring data marker conflicting with "963                          "function symbol "964                       << *NameOrError << '\n';965          } else {966            BC->errs() << "BOLT-WARNING: function symbol " << *NameOrError967                       << " lacks code marker\n";968          }969        }970        MarkerType = MarkerSymType::CODE;971      }972 973      if (MarkerType != MarkerSymType::NONE) {974        MarkerSymbols[SymInfo.Address] = MarkerType;975        LastAddr = SymInfo.Address;976        IsData = MarkerType == MarkerSymType::DATA;977        continue;978      }979 980      if (IsData) {981        MarkerSymbols[SymInfo.Address] = MarkerSymType::DATA;982        LastAddr = SymInfo.Address;983      }984    }985  };986 987  if (BC->isAArch64() || BC->isRISCV()) {988    addExtraDataMarkerPerSymbol();989    LastSymbol = std::stable_partition(990        SortedSymbols.begin(), SortedSymbols.end(),991        [this](const SymbolInfo &S) { return !BC->isMarker(S.Symbol); });992    if (!SortedSymbols.empty())993      --LastSymbol;994  }995 996  BinaryFunction *PreviousFunction = nullptr;997  unsigned AnonymousId = 0;998 999  const auto SortedSymbolsEnd =1000      LastSymbol == SortedSymbols.end() ? LastSymbol : std::next(LastSymbol);1001  for (auto Iter = SortedSymbols.begin(); Iter != SortedSymbolsEnd; ++Iter) {1002    const SymbolRef &Symbol = Iter->Symbol;1003    const uint64_t SymbolAddress = Iter->Address;1004    const auto SymbolFlags = cantFail(Symbol.getFlags());1005    const SymbolRef::Type SymbolType = cantFail(Symbol.getType());1006 1007    if (SymbolType == SymbolRef::ST_File)1008      continue;1009 1010    StringRef SymName = cantFail(Symbol.getName(), "cannot get symbol name");1011    if (SymbolAddress == 0) {1012      if (opts::Verbosity >= 1 && SymbolType == SymbolRef::ST_Function)1013        BC->errs() << "BOLT-WARNING: function with 0 address seen\n";1014      continue;1015    }1016 1017    // Ignore input hot markers unless in heatmap mode1018    if ((SymName == "__hot_start" || SymName == "__hot_end") &&1019        !opts::HeatmapMode)1020      continue;1021 1022    FileSymRefs.emplace(SymbolAddress, Symbol);1023 1024    // Skip section symbols that will be registered by disassemblePLT().1025    if (SymbolType == SymbolRef::ST_Debug) {1026      ErrorOr<BinarySection &> BSection =1027          BC->getSectionForAddress(SymbolAddress);1028      if (BSection && getPLTSectionInfo(BSection->getName()))1029        continue;1030    }1031 1032    /// It is possible we are seeing a globalized local. LLVM might treat it as1033    /// a local if it has a "private global" prefix, e.g. ".L". Thus we have to1034    /// change the prefix to enforce global scope of the symbol.1035    std::string Name =1036        SymName.starts_with(BC->AsmInfo->getPrivateGlobalPrefix())1037            ? "PG" + std::string(SymName)1038            : std::string(SymName);1039 1040    // Disambiguate all local symbols before adding to symbol table.1041    // Since we don't know if we will see a global with the same name,1042    // always modify the local name.1043    //1044    // NOTE: the naming convention for local symbols should match1045    //       the one we use for profile data.1046    std::string UniqueName;1047    std::string AlternativeName;1048    if (Name.empty()) {1049      UniqueName = "ANONYMOUS." + std::to_string(AnonymousId++);1050    } else if (SymbolFlags & SymbolRef::SF_Global) {1051      if (const BinaryData *BD = BC->getBinaryDataByName(Name)) {1052        if (BD->getSize() == ELFSymbolRef(Symbol).getSize() &&1053            BD->getAddress() == SymbolAddress) {1054          if (opts::Verbosity > 1)1055            BC->errs() << "BOLT-WARNING: ignoring duplicate global symbol "1056                       << Name << "\n";1057          // Ignore duplicate entry - possibly a bug in the linker1058          continue;1059        }1060        BC->errs() << "BOLT-ERROR: bad input binary, global symbol \"" << Name1061                   << "\" is not unique\n";1062        exit(1);1063      }1064      UniqueName = Name;1065    } else {1066      // If we have a local file name, we should create 2 variants for the1067      // function name. The reason is that perf profile might have been1068      // collected on a binary that did not have the local file name (e.g. as1069      // a side effect of stripping debug info from the binary):1070      //1071      //   primary:     <function>/<id>1072      //   alternative: <function>/<file>/<id2>1073      //1074      // The <id> field is used for disambiguation of local symbols since there1075      // could be identical function names coming from identical file names1076      // (e.g. from different directories).1077      auto SFI = llvm::upper_bound(FileSymbols, ELFSymbolRef(Symbol));1078      if (SymbolType == SymbolRef::ST_Function && SFI != FileSymbols.begin()) {1079        StringRef FileSymbolName = cantFail(SFI[-1].getName());1080        if (!FileSymbolName.empty())1081          AlternativeName = NR.uniquify(Name + "/" + FileSymbolName.str());1082      }1083 1084      UniqueName = NR.uniquify(Name);1085    }1086 1087    uint64_t SymbolSize = ELFSymbolRef(Symbol).getSize();1088    uint64_t SymbolAlignment = Symbol.getAlignment();1089 1090    auto registerName = [&](uint64_t FinalSize) {1091      // Register names even if it's not a function, e.g. for an entry point.1092      BC->registerNameAtAddress(UniqueName, SymbolAddress, FinalSize,1093                                SymbolAlignment, SymbolFlags);1094      if (!AlternativeName.empty())1095        BC->registerNameAtAddress(AlternativeName, SymbolAddress, FinalSize,1096                                  SymbolAlignment, SymbolFlags);1097    };1098 1099    section_iterator Section =1100        cantFail(Symbol.getSection(), "cannot get symbol section");1101    if (Section == InputFile->section_end()) {1102      // Could be an absolute symbol. Used on RISC-V for __global_pointer$ so we1103      // need to record it to handle relocations against it. For other instances1104      // of absolute symbols, we record for pretty printing.1105      LLVM_DEBUG(if (opts::Verbosity > 1) {1106        dbgs() << "BOLT-INFO: absolute sym " << UniqueName << "\n";1107      });1108      registerName(SymbolSize);1109      continue;1110    }1111 1112    if (SymName == getBOLTReservedStart() || SymName == getBOLTReservedEnd()) {1113      registerName(SymbolSize);1114      continue;1115    }1116 1117    LLVM_DEBUG(dbgs() << "BOLT-DEBUG: considering symbol " << UniqueName1118                      << " for function\n");1119 1120    if (SymbolAddress == Section->getAddress() + Section->getSize()) {1121      assert(SymbolSize == 0 &&1122             "unexpected non-zero sized symbol at end of section");1123      LLVM_DEBUG(1124          dbgs()1125          << "BOLT-DEBUG: rejecting as symbol points to end of its section\n");1126      registerName(SymbolSize);1127      continue;1128    }1129 1130    if (!Section->isText() || Section->isVirtual()) {1131      assert(SymbolType != SymbolRef::ST_Function &&1132             "unexpected function inside non-code section");1133      LLVM_DEBUG(dbgs() << "BOLT-DEBUG: rejecting as symbol is not in code or "1134                           "is in nobits section\n");1135      registerName(SymbolSize);1136      continue;1137    }1138 1139    // Assembly functions could be ST_NONE with 0 size. Check that the1140    // corresponding section is a code section and they are not inside any1141    // other known function to consider them.1142    //1143    // Sometimes assembly functions are not marked as functions and neither are1144    // their local labels. The only way to tell them apart is to look at1145    // symbol scope - global vs local.1146    if (PreviousFunction && SymbolType != SymbolRef::ST_Function) {1147      if (PreviousFunction->containsAddress(SymbolAddress)) {1148        if (PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) {1149          LLVM_DEBUG(dbgs()1150                     << "BOLT-DEBUG: symbol is a function local symbol\n");1151        } else if (SymbolAddress == PreviousFunction->getAddress() &&1152                   !SymbolSize) {1153          LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring symbol as a marker\n");1154        } else if (opts::Verbosity > 1) {1155          BC->errs() << "BOLT-WARNING: symbol " << UniqueName1156                     << " seen in the middle of function " << *PreviousFunction1157                     << ". Could be a new entry.\n";1158        }1159        registerName(SymbolSize);1160        continue;1161      } else if (PreviousFunction->getSize() == 0 &&1162                 PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) {1163        LLVM_DEBUG(dbgs() << "BOLT-DEBUG: symbol is a function local symbol\n");1164        registerName(SymbolSize);1165        continue;1166      }1167    }1168 1169    if (PreviousFunction && PreviousFunction->containsAddress(SymbolAddress) &&1170        PreviousFunction->getAddress() != SymbolAddress) {1171      if (PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) {1172        if (opts::Verbosity >= 1)1173          BC->outs()1174              << "BOLT-INFO: skipping possibly another entry for function "1175              << *PreviousFunction << " : " << UniqueName << '\n';1176        registerName(SymbolSize);1177      } else {1178        BC->outs() << "BOLT-INFO: using " << UniqueName1179                   << " as another entry to "1180                   << "function " << *PreviousFunction << '\n';1181 1182        registerName(0);1183 1184        PreviousFunction->addEntryPointAtOffset(SymbolAddress -1185                                                PreviousFunction->getAddress());1186 1187        // Remove the symbol from FileSymRefs so that we can skip it from1188        // in the future.1189        auto SI = llvm::find_if(1190            llvm::make_range(FileSymRefs.equal_range(SymbolAddress)),1191            [&](auto SymIt) { return SymIt.second == Symbol; });1192        assert(SI != FileSymRefs.end() && "symbol expected to be present");1193        assert(SI->second == Symbol && "wrong symbol found");1194        FileSymRefs.erase(SI);1195      }1196      continue;1197    }1198 1199    // Checkout for conflicts with function data from FDEs.1200    bool IsSimple = true;1201    auto FDEI = CFIRdWrt->getFDEs().lower_bound(SymbolAddress);1202    if (FDEI != CFIRdWrt->getFDEs().end()) {1203      const dwarf::FDE &FDE = *FDEI->second;1204      if (FDEI->first != SymbolAddress) {1205        // There's no matching starting address in FDE. Make sure the previous1206        // FDE does not contain this address.1207        if (FDEI != CFIRdWrt->getFDEs().begin()) {1208          --FDEI;1209          const dwarf::FDE &PrevFDE = *FDEI->second;1210          uint64_t PrevStart = PrevFDE.getInitialLocation();1211          uint64_t PrevLength = PrevFDE.getAddressRange();1212          if (SymbolAddress > PrevStart &&1213              SymbolAddress < PrevStart + PrevLength) {1214            BC->errs() << "BOLT-ERROR: function " << UniqueName1215                       << " is in conflict with FDE ["1216                       << Twine::utohexstr(PrevStart) << ", "1217                       << Twine::utohexstr(PrevStart + PrevLength)1218                       << "). Skipping.\n";1219            IsSimple = false;1220          }1221        }1222      } else if (FDE.getAddressRange() != SymbolSize) {1223        if (SymbolSize) {1224          // Function addresses match but sizes differ.1225          BC->errs() << "BOLT-WARNING: sizes differ for function " << UniqueName1226                     << ". FDE : " << FDE.getAddressRange()1227                     << "; symbol table : " << SymbolSize1228                     << ". Using max size.\n";1229        }1230        SymbolSize = std::max(SymbolSize, FDE.getAddressRange());1231        if (BC->getBinaryDataAtAddress(SymbolAddress)) {1232          BC->setBinaryDataSize(SymbolAddress, SymbolSize);1233        } else {1234          LLVM_DEBUG(dbgs() << "BOLT-DEBUG: No BD @ 0x"1235                            << Twine::utohexstr(SymbolAddress) << "\n");1236        }1237      }1238    }1239 1240    BinaryFunction *BF = nullptr;1241    // Since function may not have yet obtained its real size, do a search1242    // using the list of registered functions instead of calling1243    // getBinaryFunctionAtAddress().1244    auto BFI = BC->getBinaryFunctions().find(SymbolAddress);1245    if (BFI != BC->getBinaryFunctions().end()) {1246      BF = &BFI->second;1247      // Duplicate the function name. Make sure everything matches before we add1248      // an alternative name.1249      if (SymbolSize != BF->getSize()) {1250        if (opts::Verbosity >= 1) {1251          if (SymbolSize && BF->getSize())1252            BC->errs() << "BOLT-WARNING: size mismatch for duplicate entries "1253                       << *BF << " and " << UniqueName << '\n';1254          BC->outs() << "BOLT-INFO: adjusting size of function " << *BF1255                     << " old " << BF->getSize() << " new " << SymbolSize1256                     << "\n";1257        }1258        BF->setSize(std::max(SymbolSize, BF->getSize()));1259        BC->setBinaryDataSize(SymbolAddress, BF->getSize());1260      }1261      BF->addAlternativeName(UniqueName);1262    } else {1263      ErrorOr<BinarySection &> Section =1264          BC->getSectionForAddress(SymbolAddress);1265      // Skip symbols from invalid sections1266      if (!Section) {1267        BC->errs() << "BOLT-WARNING: " << UniqueName << " (0x"1268                   << Twine::utohexstr(SymbolAddress)1269                   << ") does not have any section\n";1270        continue;1271      }1272 1273      // Skip symbols from zero-sized sections.1274      if (!Section->getSize())1275        continue;1276 1277      BF = BC->createBinaryFunction(UniqueName, *Section, SymbolAddress,1278                                    SymbolSize);1279      if (!IsSimple)1280        BF->setSimple(false);1281    }1282 1283    // Check if it's a cold function fragment.1284    if (FunctionFragmentTemplate.match(SymName)) {1285      static bool PrintedWarning = false;1286      if (!PrintedWarning) {1287        PrintedWarning = true;1288        BC->errs() << "BOLT-WARNING: split function detected on input : "1289                   << SymName;1290        if (BC->HasRelocations)1291          BC->errs() << ". The support is limited in relocation mode\n";1292        else1293          BC->errs() << '\n';1294      }1295      BC->HasSplitFunctions = true;1296      BF->IsFragment = true;1297    }1298 1299    if (!AlternativeName.empty())1300      BF->addAlternativeName(AlternativeName);1301 1302    registerName(SymbolSize);1303    PreviousFunction = BF;1304  }1305 1306  // Read dynamic relocation first as their presence affects the way we process1307  // static relocations. E.g. we will ignore a static relocation at an address1308  // that is a subject to dynamic relocation processing.1309  processDynamicRelocations();1310 1311  // Process PLT section.1312  disassemblePLT();1313 1314  // See if we missed any functions marked by FDE.1315  for (const auto &FDEI : CFIRdWrt->getFDEs()) {1316    const uint64_t Address = FDEI.first;1317    const dwarf::FDE *FDE = FDEI.second;1318    const BinaryFunction *BF = BC->getBinaryFunctionAtAddress(Address);1319    if (BF)1320      continue;1321 1322    BF = BC->getBinaryFunctionContainingAddress(Address);1323    if (BF) {1324      BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address)1325                 << ", 0x" << Twine::utohexstr(Address + FDE->getAddressRange())1326                 << ") conflicts with function " << *BF << '\n';1327      continue;1328    }1329 1330    if (opts::Verbosity >= 1)1331      BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address)1332                 << ", 0x" << Twine::utohexstr(Address + FDE->getAddressRange())1333                 << ") has no corresponding symbol table entry\n";1334 1335    ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);1336    assert(Section && "cannot get section for address from FDE");1337    std::string FunctionName =1338        "__BOLT_FDE_FUNCat" + Twine::utohexstr(Address).str();1339    BC->createBinaryFunction(FunctionName, *Section, Address,1340                             FDE->getAddressRange());1341  }1342 1343  BC->setHasSymbolsWithFileName(FileSymbols.size());1344 1345  // Now that all the functions were created - adjust their boundaries.1346  adjustFunctionBoundaries(MarkerSymbols);1347 1348  // Annotate functions with code/data markers in AArch641349  for (auto &[Address, Type] : MarkerSymbols) {1350    auto *BF = BC->getBinaryFunctionContainingAddress(Address,1351                                                      /*CheckPastEnd*/ false,1352                                                      /*UseMaxSize*/ true);1353 1354    if (!BF) {1355      // Stray marker1356      continue;1357    }1358    const auto EntryOffset = Address - BF->getAddress();1359    if (Type == MarkerSymType::CODE) {1360      BF->markCodeAtOffset(EntryOffset);1361      continue;1362    }1363    if (Type == MarkerSymType::DATA) {1364      BF->markDataAtOffset(EntryOffset);1365      BC->AddressToConstantIslandMap[Address] = BF;1366      continue;1367    }1368    llvm_unreachable("Unknown marker");1369  }1370 1371  if (BC->isAArch64()) {1372    // Check for dynamic relocations that might be contained in1373    // constant islands.1374    for (const BinarySection &Section : BC->allocatableSections()) {1375      const uint64_t SectionAddress = Section.getAddress();1376      for (const Relocation &Rel : Section.dynamicRelocations()) {1377        const uint64_t RelAddress = SectionAddress + Rel.Offset;1378        BinaryFunction *BF =1379            BC->getBinaryFunctionContainingAddress(RelAddress,1380                                                   /*CheckPastEnd*/ false,1381                                                   /*UseMaxSize*/ true);1382        if (BF) {1383          assert(Rel.isRelative() && "Expected relative relocation for island");1384          BC->logBOLTErrorsAndQuitOnFatal(1385              BF->markIslandDynamicRelocationAtAddress(RelAddress));1386        }1387      }1388    }1389 1390    // The linker may omit data markers for absolute long veneers. Introduce1391    // those markers artificially to assist the disassembler.1392    for (BinaryFunction &BF :1393         llvm::make_second_range(BC->getBinaryFunctions())) {1394      if (BF.getOneName().starts_with("__AArch64AbsLongThunk_") &&1395          BF.getSize() == 16 && !BF.getSizeOfDataInCodeAt(8)) {1396        BC->errs() << "BOLT-WARNING: missing data marker detected in veneer "1397                   << BF << '\n';1398        BF.markDataAtOffset(8);1399        BC->AddressToConstantIslandMap[BF.getAddress() + 8] = &BF;1400      }1401    }1402  }1403 1404  if (!BC->IsLinuxKernel) {1405    // Read all relocations now that we have binary functions mapped.1406    processRelocations();1407  }1408 1409  registerFragments();1410  FileSymbols.clear();1411  FileSymRefs.clear();1412 1413  discoverBOLTReserved();1414}1415 1416void RewriteInstance::discoverBOLTReserved() {1417  BinaryData *StartBD = BC->getBinaryDataByName(getBOLTReservedStart());1418  BinaryData *EndBD = BC->getBinaryDataByName(getBOLTReservedEnd());1419  if (!StartBD != !EndBD) {1420    BC->errs() << "BOLT-ERROR: one of the symbols is missing from the binary: "1421               << getBOLTReservedStart() << ", " << getBOLTReservedEnd()1422               << '\n';1423    exit(1);1424  }1425 1426  if (!StartBD)1427    return;1428 1429  if (StartBD->getAddress() >= EndBD->getAddress()) {1430    BC->errs() << "BOLT-ERROR: invalid reserved space boundaries\n";1431    exit(1);1432  }1433  BC->BOLTReserved = AddressRange(StartBD->getAddress(), EndBD->getAddress());1434  BC->outs() << "BOLT-INFO: using reserved space for allocating new sections\n";1435 1436  PHDRTableOffset = 0;1437  PHDRTableAddress = 0;1438  NewTextSegmentAddress = 0;1439  NewTextSegmentOffset = 0;1440  NextAvailableAddress = BC->BOLTReserved.start();1441}1442 1443Error RewriteInstance::discoverRtInitAddress() {1444  if (BC->HasInterpHeader && opts::RuntimeLibInitHook == opts::RLIH_ENTRY_POINT)1445    return Error::success();1446 1447  // Use DT_INIT if it's available.1448  if (BC->InitAddress && opts::RuntimeLibInitHook <= opts::RLIH_INIT) {1449    BC->StartFunctionAddress = BC->InitAddress;1450    return Error::success();1451  }1452 1453  if (!BC->InitArrayAddress || !BC->InitArraySize) {1454    return createStringError(std::errc::not_supported,1455                             "Instrumentation of shared library needs either "1456                             "DT_INIT or DT_INIT_ARRAY");1457  }1458 1459  if (*BC->InitArraySize < BC->AsmInfo->getCodePointerSize()) {1460    return createStringError(std::errc::not_supported,1461                             "Need at least 1 DT_INIT_ARRAY slot");1462  }1463 1464  ErrorOr<BinarySection &> InitArraySection =1465      BC->getSectionForAddress(*BC->InitArrayAddress);1466  if (auto EC = InitArraySection.getError())1467    return errorCodeToError(EC);1468 1469  if (InitArraySection->getAddress() != *BC->InitArrayAddress) {1470    return createStringError(std::errc::not_supported,1471                             "Inconsistent address of .init_array section");1472  }1473 1474  if (const Relocation *Reloc = InitArraySection->getDynamicRelocationAt(0)) {1475    if (Reloc->isRelative()) {1476      BC->StartFunctionAddress = Reloc->Addend;1477    } else {1478      MCSymbol *Sym = Reloc->Symbol;1479      if (!Sym)1480        return createStringError(1481            std::errc::not_supported,1482            "Failed to locate symbol for 0 entry of .init_array");1483      const BinaryFunction *BF = BC->getFunctionForSymbol(Sym);1484      if (!BF)1485        return createStringError(1486            std::errc::not_supported,1487            "Failed to locate binary function for 0 entry of .init_array");1488      BC->StartFunctionAddress = BF->getAddress() + Reloc->Addend;1489    }1490    return Error::success();1491  }1492 1493  if (const Relocation *Reloc = InitArraySection->getRelocationAt(0)) {1494    BC->StartFunctionAddress = Reloc->Value;1495    return Error::success();1496  }1497 1498  return createStringError(std::errc::not_supported,1499                           "No relocation for first DT_INIT_ARRAY slot");1500}1501 1502Error RewriteInstance::discoverRtFiniAddress() {1503  // Use DT_FINI if it's available.1504  if (BC->FiniAddress) {1505    BC->FiniFunctionAddress = BC->FiniAddress;1506    return Error::success();1507  }1508 1509  if (!BC->FiniArrayAddress || !BC->FiniArraySize) {1510    return createStringError(1511        std::errc::not_supported,1512        "Instrumentation needs either DT_FINI or DT_FINI_ARRAY");1513  }1514 1515  if (*BC->FiniArraySize < BC->AsmInfo->getCodePointerSize()) {1516    return createStringError(std::errc::not_supported,1517                             "Need at least 1 DT_FINI_ARRAY slot");1518  }1519 1520  ErrorOr<BinarySection &> FiniArraySection =1521      BC->getSectionForAddress(*BC->FiniArrayAddress);1522  if (auto EC = FiniArraySection.getError())1523    return errorCodeToError(EC);1524 1525  if (FiniArraySection->getAddress() != *BC->FiniArrayAddress) {1526    return createStringError(std::errc::not_supported,1527                             "Inconsistent address of .fini_array section");1528  }1529 1530  if (const Relocation *Reloc = FiniArraySection->getDynamicRelocationAt(0)) {1531    BC->FiniFunctionAddress = Reloc->Addend;1532    return Error::success();1533  }1534 1535  if (const Relocation *Reloc = FiniArraySection->getRelocationAt(0)) {1536    BC->FiniFunctionAddress = Reloc->Value;1537    return Error::success();1538  }1539 1540  return createStringError(std::errc::not_supported,1541                           "No relocation for first DT_FINI_ARRAY slot");1542}1543 1544Error RewriteInstance::updateRtInitReloc() {1545  if (BC->HasInterpHeader && opts::RuntimeLibInitHook == opts::RLIH_ENTRY_POINT)1546    return Error::success();1547 1548  // Updating DT_INIT is handled by patchELFDynamic.1549  if (BC->InitAddress && opts::RuntimeLibInitHook <= opts::RLIH_INIT)1550    return Error::success();1551 1552  const RuntimeLibrary *RT = BC->getRuntimeLibrary();1553  if (!RT || !RT->getRuntimeStartAddress())1554    return Error::success();1555 1556  if (!BC->InitArrayAddress)1557    return Error::success();1558 1559  if (!BC->InitArrayAddress || !BC->InitArraySize)1560    return createStringError(std::errc::not_supported,1561                             "inconsistent .init_array state");1562 1563  ErrorOr<BinarySection &> InitArraySection =1564      BC->getSectionForAddress(*BC->InitArrayAddress);1565  if (!InitArraySection)1566    return createStringError(std::errc::not_supported, ".init_array removed");1567 1568  if (std::optional<Relocation> Reloc =1569          InitArraySection->takeDynamicRelocationAt(0)) {1570    if (Reloc->isRelative()) {1571      if (Reloc->Addend != BC->StartFunctionAddress)1572        return createStringError(std::errc::not_supported,1573                                 "inconsistent .init_array dynamic relocation");1574      Reloc->Addend = RT->getRuntimeStartAddress();1575      InitArraySection->addDynamicRelocation(*Reloc);1576    } else {1577      MCSymbol *Sym = Reloc->Symbol;1578      if (!Sym)1579        return createStringError(1580            std::errc::not_supported,1581            "Failed to locate symbol for 0 entry of .init_array");1582      const BinaryFunction *BF = BC->getFunctionForSymbol(Sym);1583      if (!BF)1584        return createStringError(1585            std::errc::not_supported,1586            "Failed to locate binary function for 0 entry of .init_array");1587      if (BF->getAddress() + Reloc->Addend != BC->StartFunctionAddress)1588        return createStringError(std::errc::not_supported,1589                                 "inconsistent .init_array dynamic relocation");1590      InitArraySection->addDynamicRelocation(Relocation{1591          /*Offset*/ 0, /*Symbol*/ nullptr, /*Type*/ Relocation::getAbs64(),1592          /*Addend*/ RT->getRuntimeStartAddress(), /*Value*/ 0});1593    }1594  }1595  // Update the static relocation by adding a pending relocation which will get1596  // patched when flushPendingRelocations is called in rewriteFile. Note that1597  // flushPendingRelocations will calculate the value to patch as1598  // "Symbol + Addend". Since we don't have a symbol, just set the addend to the1599  // desired value.1600  InitArraySection->addPendingRelocation(Relocation{1601      /*Offset*/ 0, /*Symbol*/ nullptr, /*Type*/ Relocation::getAbs64(),1602      /*Addend*/ RT->getRuntimeStartAddress(), /*Value*/ 0});1603  BC->outs()1604      << "BOLT-INFO: runtime library initialization was hooked via .init_array "1605         "entry, set to 0x"1606      << Twine::utohexstr(RT->getRuntimeStartAddress()) << "\n";1607  return Error::success();1608}1609 1610Error RewriteInstance::updateRtFiniReloc() {1611  // Updating DT_FINI is handled by patchELFDynamic.1612  if (BC->FiniAddress)1613    return Error::success();1614 1615  const RuntimeLibrary *RT = BC->getRuntimeLibrary();1616  if (!RT || !RT->getRuntimeFiniAddress())1617    return Error::success();1618 1619  if (!BC->FiniArrayAddress || !BC->FiniArraySize)1620    return createStringError(std::errc::not_supported,1621                             "inconsistent .fini_array state");1622 1623  ErrorOr<BinarySection &> FiniArraySection =1624      BC->getSectionForAddress(*BC->FiniArrayAddress);1625  if (!FiniArraySection)1626    return createStringError(std::errc::not_supported, ".fini_array removed");1627 1628  if (std::optional<Relocation> Reloc =1629          FiniArraySection->takeDynamicRelocationAt(0)) {1630    if (Reloc->Addend != BC->FiniFunctionAddress)1631      return createStringError(std::errc::not_supported,1632                               "inconsistent .fini_array dynamic relocation");1633    Reloc->Addend = RT->getRuntimeFiniAddress();1634    FiniArraySection->addDynamicRelocation(*Reloc);1635  }1636 1637  // Update the static relocation by adding a pending relocation which will get1638  // patched when flushPendingRelocations is called in rewriteFile. Note that1639  // flushPendingRelocations will calculate the value to patch as1640  // "Symbol + Addend". Since we don't have a symbol, just set the addend to the1641  // desired value.1642  FiniArraySection->addPendingRelocation(Relocation{1643      /*Offset*/ 0, /*Symbol*/ nullptr, /*Type*/ Relocation::getAbs64(),1644      /*Addend*/ RT->getRuntimeFiniAddress(), /*Value*/ 0});1645  BC->outs() << "BOLT-INFO: runtime library finalization was hooked via "1646                ".fini_array entry, set to 0x"1647             << Twine::utohexstr(RT->getRuntimeFiniAddress()) << "\n";1648  return Error::success();1649}1650 1651void RewriteInstance::registerFragments() {1652  if (!BC->HasSplitFunctions ||1653      opts::HeatmapMode == opts::HeatmapModeKind::HM_Exclusive)1654    return;1655 1656  // Process fragments with ambiguous parents separately as they are typically a1657  // vanishing minority of cases and require expensive symbol table lookups.1658  std::vector<std::pair<StringRef, BinaryFunction *>> AmbiguousFragments;1659  for (auto &BFI : BC->getBinaryFunctions()) {1660    BinaryFunction &Function = BFI.second;1661    if (!Function.isFragment())1662      continue;1663    for (StringRef Name : Function.getNames()) {1664      StringRef BaseName = NR.restore(Name);1665      const bool IsGlobal = BaseName == Name;1666      SmallVector<StringRef> Matches;1667      if (!FunctionFragmentTemplate.match(BaseName, &Matches))1668        continue;1669      StringRef ParentName = Matches[1];1670      const BinaryData *BD = BC->getBinaryDataByName(ParentName);1671      const uint64_t NumPossibleLocalParents =1672          NR.getUniquifiedNameCount(ParentName);1673      // The most common case: single local parent fragment.1674      if (!BD && NumPossibleLocalParents == 1) {1675        BD = BC->getBinaryDataByName(NR.getUniqueName(ParentName, 1));1676      } else if (BD && (!NumPossibleLocalParents || IsGlobal)) {1677        // Global parent and either no local candidates (second most common), or1678        // the fragment is global as well (uncommon).1679      } else {1680        // Any other case: need to disambiguate using FILE symbols.1681        AmbiguousFragments.emplace_back(ParentName, &Function);1682        continue;1683      }1684      if (BD) {1685        BinaryFunction *BF = BC->getFunctionForSymbol(BD->getSymbol());1686        if (BF == &Function) {1687          BC->errs()1688              << "BOLT-WARNING: fragment maps to the same function as parent: "1689              << Function << '\n';1690          continue;1691        }1692        if (BF) {1693          BC->registerFragment(Function, *BF);1694          continue;1695        }1696      }1697      BC->errs() << "BOLT-ERROR: parent function not found for " << Function1698                 << '\n';1699      exit(1);1700    }1701  }1702 1703  if (AmbiguousFragments.empty())1704    return;1705 1706  if (!BC->hasSymbolsWithFileName()) {1707    BC->errs() << "BOLT-ERROR: input file has split functions but does not "1708                  "have FILE symbols. If the binary was stripped, preserve "1709                  "FILE symbols with --keep-file-symbols strip option\n";1710    exit(1);1711  }1712 1713  // The first global symbol is identified by the symbol table sh_info value.1714  // Used as local symbol search stopping point.1715  auto *ELF64LEFile = cast<ELF64LEObjectFile>(InputFile);1716  const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();1717  auto *SymTab = llvm::find_if(cantFail(Obj.sections()), [](const auto &Sec) {1718    return Sec.sh_type == ELF::SHT_SYMTAB;1719  });1720  assert(SymTab);1721  // Symtab sh_info contains the value one greater than the symbol table index1722  // of the last local symbol.1723  ELFSymbolRef LocalSymEnd = ELF64LEFile->toSymbolRef(SymTab, SymTab->sh_info);1724 1725  for (auto &Fragment : AmbiguousFragments) {1726    const StringRef &ParentName = Fragment.first;1727    BinaryFunction *BF = Fragment.second;1728    const uint64_t Address = BF->getAddress();1729 1730    // Get fragment's own symbol1731    const auto SymIt = llvm::find_if(1732        llvm::make_range(FileSymRefs.equal_range(Address)), [&](auto SI) {1733          StringRef Name = cantFail(SI.second.getName());1734          return Name.contains(ParentName);1735        });1736    if (SymIt == FileSymRefs.end()) {1737      BC->errs()1738          << "BOLT-ERROR: symbol lookup failed for function at address 0x"1739          << Twine::utohexstr(Address) << '\n';1740      exit(1);1741    }1742 1743    // Find containing FILE symbol1744    ELFSymbolRef Symbol = SymIt->second;1745    auto FSI = llvm::upper_bound(FileSymbols, Symbol);1746    if (FSI == FileSymbols.begin()) {1747      BC->errs() << "BOLT-ERROR: owning FILE symbol not found for symbol "1748                 << cantFail(Symbol.getName()) << '\n';1749      exit(1);1750    }1751 1752    ELFSymbolRef StopSymbol = LocalSymEnd;1753    if (FSI != FileSymbols.end())1754      StopSymbol = *FSI;1755 1756    uint64_t ParentAddress{0};1757 1758    // Check if containing FILE symbol is BOLT emitted synthetic symbol marking1759    // local fragments of global parents.1760    if (cantFail(FSI[-1].getName()) == getBOLTFileSymbolName())1761      goto registerParent;1762 1763    // BOLT split fragment symbols are emitted just before the main function1764    // symbol.1765    for (ELFSymbolRef NextSymbol = Symbol; NextSymbol < StopSymbol;1766         NextSymbol.moveNext()) {1767      StringRef Name = cantFail(NextSymbol.getName());1768      if (Name == ParentName) {1769        ParentAddress = cantFail(NextSymbol.getValue());1770        goto registerParent;1771      }1772      if (Name.starts_with(ParentName))1773        // With multi-way splitting, there are multiple fragments with different1774        // suffixes. Parent follows the last fragment.1775        continue;1776      break;1777    }1778 1779    // Iterate over local file symbols and check symbol names to match parent.1780    for (ELFSymbolRef Symbol(FSI[-1]); Symbol < StopSymbol; Symbol.moveNext()) {1781      if (cantFail(Symbol.getName()) == ParentName) {1782        ParentAddress = cantFail(Symbol.getAddress());1783        break;1784      }1785    }1786 1787registerParent:1788    // No local parent is found, use global parent function.1789    if (!ParentAddress)1790      if (BinaryData *ParentBD = BC->getBinaryDataByName(ParentName))1791        ParentAddress = ParentBD->getAddress();1792 1793    if (BinaryFunction *ParentBF =1794            BC->getBinaryFunctionAtAddress(ParentAddress)) {1795      BC->registerFragment(*BF, *ParentBF);1796      continue;1797    }1798    BC->errs() << "BOLT-ERROR: parent function not found for " << *BF << '\n';1799    exit(1);1800  }1801}1802 1803void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,1804                                              uint64_t EntryAddress,1805                                              uint64_t EntrySize) {1806  if (!TargetAddress)1807    return;1808 1809  auto setPLTSymbol = [&](BinaryFunction *BF, StringRef Name) {1810    const unsigned PtrSize = BC->AsmInfo->getCodePointerSize();1811    MCSymbol *TargetSymbol = BC->registerNameAtAddress(1812        Name.str() + "@GOT", TargetAddress, PtrSize, PtrSize);1813    BF->setPLTSymbol(TargetSymbol);1814  };1815 1816  BinaryFunction *BF = BC->getBinaryFunctionAtAddress(EntryAddress);1817  if (BF && BC->isAArch64()) {1818    // Handle IFUNC trampoline with symbol1819    setPLTSymbol(BF, BF->getOneName());1820    return;1821  }1822 1823  const Relocation *Rel = BC->getDynamicRelocationAt(TargetAddress);1824  if (!Rel)1825    return;1826 1827  MCSymbol *Symbol = Rel->Symbol;1828  if (!Symbol) {1829    if (BC->isRISCV() || !Rel->Addend || !Rel->isIRelative())1830      return;1831 1832    // IFUNC trampoline without symbol1833    BinaryFunction *TargetBF = BC->getBinaryFunctionAtAddress(Rel->Addend);1834    if (!TargetBF) {1835      BC->errs()1836          << "BOLT-WARNING: Expected BF to be presented as IFUNC resolver at "1837          << Twine::utohexstr(Rel->Addend) << ", skipping\n";1838      return;1839    }1840 1841    Symbol = TargetBF->getSymbol();1842  }1843 1844  ErrorOr<BinarySection &> Section = BC->getSectionForAddress(EntryAddress);1845  assert(Section && "cannot get section for address");1846  if (!BF)1847    BF = BC->createBinaryFunction(Symbol->getName().str() + "@PLT", *Section,1848                                  EntryAddress, 0, EntrySize,1849                                  Section->getAlignment());1850  else1851    BF->addAlternativeName(Symbol->getName().str() + "@PLT");1852  setPLTSymbol(BF, Symbol->getName());1853}1854 1855void RewriteInstance::disassemblePLTInstruction(const BinarySection &Section,1856                                                uint64_t InstrOffset,1857                                                MCInst &Instruction,1858                                                uint64_t &InstrSize) {1859  const uint64_t SectionAddress = Section.getAddress();1860  const uint64_t SectionSize = Section.getSize();1861  StringRef PLTContents = Section.getContents();1862  ArrayRef<uint8_t> PLTData(1863      reinterpret_cast<const uint8_t *>(PLTContents.data()), SectionSize);1864 1865  const uint64_t InstrAddr = SectionAddress + InstrOffset;1866  if (!BC->DisAsm->getInstruction(Instruction, InstrSize,1867                                  PLTData.slice(InstrOffset), InstrAddr,1868                                  nulls())) {1869    BC->errs()1870        << "BOLT-ERROR: unable to disassemble instruction in PLT section "1871        << Section.getName() << formatv(" at offset {0:x}\n", InstrOffset);1872    exit(1);1873  }1874}1875 1876void RewriteInstance::disassemblePLTSectionAArch64(BinarySection &Section) {1877  const uint64_t SectionAddress = Section.getAddress();1878  const uint64_t SectionSize = Section.getSize();1879 1880  uint64_t InstrOffset = 0;1881  // Locate new plt entry1882  while (InstrOffset < SectionSize) {1883    InstructionListType Instructions;1884    MCInst Instruction;1885    uint64_t EntryOffset = InstrOffset;1886    uint64_t EntrySize = 0;1887    uint64_t InstrSize;1888    // Loop through entry instructions1889    while (InstrOffset < SectionSize) {1890      disassemblePLTInstruction(Section, InstrOffset, Instruction, InstrSize);1891      EntrySize += InstrSize;1892      if (!BC->MIB->isIndirectBranch(Instruction)) {1893        Instructions.emplace_back(Instruction);1894        InstrOffset += InstrSize;1895        continue;1896      }1897 1898      const uint64_t EntryAddress = SectionAddress + EntryOffset;1899      const uint64_t TargetAddress = BC->MIB->analyzePLTEntry(1900          Instruction, Instructions.begin(), Instructions.end(), EntryAddress);1901 1902      createPLTBinaryFunction(TargetAddress, EntryAddress, EntrySize);1903      break;1904    }1905 1906    // Branch instruction1907    InstrOffset += InstrSize;1908 1909    // Skip nops if any1910    while (InstrOffset < SectionSize) {1911      disassemblePLTInstruction(Section, InstrOffset, Instruction, InstrSize);1912      if (!BC->MIB->isNoop(Instruction))1913        break;1914 1915      InstrOffset += InstrSize;1916    }1917  }1918}1919 1920void RewriteInstance::disassemblePLTSectionRISCV(BinarySection &Section) {1921  const uint64_t SectionAddress = Section.getAddress();1922  const uint64_t SectionSize = Section.getSize();1923  StringRef PLTContents = Section.getContents();1924  ArrayRef<uint8_t> PLTData(1925      reinterpret_cast<const uint8_t *>(PLTContents.data()), SectionSize);1926 1927  auto disassembleInstruction = [&](uint64_t InstrOffset, MCInst &Instruction,1928                                    uint64_t &InstrSize) {1929    const uint64_t InstrAddr = SectionAddress + InstrOffset;1930    if (!BC->DisAsm->getInstruction(Instruction, InstrSize,1931                                    PLTData.slice(InstrOffset), InstrAddr,1932                                    nulls())) {1933      BC->errs()1934          << "BOLT-ERROR: unable to disassemble instruction in PLT section "1935          << Section.getName() << " at offset 0x"1936          << Twine::utohexstr(InstrOffset) << '\n';1937      exit(1);1938    }1939  };1940 1941  // Skip the first special entry since no relocation points to it.1942  uint64_t InstrOffset = 32;1943 1944  while (InstrOffset < SectionSize) {1945    InstructionListType Instructions;1946    MCInst Instruction;1947    const uint64_t EntryOffset = InstrOffset;1948    const uint64_t EntrySize = 16;1949    uint64_t InstrSize;1950 1951    while (InstrOffset < EntryOffset + EntrySize) {1952      disassembleInstruction(InstrOffset, Instruction, InstrSize);1953      Instructions.emplace_back(Instruction);1954      InstrOffset += InstrSize;1955    }1956 1957    const uint64_t EntryAddress = SectionAddress + EntryOffset;1958    const uint64_t TargetAddress = BC->MIB->analyzePLTEntry(1959        Instruction, Instructions.begin(), Instructions.end(), EntryAddress);1960 1961    createPLTBinaryFunction(TargetAddress, EntryAddress, EntrySize);1962  }1963}1964 1965void RewriteInstance::disassemblePLTSectionX86(BinarySection &Section,1966                                               uint64_t EntrySize) {1967  const uint64_t SectionAddress = Section.getAddress();1968  const uint64_t SectionSize = Section.getSize();1969 1970  for (uint64_t EntryOffset = 0; EntryOffset + EntrySize <= SectionSize;1971       EntryOffset += EntrySize) {1972    MCInst Instruction;1973    uint64_t InstrSize, InstrOffset = EntryOffset;1974    while (InstrOffset < EntryOffset + EntrySize) {1975      disassemblePLTInstruction(Section, InstrOffset, Instruction, InstrSize);1976      // Check if the entry size needs adjustment.1977      if (EntryOffset == 0 && BC->MIB->isTerminateBranch(Instruction) &&1978          EntrySize == 8)1979        EntrySize = 16;1980 1981      if (BC->MIB->isIndirectBranch(Instruction))1982        break;1983 1984      InstrOffset += InstrSize;1985    }1986 1987    if (InstrOffset + InstrSize > EntryOffset + EntrySize)1988      continue;1989 1990    uint64_t TargetAddress;1991    if (!BC->MIB->evaluateMemOperandTarget(Instruction, TargetAddress,1992                                           SectionAddress + InstrOffset,1993                                           InstrSize)) {1994      BC->errs() << "BOLT-ERROR: error evaluating PLT instruction at offset 0x"1995                 << Twine::utohexstr(SectionAddress + InstrOffset) << '\n';1996      exit(1);1997    }1998 1999    createPLTBinaryFunction(TargetAddress, SectionAddress + EntryOffset,2000                            EntrySize);2001  }2002}2003 2004void RewriteInstance::disassemblePLT() {2005  auto analyzeOnePLTSection = [&](BinarySection &Section, uint64_t EntrySize) {2006    if (BC->isAArch64())2007      return disassemblePLTSectionAArch64(Section);2008    if (BC->isRISCV())2009      return disassemblePLTSectionRISCV(Section);2010    if (BC->isX86())2011      return disassemblePLTSectionX86(Section, EntrySize);2012    llvm_unreachable("Unmplemented PLT");2013  };2014 2015  for (BinarySection &Section : BC->allocatableSections()) {2016    const PLTSectionInfo *PLTSI = getPLTSectionInfo(Section.getName());2017    if (!PLTSI)2018      continue;2019 2020    analyzeOnePLTSection(Section, PLTSI->EntrySize);2021 2022    BinaryFunction *PltBF;2023    auto BFIter = BC->getBinaryFunctions().find(Section.getAddress());2024    if (BFIter != BC->getBinaryFunctions().end()) {2025      PltBF = &BFIter->second;2026    } else {2027      // If we did not register any function at the start of the section,2028      // then it must be a general PLT entry. Add a function at the location.2029      PltBF = BC->createBinaryFunction(2030          "__BOLT_PSEUDO_" + Section.getName().str(), Section,2031          Section.getAddress(), 0, PLTSI->EntrySize, Section.getAlignment());2032    }2033    PltBF->setPseudo(true);2034  }2035}2036 2037void RewriteInstance::adjustFunctionBoundaries(2038    DenseMap<uint64_t, MarkerSymType> &MarkerSyms) {2039  for (auto BFI = BC->getBinaryFunctions().begin(),2040            BFE = BC->getBinaryFunctions().end();2041       BFI != BFE; ++BFI) {2042    BinaryFunction &Function = BFI->second;2043    const BinaryFunction *NextFunction = nullptr;2044    if (std::next(BFI) != BFE)2045      NextFunction = &std::next(BFI)->second;2046 2047    // Check if there's a symbol or a function with a larger address in the2048    // same section. If there is - it determines the maximum size for the2049    // current function. Otherwise, it is the size of a containing section2050    // the defines it.2051    //2052    // NOTE: ignore some symbols that could be tolerated inside the body2053    //       of a function.2054    auto NextSymRefI = FileSymRefs.upper_bound(Function.getAddress());2055    while (NextSymRefI != FileSymRefs.end()) {2056      SymbolRef &Symbol = NextSymRefI->second;2057      const uint64_t SymbolAddress = NextSymRefI->first;2058      const uint64_t SymbolSize = ELFSymbolRef(Symbol).getSize();2059 2060      if (NextFunction && SymbolAddress >= NextFunction->getAddress())2061        break;2062 2063      if (!Function.isSymbolValidInScope(Symbol, SymbolSize))2064        break;2065 2066      // Skip basic block labels. This happens on RISC-V with linker relaxation2067      // enabled because every branch needs a relocation and corresponding2068      // symbol. We don't want to add such symbols as entry points.2069      const auto PrivateLabelPrefix = BC->AsmInfo->getPrivateLabelPrefix();2070      if (!PrivateLabelPrefix.empty() &&2071          cantFail(Symbol.getName()).starts_with(PrivateLabelPrefix)) {2072        ++NextSymRefI;2073        continue;2074      }2075 2076      auto It = MarkerSyms.find(NextSymRefI->first);2077      if (It == MarkerSyms.end() || It->second != MarkerSymType::DATA) {2078        // This is potentially another entry point into the function.2079        uint64_t EntryOffset = NextSymRefI->first - Function.getAddress();2080        LLVM_DEBUG(dbgs() << "BOLT-DEBUG: adding entry point to function "2081                          << Function << " at offset 0x"2082                          << Twine::utohexstr(EntryOffset) << '\n');2083        Function.addEntryPointAtOffset(EntryOffset);2084      }2085 2086      ++NextSymRefI;2087    }2088 2089    // Function runs at most till the end of the containing section.2090    uint64_t NextObjectAddress = Function.getOriginSection()->getEndAddress();2091    // Or till the next object marked by a symbol.2092    if (NextSymRefI != FileSymRefs.end())2093      NextObjectAddress = std::min(NextSymRefI->first, NextObjectAddress);2094 2095    // Or till the next function not marked by a symbol.2096    if (NextFunction)2097      NextObjectAddress =2098          std::min(NextFunction->getAddress(), NextObjectAddress);2099 2100    const uint64_t MaxSize = NextObjectAddress - Function.getAddress();2101    if (MaxSize < Function.getSize()) {2102      BC->errs() << "BOLT-ERROR: symbol seen in the middle of the function "2103                 << Function << ". Skipping.\n";2104      Function.setSimple(false);2105      Function.setMaxSize(Function.getSize());2106      continue;2107    }2108    Function.setMaxSize(MaxSize);2109    if (!Function.getSize() && Function.isSimple()) {2110      // Some assembly functions have their size set to 0, use the max2111      // size as their real size.2112      if (opts::Verbosity >= 1)2113        BC->outs() << "BOLT-INFO: setting size of function " << Function2114                   << " to " << Function.getMaxSize() << " (was 0)\n";2115      Function.setSize(Function.getMaxSize());2116    }2117  }2118}2119 2120void RewriteInstance::relocateEHFrameSection() {2121  assert(EHFrameSection && "Non-empty .eh_frame section expected.");2122 2123  BinarySection *RelocatedEHFrameSection =2124      getSection(".relocated" + getEHFrameSectionName());2125  assert(RelocatedEHFrameSection &&2126         "Relocated eh_frame section should be preregistered.");2127  DWARFDataExtractor DE(EHFrameSection->getContents(),2128                        BC->AsmInfo->isLittleEndian(),2129                        BC->AsmInfo->getCodePointerSize());2130  auto createReloc = [&](uint64_t Value, uint64_t Offset, uint64_t DwarfType) {2131    if (DwarfType == dwarf::DW_EH_PE_omit)2132      return;2133 2134    // Only fix references that are relative to other locations.2135    if (!(DwarfType & dwarf::DW_EH_PE_pcrel) &&2136        !(DwarfType & dwarf::DW_EH_PE_textrel) &&2137        !(DwarfType & dwarf::DW_EH_PE_funcrel) &&2138        !(DwarfType & dwarf::DW_EH_PE_datarel))2139      return;2140 2141    if (!(DwarfType & dwarf::DW_EH_PE_sdata4))2142      return;2143 2144    uint32_t RelType;2145    switch (DwarfType & 0x0f) {2146    default:2147      llvm_unreachable("unsupported DWARF encoding type");2148    case dwarf::DW_EH_PE_sdata4:2149    case dwarf::DW_EH_PE_udata4:2150      RelType = Relocation::getPC32();2151      Offset -= 4;2152      break;2153    case dwarf::DW_EH_PE_sdata8:2154    case dwarf::DW_EH_PE_udata8:2155      RelType = Relocation::getPC64();2156      Offset -= 8;2157      break;2158    }2159 2160    // Create a relocation against an absolute value since the goal is to2161    // preserve the contents of the section independent of the new values2162    // of referenced symbols.2163    RelocatedEHFrameSection->addRelocation(Offset, nullptr, RelType, Value);2164  };2165 2166  Error E = EHFrameParser::parse(DE, EHFrameSection->getAddress(), createReloc);2167  check_error(std::move(E), "failed to patch EH frame");2168}2169 2170Error RewriteInstance::readSpecialSections() {2171  NamedRegionTimer T("readSpecialSections", "read special sections",2172                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);2173 2174  bool HasTextRelocations = false;2175  bool HasSymbolTable = false;2176  bool HasDebugInfo = false;2177 2178  // Process special sections.2179  for (const SectionRef &Section : InputFile->sections()) {2180    Expected<StringRef> SectionNameOrErr = Section.getName();2181    check_error(SectionNameOrErr.takeError(), "cannot get section name");2182    StringRef SectionName = *SectionNameOrErr;2183 2184    if (Error E = Section.getContents().takeError())2185      return E;2186    BC->registerSection(Section);2187    LLVM_DEBUG(2188        dbgs() << "BOLT-DEBUG: registering section " << SectionName << " @ 0x"2189               << Twine::utohexstr(Section.getAddress()) << ":0x"2190               << Twine::utohexstr(Section.getAddress() + Section.getSize())2191               << "\n");2192    if (isDebugSection(SectionName))2193      HasDebugInfo = true;2194  }2195 2196  // Set IsRelro section attribute based on PT_GNU_RELRO segment.2197  markGnuRelroSections();2198 2199  if (HasDebugInfo && !opts::UpdateDebugSections && !opts::AggregateOnly) {2200    BC->errs() << "BOLT-WARNING: debug info will be stripped from the binary. "2201                  "Use -update-debug-sections to keep it.\n";2202  }2203 2204  HasTextRelocations = (bool)BC->getUniqueSectionByName(2205      ".rela" + std::string(BC->getMainCodeSectionName()));2206  HasSymbolTable = (bool)BC->getUniqueSectionByName(".symtab");2207  EHFrameSection = BC->getUniqueSectionByName(".eh_frame");2208 2209  if (ErrorOr<BinarySection &> BATSec =2210          BC->getUniqueSectionByName(BoltAddressTranslation::SECTION_NAME)) {2211    BC->HasBATSection = true;2212    // Do not read BAT when plotting a heatmap2213    if (opts::HeatmapMode != opts::HeatmapModeKind::HM_Exclusive) {2214      if (std::error_code EC = BAT->parse(BC->outs(), BATSec->getContents())) {2215        BC->errs() << "BOLT-ERROR: failed to parse BOLT address translation "2216                      "table.\n";2217        exit(1);2218      }2219    }2220  }2221 2222  if (opts::PrintSections) {2223    BC->outs() << "BOLT-INFO: Sections from original binary:\n";2224    BC->printSections(BC->outs());2225  }2226 2227  if (opts::RelocationMode == cl::BOU_TRUE && !HasTextRelocations) {2228    BC->errs()2229        << "BOLT-ERROR: relocations against code are missing from the input "2230           "file. Cannot proceed in relocations mode (-relocs).\n";2231    exit(1);2232  }2233 2234  BC->HasRelocations =2235      HasTextRelocations && (opts::RelocationMode != cl::BOU_FALSE);2236 2237  if (BC->IsLinuxKernel && BC->HasRelocations) {2238    BC->outs() << "BOLT-INFO: disabling relocation mode for Linux kernel\n";2239    BC->HasRelocations = false;2240  }2241 2242  BC->IsStripped = !HasSymbolTable;2243 2244  if (BC->IsStripped && !opts::AllowStripped) {2245    BC->errs()2246        << "BOLT-ERROR: stripped binaries are not supported. If you know "2247           "what you're doing, use --allow-stripped to proceed\n";2248    exit(1);2249  }2250 2251  // Force non-relocation mode for heatmap generation2252  if (opts::HeatmapMode == opts::HeatmapModeKind::HM_Exclusive)2253    BC->HasRelocations = false;2254 2255  if (BC->HasRelocations)2256    BC->outs() << "BOLT-INFO: enabling " << (opts::StrictMode ? "strict " : "")2257               << "relocation mode\n";2258 2259  // Read EH frame for function boundaries info.2260  Expected<const DWARFDebugFrame *> EHFrameOrError = BC->DwCtx->getEHFrame();2261  if (!EHFrameOrError)2262    report_error("expected valid eh_frame section", EHFrameOrError.takeError());2263  CFIRdWrt.reset(new CFIReaderWriter(*BC, *EHFrameOrError.get()));2264 2265  processSectionMetadata();2266 2267  // Read .dynamic/PT_DYNAMIC.2268  return readELFDynamic();2269}2270 2271void RewriteInstance::adjustCommandLineOptions() {2272  if (BC->isAArch64() && !BC->HasRelocations)2273    BC->errs() << "BOLT-WARNING: non-relocation mode for AArch64 is not fully "2274                  "supported\n";2275 2276  if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary())2277    RtLibrary->adjustCommandLineOptions(*BC);2278 2279  if (BC->isX86() && BC->MAB->allowAutoPadding()) {2280    if (!BC->HasRelocations) {2281      BC->errs()2282          << "BOLT-ERROR: cannot apply mitigations for Intel JCC erratum in "2283             "non-relocation mode\n";2284      exit(1);2285    }2286    BC->outs()2287        << "BOLT-WARNING: using mitigation for Intel JCC erratum, layout "2288           "may take several minutes\n";2289  }2290 2291  if (opts::SplitEH && !BC->HasRelocations) {2292    BC->errs() << "BOLT-WARNING: disabling -split-eh in non-relocation mode\n";2293    opts::SplitEH = false;2294  }2295 2296  if (BC->isAArch64() && !opts::CompactCodeModel &&2297      opts::SplitStrategy == opts::SplitFunctionsStrategy::CDSplit) {2298    BC->errs() << "BOLT-ERROR: CDSplit is not supported with LongJmp. Try with "2299                  "'--compact-code-model'\n";2300    exit(1);2301  }2302 2303  if (opts::StrictMode && !BC->HasRelocations) {2304    BC->errs()2305        << "BOLT-WARNING: disabling strict mode (-strict) in non-relocation "2306           "mode\n";2307    opts::StrictMode = false;2308  }2309 2310  if (BC->HasRelocations && opts::AggregateOnly &&2311      !opts::StrictMode.getNumOccurrences()) {2312    BC->outs() << "BOLT-INFO: enabling strict relocation mode for aggregation "2313                  "purposes\n";2314    opts::StrictMode = true;2315  }2316 2317  if (!BC->HasRelocations &&2318      opts::ReorderFunctions != ReorderFunctions::RT_NONE) {2319    BC->errs() << "BOLT-ERROR: function reordering only works when "2320               << "relocations are enabled\n";2321    exit(1);2322  }2323 2324  if (!BC->HasRelocations &&2325      opts::ICF == IdenticalCodeFolding::ICFLevel::Safe) {2326    BC->errs() << "BOLT-ERROR: binary built without relocations. Safe ICF is "2327                  "not supported\n";2328    exit(1);2329  }2330 2331  if (opts::Instrument ||2332      (opts::ReorderFunctions != ReorderFunctions::RT_NONE &&2333       !opts::HotText.getNumOccurrences())) {2334    opts::HotText = true;2335  } else if (opts::HotText && !BC->HasRelocations) {2336    BC->errs() << "BOLT-WARNING: hot text is disabled in non-relocation mode\n";2337    opts::HotText = false;2338  }2339 2340  if (opts::Instrument && opts::UseGnuStack) {2341    BC->errs() << "BOLT-ERROR: cannot avoid having writeable and executable "2342                  "segment in instrumented binary if program headers will be "2343                  "updated in place\n";2344    exit(1);2345  }2346 2347  if (opts::Instrument && opts::RuntimeLibInitHook == opts::RLIH_ENTRY_POINT &&2348      !BC->HasInterpHeader) {2349    BC->errs()2350        << "BOLT-WARNING: adjusted runtime-lib-init-hook to 'init' due to "2351           "absence of INTERP header\n";2352    opts::RuntimeLibInitHook = opts::RLIH_INIT;2353  }2354 2355  if (opts::HotText && opts::HotTextMoveSections.getNumOccurrences() == 0) {2356    opts::HotTextMoveSections.addValue(".stub");2357    opts::HotTextMoveSections.addValue(".mover");2358    opts::HotTextMoveSections.addValue(".never_hugify");2359  }2360 2361  if (opts::UseOldText && !BC->OldTextSectionAddress) {2362    BC->errs()2363        << "BOLT-WARNING: cannot use old .text as the section was not found"2364           "\n";2365    opts::UseOldText = false;2366  }2367  if (opts::UseOldText && !BC->HasRelocations) {2368    BC->errs() << "BOLT-WARNING: cannot use old .text in non-relocation mode\n";2369    opts::UseOldText = false;2370  }2371 2372  if (!opts::AlignText.getNumOccurrences())2373    opts::AlignText = BC->PageAlign;2374 2375  if (opts::AlignText < opts::AlignFunctions)2376    opts::AlignText = (unsigned)opts::AlignFunctions;2377 2378  if (BC->isX86() && opts::Lite.getNumOccurrences() == 0 && !opts::StrictMode &&2379      !opts::UseOldText)2380    opts::Lite = true;2381 2382  if (opts::Lite && opts::UseOldText) {2383    BC->errs() << "BOLT-WARNING: cannot combine -lite with -use-old-text. "2384                  "Disabling -use-old-text.\n";2385    opts::UseOldText = false;2386  }2387 2388  if (opts::Lite && opts::StrictMode) {2389    BC->errs()2390        << "BOLT-ERROR: -strict and -lite cannot be used at the same time\n";2391    exit(1);2392  }2393 2394  if (opts::Lite)2395    BC->outs() << "BOLT-INFO: enabling lite mode\n";2396 2397  if (BC->IsLinuxKernel) {2398    if (!opts::KeepNops.getNumOccurrences())2399      opts::KeepNops = true;2400 2401    // Linux kernel may resume execution after a trap or x86 HLT instruction.2402    if (!opts::TerminalHLT.getNumOccurrences())2403      opts::TerminalHLT = false;2404    if (!opts::TerminalTrap.getNumOccurrences())2405      opts::TerminalTrap = false;2406  }2407}2408 2409namespace {2410template <typename ELFT>2411int64_t getRelocationAddend(const ELFObjectFile<ELFT> *Obj,2412                            const RelocationRef &RelRef) {2413  using ELFShdrTy = typename ELFT::Shdr;2414  using Elf_Rela = typename ELFT::Rela;2415  int64_t Addend = 0;2416  const ELFFile<ELFT> &EF = Obj->getELFFile();2417  DataRefImpl Rel = RelRef.getRawDataRefImpl();2418  const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));2419  switch (RelocationSection->sh_type) {2420  default:2421    llvm_unreachable("unexpected relocation section type");2422  case ELF::SHT_REL:2423    break;2424  case ELF::SHT_RELA: {2425    const Elf_Rela *RelA = Obj->getRela(Rel);2426    Addend = RelA->r_addend;2427    break;2428  }2429  }2430 2431  return Addend;2432}2433 2434int64_t getRelocationAddend(const ELFObjectFileBase *Obj,2435                            const RelocationRef &Rel) {2436  return getRelocationAddend(cast<ELF64LEObjectFile>(Obj), Rel);2437}2438 2439template <typename ELFT>2440uint32_t getRelocationSymbol(const ELFObjectFile<ELFT> *Obj,2441                             const RelocationRef &RelRef) {2442  using ELFShdrTy = typename ELFT::Shdr;2443  uint32_t Symbol = 0;2444  const ELFFile<ELFT> &EF = Obj->getELFFile();2445  DataRefImpl Rel = RelRef.getRawDataRefImpl();2446  const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));2447  switch (RelocationSection->sh_type) {2448  default:2449    llvm_unreachable("unexpected relocation section type");2450  case ELF::SHT_REL:2451    Symbol = Obj->getRel(Rel)->getSymbol(EF.isMips64EL());2452    break;2453  case ELF::SHT_RELA:2454    Symbol = Obj->getRela(Rel)->getSymbol(EF.isMips64EL());2455    break;2456  }2457 2458  return Symbol;2459}2460 2461uint32_t getRelocationSymbol(const ELFObjectFileBase *Obj,2462                             const RelocationRef &Rel) {2463  return getRelocationSymbol(cast<ELF64LEObjectFile>(Obj), Rel);2464}2465} // anonymous namespace2466 2467bool RewriteInstance::analyzeRelocation(2468    const RelocationRef &Rel, uint32_t &RType, std::string &SymbolName,2469    bool &IsSectionRelocation, uint64_t &SymbolAddress, int64_t &Addend,2470    uint64_t &ExtractedValue) const {2471  if (!Relocation::isSupported(RType))2472    return false;2473 2474  auto IsWeakReference = [](const SymbolRef &Symbol) {2475    Expected<uint32_t> SymFlagsOrErr = Symbol.getFlags();2476    if (!SymFlagsOrErr)2477      return false;2478    return (*SymFlagsOrErr & SymbolRef::SF_Undefined) &&2479           (*SymFlagsOrErr & SymbolRef::SF_Weak);2480  };2481 2482  const bool IsAArch64 = BC->isAArch64();2483 2484  const size_t RelSize = Relocation::getSizeForType(RType);2485 2486  ErrorOr<uint64_t> Value =2487      BC->getUnsignedValueAtAddress(Rel.getOffset(), RelSize);2488  assert(Value && "failed to extract relocated value");2489 2490  ExtractedValue = Relocation::extractValue(RType, *Value, Rel.getOffset());2491  Addend = getRelocationAddend(InputFile, Rel);2492 2493  const bool IsPCRelative = Relocation::isPCRelative(RType);2494  const uint64_t PCRelOffset = IsPCRelative && !IsAArch64 ? Rel.getOffset() : 0;2495  bool SkipVerification = false;2496  auto SymbolIter = Rel.getSymbol();2497  if (SymbolIter == InputFile->symbol_end()) {2498    SymbolAddress = ExtractedValue - Addend + PCRelOffset;2499    MCSymbol *RelSymbol =2500        BC->getOrCreateGlobalSymbol(SymbolAddress, "RELSYMat");2501    SymbolName = std::string(RelSymbol->getName());2502    IsSectionRelocation = false;2503  } else {2504    const SymbolRef &Symbol = *SymbolIter;2505    SymbolName = std::string(cantFail(Symbol.getName()));2506    SymbolAddress = cantFail(Symbol.getAddress());2507    SkipVerification = (cantFail(Symbol.getType()) == SymbolRef::ST_Other);2508    // Section symbols are marked as ST_Debug.2509    IsSectionRelocation = (cantFail(Symbol.getType()) == SymbolRef::ST_Debug);2510    // Check for PLT entry registered with symbol name2511    if (!SymbolAddress && !IsWeakReference(Symbol) &&2512        (IsAArch64 || BC->isRISCV())) {2513      const BinaryData *BD = BC->getPLTBinaryDataByName(SymbolName);2514      SymbolAddress = BD ? BD->getAddress() : 0;2515    }2516  }2517  // For PIE or dynamic libs, the linker may choose not to put the relocation2518  // result at the address if it is a X86_64_64 one because it will emit a2519  // dynamic relocation (X86_RELATIVE) for the dynamic linker and loader to2520  // resolve it at run time. The static relocation result goes as the addend2521  // of the dynamic relocation in this case. We can't verify these cases.2522  // FIXME: perhaps we can try to find if it really emitted a corresponding2523  // RELATIVE relocation at this offset with the correct value as the addend.2524  if (!BC->HasFixedLoadAddress && RelSize == 8)2525    SkipVerification = true;2526 2527  if (IsSectionRelocation && !IsAArch64) {2528    ErrorOr<BinarySection &> Section = BC->getSectionForAddress(SymbolAddress);2529    assert(Section && "section expected for section relocation");2530    SymbolName = "section " + std::string(Section->getName());2531    // Convert section symbol relocations to regular relocations inside2532    // non-section symbols.2533    if (Section->containsAddress(ExtractedValue) && !IsPCRelative) {2534      SymbolAddress = ExtractedValue;2535      Addend = 0;2536    } else {2537      Addend = ExtractedValue - (SymbolAddress - PCRelOffset);2538    }2539  }2540 2541  // GOT relocation can cause the underlying instruction to be modified by the2542  // linker, resulting in the extracted value being different from the actual2543  // symbol. It's also possible to have a GOT entry for a symbol defined in the2544  // binary. In the latter case, the instruction can be using the GOT version2545  // causing the extracted value mismatch. Similar cases can happen for TLS.2546  // Pass the relocation information as is to the disassembler and let it decide2547  // how to use it for the operand symbolization.2548  if (Relocation::isGOT(RType) || Relocation::isTLS(RType)) {2549    SkipVerification = true;2550  } else if (!SymbolAddress) {2551    assert(!IsSectionRelocation);2552    if (ExtractedValue || Addend == 0 || IsPCRelative) {2553      SymbolAddress =2554          truncateToSize(ExtractedValue - Addend + PCRelOffset, RelSize);2555    } else {2556      // This is weird case.  The extracted value is zero but the addend is2557      // non-zero and the relocation is not pc-rel.  Using the previous logic,2558      // the SymbolAddress would end up as a huge number.  Seen in2559      // exceptions_pic.test.2560      LLVM_DEBUG(dbgs() << "BOLT-DEBUG: relocation @ 0x"2561                        << Twine::utohexstr(Rel.getOffset())2562                        << " value does not match addend for "2563                        << "relocation to undefined symbol.\n");2564      return true;2565    }2566  }2567 2568  auto verifyExtractedValue = [&]() {2569    if (SkipVerification)2570      return true;2571 2572    if (IsAArch64 || BC->isRISCV())2573      return true;2574 2575    if (SymbolName == "__hot_start" || SymbolName == "__hot_end")2576      return true;2577 2578    if (RType == ELF::R_X86_64_PLT32)2579      return true;2580 2581    return truncateToSize(ExtractedValue, RelSize) ==2582           truncateToSize(SymbolAddress + Addend - PCRelOffset, RelSize);2583  };2584 2585  (void)verifyExtractedValue;2586  assert(verifyExtractedValue() && "mismatched extracted relocation value");2587 2588  return true;2589}2590 2591void RewriteInstance::processDynamicRelocations() {2592  // Read .relr.dyn section containing compressed R_*_RELATIVE relocations.2593  if (DynamicRelrSize > 0) {2594    ErrorOr<BinarySection &> DynamicRelrSectionOrErr =2595        BC->getSectionForAddress(*DynamicRelrAddress);2596    if (!DynamicRelrSectionOrErr)2597      report_error("unable to find section corresponding to DT_RELR",2598                   DynamicRelrSectionOrErr.getError());2599    if (DynamicRelrSectionOrErr->getSize() != DynamicRelrSize)2600      report_error("section size mismatch for DT_RELRSZ",2601                   errc::executable_format_error);2602    readDynamicRelrRelocations(*DynamicRelrSectionOrErr);2603  }2604 2605  // Read relocations for PLT - DT_JMPREL.2606  if (PLTRelocationsSize > 0) {2607    ErrorOr<BinarySection &> PLTRelSectionOrErr =2608        BC->getSectionForAddress(*PLTRelocationsAddress);2609    if (!PLTRelSectionOrErr)2610      report_error("unable to find section corresponding to DT_JMPREL",2611                   PLTRelSectionOrErr.getError());2612    if (PLTRelSectionOrErr->getSize() != PLTRelocationsSize)2613      report_error("section size mismatch for DT_PLTRELSZ",2614                   errc::executable_format_error);2615    readDynamicRelocations(PLTRelSectionOrErr->getSectionRef(),2616                           /*IsJmpRel*/ true);2617  }2618 2619  // The rest of dynamic relocations - DT_RELA.2620  // The static executable might have .rela.dyn section and not have PT_DYNAMIC2621  if (!DynamicRelocationsSize && BC->IsStaticExecutable) {2622    ErrorOr<BinarySection &> DynamicRelSectionOrErr =2623        BC->getUniqueSectionByName(getRelaDynSectionName());2624    if (DynamicRelSectionOrErr) {2625      DynamicRelocationsAddress = DynamicRelSectionOrErr->getAddress();2626      DynamicRelocationsSize = DynamicRelSectionOrErr->getSize();2627      const SectionRef &SectionRef = DynamicRelSectionOrErr->getSectionRef();2628      DynamicRelativeRelocationsCount = std::distance(2629          SectionRef.relocation_begin(), SectionRef.relocation_end());2630    }2631  }2632 2633  if (DynamicRelocationsSize > 0) {2634    ErrorOr<BinarySection &> DynamicRelSectionOrErr =2635        BC->getSectionForAddress(*DynamicRelocationsAddress);2636    if (!DynamicRelSectionOrErr)2637      report_error("unable to find section corresponding to DT_RELA",2638                   DynamicRelSectionOrErr.getError());2639    auto DynamicRelSectionSize = DynamicRelSectionOrErr->getSize();2640    // On RISC-V DT_RELASZ seems to include both .rela.dyn and .rela.plt2641    if (DynamicRelocationsSize == DynamicRelSectionSize + PLTRelocationsSize)2642      DynamicRelocationsSize = DynamicRelSectionSize;2643    if (DynamicRelSectionSize != DynamicRelocationsSize)2644      report_error("section size mismatch for DT_RELASZ",2645                   errc::executable_format_error);2646    readDynamicRelocations(DynamicRelSectionOrErr->getSectionRef(),2647                           /*IsJmpRel*/ false);2648  }2649}2650 2651void RewriteInstance::processRelocations() {2652  if (!BC->HasRelocations)2653    return;2654 2655  for (const SectionRef &Section : InputFile->sections()) {2656    section_iterator SecIter = cantFail(Section.getRelocatedSection());2657    if (SecIter == InputFile->section_end())2658      continue;2659    if (BinarySection(*BC, Section).isAllocatable())2660      continue;2661 2662    readRelocations(Section);2663  }2664 2665  if (NumFailedRelocations)2666    BC->errs() << "BOLT-WARNING: Failed to analyze " << NumFailedRelocations2667               << " relocations\n";2668}2669 2670void RewriteInstance::readDynamicRelocations(const SectionRef &Section,2671                                             bool IsJmpRel) {2672  assert(BinarySection(*BC, Section).isAllocatable() && "allocatable expected");2673 2674  LLVM_DEBUG({2675    StringRef SectionName = cantFail(Section.getName());2676    dbgs() << "BOLT-DEBUG: reading relocations for section " << SectionName2677           << ":\n";2678  });2679 2680  for (const RelocationRef &Rel : Section.relocations()) {2681    const uint32_t RType = Relocation::getType(Rel);2682    if (Relocation::isNone(RType))2683      continue;2684 2685    StringRef SymbolName = "<none>";2686    MCSymbol *Symbol = nullptr;2687    uint64_t SymbolAddress = 0;2688    const uint64_t Addend = getRelocationAddend(InputFile, Rel);2689 2690    symbol_iterator SymbolIter = Rel.getSymbol();2691    if (SymbolIter != InputFile->symbol_end()) {2692      SymbolName = cantFail(SymbolIter->getName());2693      BinaryData *BD = BC->getBinaryDataByName(SymbolName);2694      Symbol = BD ? BD->getSymbol()2695                  : BC->getOrCreateUndefinedGlobalSymbol(SymbolName);2696      SymbolAddress = cantFail(SymbolIter->getAddress());2697      (void)SymbolAddress;2698    }2699 2700    LLVM_DEBUG(2701      SmallString<16> TypeName;2702      Rel.getTypeName(TypeName);2703      dbgs() << "BOLT-DEBUG: dynamic relocation at 0x"2704             << Twine::utohexstr(Rel.getOffset()) << " : " << TypeName2705             << " : " << SymbolName << " : " <<  Twine::utohexstr(SymbolAddress)2706             << " : + 0x" << Twine::utohexstr(Addend) << '\n'2707    );2708 2709    if (IsJmpRel)2710      IsJmpRelocation[RType] = true;2711 2712    if (Symbol)2713      SymbolIndex[Symbol] = getRelocationSymbol(InputFile, Rel);2714 2715    const uint64_t ReferencedAddress = SymbolAddress + Addend;2716    BinaryFunction *Func =2717        BC->getBinaryFunctionContainingAddress(ReferencedAddress);2718 2719    if (Relocation::isRelative(RType) && SymbolAddress == 0) {2720      if (Func) {2721        if (!Func->isInConstantIsland(ReferencedAddress)) {2722          if (const uint64_t ReferenceOffset =2723                  ReferencedAddress - Func->getAddress()) {2724            Func->addEntryPointAtOffset(ReferenceOffset);2725          }2726        } else {2727          BC->errs() << "BOLT-ERROR: referenced address at 0x"2728                     << Twine::utohexstr(ReferencedAddress)2729                     << " is in constant island of function " << *Func << "\n";2730          exit(1);2731        }2732      }2733    } else if (Relocation::isRelative(RType) && SymbolAddress != 0) {2734      BC->errs() << "BOLT-ERROR: symbol address non zero for RELATIVE "2735                    "relocation type\n";2736      exit(1);2737    }2738 2739    BC->addDynamicRelocation(Rel.getOffset(), Symbol, RType, Addend);2740  }2741}2742 2743void RewriteInstance::readDynamicRelrRelocations(BinarySection &Section) {2744  assert(Section.isAllocatable() && "allocatable expected");2745 2746  LLVM_DEBUG({2747    StringRef SectionName = Section.getName();2748    dbgs() << "BOLT-DEBUG: reading relocations in section " << SectionName2749           << ":\n";2750  });2751 2752  const uint32_t RType = Relocation::getRelative();2753  const uint8_t PSize = BC->AsmInfo->getCodePointerSize();2754  const uint64_t MaxDelta = ((CHAR_BIT * DynamicRelrEntrySize) - 1) * PSize;2755 2756  auto ExtractAddendValue = [&](uint64_t Address) -> uint64_t {2757    ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);2758    assert(Section && "cannot get section for data address from RELR");2759    DataExtractor DE = DataExtractor(Section->getContents(),2760                                     BC->AsmInfo->isLittleEndian(), PSize);2761    uint64_t Offset = Address - Section->getAddress();2762    return DE.getUnsigned(&Offset, PSize);2763  };2764 2765  auto AddRelocation = [&](uint64_t Address) {2766    uint64_t Addend = ExtractAddendValue(Address);2767    LLVM_DEBUG(dbgs() << "BOLT-DEBUG: R_*_RELATIVE relocation at 0x"2768                      << Twine::utohexstr(Address) << " to 0x"2769                      << Twine::utohexstr(Addend) << '\n';);2770    BC->addDynamicRelocation(Address, nullptr, RType, Addend);2771  };2772 2773  DataExtractor DE = DataExtractor(Section.getContents(),2774                                   BC->AsmInfo->isLittleEndian(), PSize);2775  uint64_t Offset = 0, Address = 0;2776  uint64_t RelrCount = DynamicRelrSize / DynamicRelrEntrySize;2777  while (RelrCount--) {2778    assert(DE.isValidOffset(Offset));2779    uint64_t Entry = DE.getUnsigned(&Offset, DynamicRelrEntrySize);2780    if ((Entry & 1) == 0) {2781      AddRelocation(Entry);2782      Address = Entry + PSize;2783    } else {2784      const uint64_t StartAddress = Address;2785      while (Entry >>= 1) {2786        if (Entry & 1)2787          AddRelocation(Address);2788 2789        Address += PSize;2790      }2791 2792      Address = StartAddress + MaxDelta;2793    }2794  }2795}2796 2797void RewriteInstance::printRelocationInfo(const RelocationRef &Rel,2798                                          StringRef SymbolName,2799                                          uint64_t SymbolAddress,2800                                          uint64_t Addend,2801                                          uint64_t ExtractedValue) const {2802  SmallString<16> TypeName;2803  Rel.getTypeName(TypeName);2804  const uint64_t Address = SymbolAddress + Addend;2805  const uint64_t Offset = Rel.getOffset();2806  ErrorOr<BinarySection &> Section = BC->getSectionForAddress(SymbolAddress);2807  BinaryFunction *Func =2808      BC->getBinaryFunctionContainingAddress(Offset, false, BC->isAArch64());2809  dbgs() << formatv("Relocation: offset = {0:x}; type = {1}; value = {2:x}; ",2810                    Offset, TypeName, ExtractedValue)2811         << formatv("symbol = {0} ({1}); symbol address = {2:x}; ", SymbolName,2812                    Section ? Section->getName() : "", SymbolAddress)2813         << formatv("addend = {0:x}; address = {1:x}; in = ", Addend, Address);2814  if (Func)2815    dbgs() << Func->getPrintName();2816  else2817    dbgs() << BC->getSectionForAddress(Rel.getOffset())->getName();2818  dbgs() << '\n';2819}2820 2821void RewriteInstance::readRelocations(const SectionRef &Section) {2822  LLVM_DEBUG({2823    StringRef SectionName = cantFail(Section.getName());2824    dbgs() << "BOLT-DEBUG: reading relocations for section " << SectionName2825           << ":\n";2826  });2827  if (BinarySection(*BC, Section).isAllocatable()) {2828    LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring runtime relocations\n");2829    return;2830  }2831  section_iterator SecIter = cantFail(Section.getRelocatedSection());2832  assert(SecIter != InputFile->section_end() && "relocated section expected");2833  SectionRef RelocatedSection = *SecIter;2834 2835  StringRef RelocatedSectionName = cantFail(RelocatedSection.getName());2836  LLVM_DEBUG(dbgs() << "BOLT-DEBUG: relocated section is "2837                    << RelocatedSectionName << '\n');2838 2839  if (!BinarySection(*BC, RelocatedSection).isAllocatable()) {2840    LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring relocations against "2841                      << "non-allocatable section\n");2842    return;2843  }2844  const bool SkipRelocs = StringSwitch<bool>(RelocatedSectionName)2845                              .Cases({".plt", ".rela.plt", ".got.plt",2846                                      ".eh_frame", ".gcc_except_table"},2847                                     true)2848                              .Default(false);2849  if (SkipRelocs) {2850    LLVM_DEBUG(2851        dbgs() << "BOLT-DEBUG: ignoring relocations against known section\n");2852    return;2853  }2854 2855  for (const RelocationRef &Rel : Section.relocations())2856    handleRelocation(RelocatedSection, Rel);2857}2858 2859void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,2860                                       const RelocationRef &Rel) {2861  const bool IsAArch64 = BC->isAArch64();2862  const bool IsX86 = BC->isX86();2863  const bool IsFromCode = RelocatedSection.isText();2864  const bool IsWritable = BinarySection(*BC, RelocatedSection).isWritable();2865 2866  SmallString<16> TypeName;2867  Rel.getTypeName(TypeName);2868  uint32_t RType = Relocation::getType(Rel);2869  if (Relocation::skipRelocationType(RType))2870    return;2871 2872  // Adjust the relocation type as the linker might have skewed it.2873  if (IsX86 && (RType & ELF::R_X86_64_converted_reloc_bit)) {2874    if (opts::Verbosity >= 1)2875      dbgs() << "BOLT-WARNING: ignoring R_X86_64_converted_reloc_bit\n";2876    RType &= ~ELF::R_X86_64_converted_reloc_bit;2877  }2878 2879  if (Relocation::isTLS(RType)) {2880    // No special handling required for TLS relocations on X86.2881    if (IsX86)2882      return;2883 2884    // The non-got related TLS relocations on AArch64 and RISC-V also could be2885    // skipped.2886    if (!Relocation::isGOT(RType))2887      return;2888  }2889 2890  if (!IsAArch64 && BC->getDynamicRelocationAt(Rel.getOffset())) {2891    LLVM_DEBUG({2892      dbgs() << formatv("BOLT-DEBUG: address {0:x} has a ", Rel.getOffset())2893             << "dynamic relocation against it. Ignoring static relocation.\n";2894    });2895    return;2896  }2897 2898  std::string SymbolName;2899  uint64_t SymbolAddress;2900  int64_t Addend;2901  uint64_t ExtractedValue;2902  bool IsSectionRelocation;2903  if (!analyzeRelocation(Rel, RType, SymbolName, IsSectionRelocation,2904                         SymbolAddress, Addend, ExtractedValue)) {2905    LLVM_DEBUG({2906      dbgs() << "BOLT-WARNING: failed to analyze relocation @ offset = "2907             << formatv("{0:x}; type name = {1}\n", Rel.getOffset(), TypeName);2908    });2909    ++NumFailedRelocations;2910    return;2911  }2912 2913  if (!IsFromCode && !IsWritable && (IsX86 || IsAArch64) &&2914      Relocation::isPCRelative(RType)) {2915    BinaryData *BD = BC->getBinaryDataContainingAddress(Rel.getOffset());2916    if (BD && (BD->nameStartsWith("_ZTV") ||   // vtable2917               BD->nameStartsWith("_ZTCN"))) { // construction vtable2918      BinaryFunction *BF = BC->getBinaryFunctionContainingAddress(2919          SymbolAddress, /*CheckPastEnd*/ false, /*UseMaxSize*/ true);2920      if (BF) {2921        if (BF->getAddress() != SymbolAddress) {2922          BC->errs()2923              << "BOLT-ERROR: the virtual function table entry at offset 0x"2924              << Twine::utohexstr(Rel.getOffset())2925              << " points to the middle of a function @ 0x"2926              << Twine::utohexstr(BF->getAddress()) << "\n";2927          exit(1);2928        }2929        BC->addRelocation(Rel.getOffset(), BF->getSymbol(), RType, Addend,2930                          ExtractedValue);2931        return;2932      }2933    }2934  }2935 2936  const uint64_t Address = SymbolAddress + Addend;2937 2938  LLVM_DEBUG({2939    dbgs() << "BOLT-DEBUG: ";2940    printRelocationInfo(Rel, SymbolName, SymbolAddress, Addend, ExtractedValue);2941  });2942 2943  BinaryFunction *ContainingBF = nullptr;2944  if (IsFromCode) {2945    ContainingBF =2946        BC->getBinaryFunctionContainingAddress(Rel.getOffset(),2947                                               /*CheckPastEnd*/ false,2948                                               /*UseMaxSize*/ true);2949    assert(ContainingBF && "cannot find function for address in code");2950    if (!IsAArch64 && !ContainingBF->containsAddress(Rel.getOffset())) {2951      if (opts::Verbosity >= 1)2952        BC->outs() << formatv(2953            "BOLT-INFO: {0} has relocations in padding area\n", *ContainingBF);2954      ContainingBF->setSize(ContainingBF->getMaxSize());2955      ContainingBF->setSimple(false);2956      return;2957    }2958  }2959 2960  MCSymbol *ReferencedSymbol = nullptr;2961  if (!IsSectionRelocation) {2962    if (BinaryData *BD = BC->getBinaryDataByName(SymbolName)) {2963      ReferencedSymbol = BD->getSymbol();2964    } else if (BC->isGOTSymbol(SymbolName)) {2965      if (BinaryData *BD = BC->getGOTSymbol())2966        ReferencedSymbol = BD->getSymbol();2967    } else if (BinaryData *BD = BC->getBinaryDataAtAddress(SymbolAddress)) {2968      ReferencedSymbol = BD->getSymbol();2969    }2970  }2971 2972  ErrorOr<BinarySection &> ReferencedSection{std::errc::bad_address};2973  symbol_iterator SymbolIter = Rel.getSymbol();2974  if (SymbolIter != InputFile->symbol_end()) {2975    SymbolRef Symbol = *SymbolIter;2976    section_iterator Section =2977        cantFail(Symbol.getSection(), "cannot get symbol section");2978    if (Section != InputFile->section_end()) {2979      Expected<StringRef> SectionName = Section->getName();2980      if (SectionName && !SectionName->empty())2981        ReferencedSection = BC->getUniqueSectionByName(*SectionName);2982    } else if (BC->isRISCV() && ReferencedSymbol && ContainingBF &&2983               (cantFail(Symbol.getFlags()) & SymbolRef::SF_Absolute)) {2984      // This might be a relocation for an ABS symbols like __global_pointer$ on2985      // RISC-V2986      ContainingBF->addRelocation(Rel.getOffset(), ReferencedSymbol,2987                                  Relocation::getType(Rel), 0,2988                                  cantFail(Symbol.getValue()));2989      return;2990    }2991  }2992 2993  if (!ReferencedSection)2994    ReferencedSection = BC->getSectionForAddress(SymbolAddress);2995 2996  const bool IsToCode = ReferencedSection && ReferencedSection->isText();2997 2998  // Special handling of PC-relative relocations.2999  if (IsX86 && Relocation::isPCRelative(RType)) {3000    if (!IsFromCode && IsToCode) {3001      // PC-relative relocations from data to code are tricky since the3002      // original information is typically lost after linking, even with3003      // '--emit-relocs'. Such relocations are normally used by PIC-style3004      // jump tables and they reference both the jump table and jump3005      // targets by computing the difference between the two. If we blindly3006      // apply the relocation, it will appear that it references an arbitrary3007      // location in the code, possibly in a different function from the one3008      // containing the jump table.3009      //3010      // For that reason, we only register the fact that there is a3011      // PC-relative relocation at a given address against the code.3012      // The actual referenced label/address will be determined during jump3013      // table analysis.3014      BC->addPCRelativeDataRelocation(Rel.getOffset());3015    } else if (ContainingBF && !IsSectionRelocation && ReferencedSymbol) {3016      // If we know the referenced symbol, register the relocation from3017      // the code. It's required  to properly handle cases where3018      // "symbol + addend" references an object different from "symbol".3019      ContainingBF->addRelocation(Rel.getOffset(), ReferencedSymbol, RType,3020                                  Addend, ExtractedValue);3021    } else {3022      LLVM_DEBUG({3023        dbgs() << "BOLT-DEBUG: not creating PC-relative relocation at"3024               << formatv("{0:x} for {1}\n", Rel.getOffset(), SymbolName);3025      });3026    }3027 3028    return;3029  }3030 3031  bool ForceRelocation = BC->forceSymbolRelocations(SymbolName);3032  if ((BC->isAArch64() || BC->isRISCV()) && Relocation::isGOT(RType))3033    ForceRelocation = true;3034 3035  if (!ReferencedSection && !ForceRelocation) {3036    LLVM_DEBUG(dbgs() << "BOLT-DEBUG: cannot determine referenced section.\n");3037    return;3038  }3039 3040  // Occasionally we may see a reference past the last byte of the function3041  // typically as a result of __builtin_unreachable(). Check it here.3042  BinaryFunction *ReferencedBF = BC->getBinaryFunctionContainingAddress(3043      Address, /*CheckPastEnd*/ true, /*UseMaxSize*/ IsAArch64);3044 3045  if (!IsSectionRelocation) {3046    if (BinaryFunction *BF =3047            BC->getBinaryFunctionContainingAddress(SymbolAddress)) {3048      if (BF != ReferencedBF) {3049        // It's possible we are referencing a function without referencing any3050        // code, e.g. when taking a bitmask action on a function address.3051        BC->errs()3052            << "BOLT-WARNING: non-standard function reference (e.g. bitmask)"3053            << formatv(" detected against function {0} from ", *BF);3054        if (IsFromCode)3055          BC->errs() << formatv("function {0}\n", *ContainingBF);3056        else3057          BC->errs() << formatv("data section at {0:x}\n", Rel.getOffset());3058        LLVM_DEBUG(printRelocationInfo(Rel, SymbolName, SymbolAddress, Addend,3059                                       ExtractedValue));3060        ReferencedBF = BF;3061      }3062    }3063  } else if (ReferencedBF) {3064    assert(ReferencedSection && "section expected for section relocation");3065    if (*ReferencedBF->getOriginSection() != *ReferencedSection) {3066      LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring false function reference\n");3067      ReferencedBF = nullptr;3068    }3069  }3070 3071  // Workaround for a member function pointer de-virtualization bug. We check3072  // if a non-pc-relative relocation in the code is pointing to (fptr - 1).3073  if (IsToCode && ContainingBF && !Relocation::isPCRelative(RType) &&3074      (!ReferencedBF || (ReferencedBF->getAddress() != Address))) {3075    if (const BinaryFunction *RogueBF =3076            BC->getBinaryFunctionAtAddress(Address + 1)) {3077      // Do an extra check that the function was referenced previously.3078      // It's a linear search, but it should rarely happen.3079      auto CheckReloc = [&](const Relocation &Rel) {3080        return Rel.Symbol == RogueBF->getSymbol() &&3081               !Relocation::isPCRelative(Rel.Type);3082      };3083      bool Found = llvm::any_of(3084          llvm::make_second_range(ContainingBF->Relocations), CheckReloc);3085 3086      if (Found) {3087        BC->errs()3088            << "BOLT-WARNING: detected possible compiler de-virtualization "3089               "bug: -1 addend used with non-pc-relative relocation against "3090            << formatv("function {0} in function {1}\n", *RogueBF,3091                       *ContainingBF);3092        return;3093      }3094    }3095  }3096 3097  if (ForceRelocation && !ReferencedBF) {3098    // Create the relocation symbol if it's not defined in the binary.3099    if (SymbolAddress == 0)3100      ReferencedSymbol = BC->registerNameAtAddress(SymbolName, 0, 0, 0);3101 3102    LLVM_DEBUG(3103        dbgs() << "BOLT-DEBUG: forcing relocation against symbol "3104               << (ReferencedSymbol ? ReferencedSymbol->getName() : "<none>")3105               << " with addend " << Addend << '\n');3106  } else if (ReferencedBF) {3107    ReferencedSymbol = ReferencedBF->getSymbol();3108    uint64_t RefFunctionOffset = 0;3109 3110    // Adjust the point of reference to a code location inside a function.3111    if (ReferencedBF->containsAddress(Address, /*UseMaxSize = */ true)) {3112      RefFunctionOffset = Address - ReferencedBF->getAddress();3113      if (Relocation::isInstructionReference(RType)) {3114        // Instruction labels are created while disassembling so we just leave3115        // the symbol empty for now. Since the extracted value is typically3116        // unrelated to the referenced symbol (e.g., %pcrel_lo in RISC-V3117        // references an instruction but the patched value references the low3118        // bits of a data address), we set the extracted value to the symbol3119        // address in order to be able to correctly reconstruct the reference3120        // later.3121        ReferencedSymbol = nullptr;3122        ExtractedValue = Address;3123      } else if (RefFunctionOffset) {3124        if (ContainingBF && ContainingBF != ReferencedBF &&3125            !ReferencedBF->isInConstantIsland(Address)) {3126          ReferencedSymbol =3127              ReferencedBF->addEntryPointAtOffset(RefFunctionOffset);3128        } else {3129          ReferencedSymbol = ReferencedBF->getOrCreateLocalLabel(Address);3130 3131          // If ContainingBF != nullptr, it equals ReferencedBF (see3132          // if-condition above) so we're handling a relocation from a function3133          // to itself. RISC-V uses such relocations for branches, for example.3134          // These should not be registered as externally references offsets.3135          if (!ContainingBF && !ReferencedBF->isInConstantIsland(Address)) {3136            ReferencedBF->registerInternalRefDataRelocation(RefFunctionOffset,3137                                                            Rel.getOffset());3138          }3139        }3140        if (opts::Verbosity > 1 &&3141            BinarySection(*BC, RelocatedSection).isWritable())3142          BC->errs()3143              << "BOLT-WARNING: writable reference into the middle of the "3144              << formatv("function {0} detected at address {1:x}\n",3145                         *ReferencedBF, Rel.getOffset());3146      }3147      SymbolAddress = Address;3148      Addend = 0;3149    }3150    LLVM_DEBUG({3151      dbgs() << "  referenced function " << *ReferencedBF;3152      if (Address != ReferencedBF->getAddress())3153        dbgs() << formatv(" at offset {0:x}", RefFunctionOffset);3154      dbgs() << '\n';3155    });3156  } else {3157    if (IsToCode && SymbolAddress) {3158      // This can happen e.g. with PIC-style jump tables.3159      LLVM_DEBUG(dbgs() << "BOLT-DEBUG: no corresponding function for "3160                           "relocation against code\n");3161    }3162 3163    // In AArch64 there are zero reasons to keep a reference to the3164    // "original" symbol plus addend. The original symbol is probably just a3165    // section symbol. If we are here, this means we are probably accessing3166    // data, so it is imperative to keep the original address.3167    if (IsAArch64) {3168      SymbolName = formatv("SYMBOLat{0:x}", Address);3169      SymbolAddress = Address;3170      Addend = 0;3171    }3172 3173    if (BinaryData *BD = BC->getBinaryDataContainingAddress(SymbolAddress)) {3174      // Note: this assertion is trying to check sanity of BinaryData objects3175      // but AArch64 and RISCV has inferred and incomplete object locations3176      // coming from GOT/TLS or any other non-trivial relocation (that requires3177      // creation of sections and whose symbol address is not really what should3178      // be encoded in the instruction). So we essentially disabled this check3179      // for AArch64 and live with bogus names for objects.3180      assert((IsAArch64 || BC->isRISCV() || IsSectionRelocation ||3181              BD->nameStartsWith(SymbolName) ||3182              BD->nameStartsWith("PG" + SymbolName) ||3183              (BD->nameStartsWith("ANONYMOUS") &&3184               (BD->getSectionName().starts_with(".plt") ||3185                BD->getSectionName().ends_with(".plt")))) &&3186             "BOLT symbol names of all non-section relocations must match up "3187             "with symbol names referenced in the relocation");3188 3189      if (IsSectionRelocation)3190        BC->markAmbiguousRelocations(*BD, Address);3191 3192      ReferencedSymbol = BD->getSymbol();3193      Addend += (SymbolAddress - BD->getAddress());3194      SymbolAddress = BD->getAddress();3195      assert(Address == SymbolAddress + Addend);3196    } else {3197      // These are mostly local data symbols but undefined symbols3198      // in relocation sections can get through here too, from .plt.3199      assert(3200          (IsAArch64 || BC->isRISCV() || IsSectionRelocation ||3201           BC->getSectionNameForAddress(SymbolAddress)->starts_with(".plt")) &&3202          "known symbols should not resolve to anonymous locals");3203 3204      if (IsSectionRelocation) {3205        ReferencedSymbol =3206            BC->getOrCreateGlobalSymbol(SymbolAddress, "SYMBOLat");3207      } else {3208        SymbolRef Symbol = *Rel.getSymbol();3209        const uint64_t SymbolSize =3210            IsAArch64 ? 0 : ELFSymbolRef(Symbol).getSize();3211        const uint64_t SymbolAlignment = IsAArch64 ? 1 : Symbol.getAlignment();3212        const uint32_t SymbolFlags = cantFail(Symbol.getFlags());3213        std::string Name;3214        if (SymbolFlags & SymbolRef::SF_Global) {3215          Name = SymbolName;3216        } else {3217          if (StringRef(SymbolName)3218                  .starts_with(BC->AsmInfo->getPrivateGlobalPrefix()))3219            Name = NR.uniquify("PG" + SymbolName);3220          else3221            Name = NR.uniquify(SymbolName);3222        }3223        ReferencedSymbol = BC->registerNameAtAddress(3224            Name, SymbolAddress, SymbolSize, SymbolAlignment, SymbolFlags);3225      }3226 3227      if (IsSectionRelocation) {3228        BinaryData *BD = BC->getBinaryDataByName(ReferencedSymbol->getName());3229        BC->markAmbiguousRelocations(*BD, Address);3230      }3231    }3232  }3233 3234  auto checkMaxDataRelocations = [&]() {3235    ++NumDataRelocations;3236    LLVM_DEBUG(if (opts::MaxDataRelocations &&3237                   NumDataRelocations + 1 == opts::MaxDataRelocations) {3238      dbgs() << "BOLT-DEBUG: processing ending on data relocation "3239             << NumDataRelocations << ": ";3240      printRelocationInfo(Rel, ReferencedSymbol->getName(), SymbolAddress,3241                          Addend, ExtractedValue);3242    });3243 3244    return (!opts::MaxDataRelocations ||3245            NumDataRelocations < opts::MaxDataRelocations);3246  };3247 3248  if ((ReferencedSection && refersToReorderedSection(ReferencedSection)) ||3249      (opts::ForceToDataRelocations && checkMaxDataRelocations()) ||3250      // RISC-V has ADD/SUB data-to-data relocations3251      BC->isRISCV())3252    ForceRelocation = true;3253 3254  if (IsFromCode)3255    ContainingBF->addRelocation(Rel.getOffset(), ReferencedSymbol, RType,3256                                Addend, ExtractedValue);3257  else if (IsToCode || ForceRelocation)3258    BC->addRelocation(Rel.getOffset(), ReferencedSymbol, RType, Addend,3259                      ExtractedValue);3260  else3261    LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring relocation from data to data\n");3262}3263 3264static BinaryFunction *getInitFunctionIfStaticBinary(BinaryContext &BC) {3265  // Workaround for https://github.com/llvm/llvm-project/issues/1000963266  // ("[BOLT] GOT array pointer incorrectly rewritten"). In aarch643267  // static glibc binaries, the .init section's _init function pointer can3268  // alias with a data pointer for the end of an array. GOT rewriting3269  // currently can't detect this and updates the data pointer to the3270  // moved _init, causing a runtime crash. Skipping _init on the other3271  // hand should be harmless.3272  if (!BC.IsStaticExecutable)3273    return nullptr;3274  const BinaryData *BD = BC.getBinaryDataByName("_init");3275  if (!BD || BD->getSectionName() != ".init")3276    return nullptr;3277  LLVM_DEBUG(dbgs() << "BOLT-DEBUG: skip _init in for GOT workaround.\n");3278  return BC.getBinaryFunctionAtAddress(BD->getAddress());3279}3280 3281static void populateFunctionNames(cl::opt<std::string> &FunctionNamesFile,3282                                  cl::list<std::string> &FunctionNames) {3283  if (FunctionNamesFile.empty())3284    return;3285  std::ifstream FuncsFile(FunctionNamesFile, std::ios::in);3286  std::string FuncName;3287  while (std::getline(FuncsFile, FuncName))3288    FunctionNames.push_back(FuncName);3289}3290 3291void RewriteInstance::selectFunctionsToPrint() {3292  populateFunctionNames(opts::PrintOnlyFile, opts::PrintOnly);3293}3294 3295void RewriteInstance::selectFunctionsToProcess() {3296  // Extend the list of functions to process or skip from a file.3297  populateFunctionNames(opts::FunctionNamesFile, opts::ForceFunctionNames);3298  populateFunctionNames(opts::SkipFunctionNamesFile, opts::SkipFunctionNames);3299  populateFunctionNames(opts::FunctionNamesFileNR, opts::ForceFunctionNamesNR);3300 3301  // Make a set of functions to process to speed up lookups.3302  std::unordered_set<std::string> ForceFunctionsNR(3303      opts::ForceFunctionNamesNR.begin(), opts::ForceFunctionNamesNR.end());3304 3305  if ((!opts::ForceFunctionNames.empty() ||3306       !opts::ForceFunctionNamesNR.empty()) &&3307      !opts::SkipFunctionNames.empty()) {3308    BC->errs()3309        << "BOLT-ERROR: cannot select functions to process and skip at the "3310           "same time. Please use only one type of selection.\n";3311    exit(1);3312  }3313 3314  uint64_t LiteThresholdExecCount = 0;3315  if (opts::LiteThresholdPct) {3316    if (opts::LiteThresholdPct > 100)3317      opts::LiteThresholdPct = 100;3318 3319    std::vector<const BinaryFunction *> TopFunctions;3320    for (auto &BFI : BC->getBinaryFunctions()) {3321      const BinaryFunction &Function = BFI.second;3322      if (ProfileReader->mayHaveProfileData(Function))3323        TopFunctions.push_back(&Function);3324    }3325    llvm::sort(3326        TopFunctions, [](const BinaryFunction *A, const BinaryFunction *B) {3327          return A->getKnownExecutionCount() < B->getKnownExecutionCount();3328        });3329 3330    size_t Index = TopFunctions.size() * opts::LiteThresholdPct / 100;3331    if (Index)3332      --Index;3333    LiteThresholdExecCount = TopFunctions[Index]->getKnownExecutionCount();3334    BC->outs() << "BOLT-INFO: limiting processing to functions with at least "3335               << LiteThresholdExecCount << " invocations\n";3336  }3337  LiteThresholdExecCount = std::max(3338      LiteThresholdExecCount, static_cast<uint64_t>(opts::LiteThresholdCount));3339 3340  StringSet<> ReorderFunctionsUserSet;3341  StringSet<> ReorderFunctionsLTOCommonSet;3342  if (opts::ReorderFunctions == ReorderFunctions::RT_USER) {3343    std::vector<std::string> FunctionNames;3344    BC->logBOLTErrorsAndQuitOnFatal(3345        ReorderFunctions::readFunctionOrderFile(FunctionNames));3346    for (const std::string &Function : FunctionNames) {3347      ReorderFunctionsUserSet.insert(Function);3348      if (std::optional<StringRef> LTOCommonName = getLTOCommonName(Function))3349        ReorderFunctionsLTOCommonSet.insert(*LTOCommonName);3350    }3351  }3352 3353  uint64_t NumFunctionsToProcess = 0;3354  auto mustSkip = [&](const BinaryFunction &Function) {3355    if (opts::MaxFunctions.getNumOccurrences() &&3356        NumFunctionsToProcess >= opts::MaxFunctions)3357      return true;3358    for (std::string &Name : opts::SkipFunctionNames)3359      if (Function.hasNameRegex(Name))3360        return true;3361 3362    return false;3363  };3364 3365  auto shouldProcess = [&](const BinaryFunction &Function) {3366    if (mustSkip(Function))3367      return false;3368 3369    // If the list is not empty, only process functions from the list.3370    if (!opts::ForceFunctionNames.empty() || !ForceFunctionsNR.empty()) {3371      // Regex check (-funcs and -funcs-file options).3372      for (std::string &Name : opts::ForceFunctionNames)3373        if (Function.hasNameRegex(Name))3374          return true;3375 3376      // Non-regex check (-funcs-no-regex and -funcs-file-no-regex).3377      for (const StringRef Name : Function.getNames())3378        if (ForceFunctionsNR.count(Name.str()))3379          return true;3380 3381      return false;3382    }3383 3384    if (opts::Lite) {3385      // Forcibly include functions specified in the -function-order file.3386      if (opts::ReorderFunctions == ReorderFunctions::RT_USER) {3387        for (const StringRef Name : Function.getNames())3388          if (ReorderFunctionsUserSet.contains(Name))3389            return true;3390        for (const StringRef Name : Function.getNames())3391          if (std::optional<StringRef> LTOCommonName = getLTOCommonName(Name))3392            if (ReorderFunctionsLTOCommonSet.contains(*LTOCommonName))3393              return true;3394      }3395 3396      if (ProfileReader && !ProfileReader->mayHaveProfileData(Function))3397        return false;3398 3399      if (Function.getKnownExecutionCount() < LiteThresholdExecCount)3400        return false;3401    }3402 3403    return true;3404  };3405 3406  if (BinaryFunction *Init = getInitFunctionIfStaticBinary(*BC))3407    Init->setIgnored();3408 3409  for (auto &BFI : BC->getBinaryFunctions()) {3410    BinaryFunction &Function = BFI.second;3411 3412    // Pseudo functions are explicitly marked by us not to be processed.3413    if (Function.isPseudo()) {3414      Function.IsIgnored = true;3415      Function.HasExternalRefRelocations = true;3416      continue;3417    }3418 3419    // Decide what to do with fragments after parent functions are processed.3420    if (Function.isFragment())3421      continue;3422 3423    if (!shouldProcess(Function)) {3424      if (opts::Verbosity >= 1) {3425        BC->outs() << "BOLT-INFO: skipping processing " << Function3426                   << " per user request\n";3427      }3428      Function.setIgnored();3429    } else {3430      ++NumFunctionsToProcess;3431      if (opts::MaxFunctions.getNumOccurrences() &&3432          NumFunctionsToProcess == opts::MaxFunctions)3433        BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n';3434    }3435  }3436 3437  if (!BC->HasSplitFunctions)3438    return;3439 3440  // Fragment overrides:3441  // - If the fragment must be skipped, then the parent must be skipped as well.3442  // Otherwise, fragment should follow the parent function:3443  // - if the parent is skipped, skip fragment,3444  // - if the parent is processed, process the fragment(s) as well.3445  for (auto &BFI : BC->getBinaryFunctions()) {3446    BinaryFunction &Function = BFI.second;3447    if (!Function.isFragment())3448      continue;3449    if (mustSkip(Function)) {3450      for (BinaryFunction *Parent : Function.ParentFragments) {3451        if (opts::Verbosity >= 1) {3452          BC->outs() << "BOLT-INFO: skipping processing " << *Parent3453                     << " together with fragment function\n";3454        }3455        Parent->setIgnored();3456        --NumFunctionsToProcess;3457      }3458      Function.setIgnored();3459      continue;3460    }3461 3462    bool IgnoredParent =3463        llvm::any_of(Function.ParentFragments, [&](BinaryFunction *Parent) {3464          return Parent->isIgnored();3465        });3466    if (IgnoredParent) {3467      if (opts::Verbosity >= 1) {3468        BC->outs() << "BOLT-INFO: skipping processing " << Function3469                   << " together with parent function\n";3470      }3471      Function.setIgnored();3472    } else {3473      ++NumFunctionsToProcess;3474      if (opts::Verbosity >= 1) {3475        BC->outs() << "BOLT-INFO: processing " << Function3476                   << " as a sibling of non-ignored function\n";3477      }3478      if (opts::MaxFunctions && NumFunctionsToProcess == opts::MaxFunctions)3479        BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n';3480    }3481  }3482}3483 3484void RewriteInstance::readDebugInfo() {3485  NamedRegionTimer T("readDebugInfo", "read debug info", TimerGroupName,3486                     TimerGroupDesc, opts::TimeRewrite);3487  if (!opts::UpdateDebugSections)3488    return;3489 3490  BC->preprocessDebugInfo();3491}3492 3493void RewriteInstance::preprocessProfileData() {3494  if (!ProfileReader)3495    return;3496 3497  NamedRegionTimer T("preprocessprofile", "pre-process profile data",3498                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3499 3500  BC->outs() << "BOLT-INFO: pre-processing profile using "3501             << ProfileReader->getReaderName() << '\n';3502 3503  if (BAT->enabledFor(InputFile)) {3504    BC->outs() << "BOLT-INFO: profile collection done on a binary already "3505                  "processed by BOLT\n";3506    ProfileReader->setBAT(&*BAT);3507  }3508 3509  if (Error E = ProfileReader->preprocessProfile(*BC))3510    report_error("cannot pre-process profile", std::move(E));3511 3512  if (!BC->hasSymbolsWithFileName() && ProfileReader->hasLocalsWithFileName() &&3513      !opts::AllowStripped) {3514    BC->errs()3515        << "BOLT-ERROR: input binary does not have local file symbols "3516           "but profile data includes function names with embedded file "3517           "names. It appears that the input binary was stripped while a "3518           "profiled binary was not. If you know what you are doing and "3519           "wish to proceed, use -allow-stripped option.\n";3520    exit(1);3521  }3522}3523 3524void RewriteInstance::initializeMetadataManager() {3525  if (BC->IsLinuxKernel)3526    MetadataManager.registerRewriter(createLinuxKernelRewriter(*BC));3527 3528  MetadataManager.registerRewriter(createBuildIDRewriter(*BC));3529 3530  MetadataManager.registerRewriter(createPseudoProbeRewriter(*BC));3531 3532  MetadataManager.registerRewriter(createRSeqRewriter(*BC));3533 3534  MetadataManager.registerRewriter(createSDTRewriter(*BC));3535 3536  MetadataManager.registerRewriter(createGNUPropertyRewriter(*BC));3537}3538 3539void RewriteInstance::processSectionMetadata() {3540  NamedRegionTimer T("processmetadata-section", "process section metadata",3541                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3542  initializeMetadataManager();3543 3544  MetadataManager.runSectionInitializers();3545}3546 3547void RewriteInstance::processMetadataPreCFG() {3548  NamedRegionTimer T("processmetadata-precfg", "process metadata pre-CFG",3549                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3550  MetadataManager.runInitializersPreCFG();3551 3552  processProfileDataPreCFG();3553}3554 3555void RewriteInstance::processMetadataPostCFG() {3556  NamedRegionTimer T("processmetadata-postcfg", "process metadata post-CFG",3557                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3558  MetadataManager.runInitializersPostCFG();3559}3560 3561void RewriteInstance::processProfileDataPreCFG() {3562  if (!ProfileReader)3563    return;3564 3565  NamedRegionTimer T("processprofile-precfg", "process profile data pre-CFG",3566                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3567 3568  if (Error E = ProfileReader->readProfilePreCFG(*BC))3569    report_error("cannot read profile pre-CFG", std::move(E));3570}3571 3572void RewriteInstance::processProfileData() {3573  if (!ProfileReader)3574    return;3575 3576  NamedRegionTimer T("processprofile", "process profile data", TimerGroupName,3577                     TimerGroupDesc, opts::TimeRewrite);3578 3579  if (Error E = ProfileReader->readProfile(*BC))3580    report_error("cannot read profile", std::move(E));3581 3582  if (opts::PrintProfile || opts::PrintAll) {3583    for (auto &BFI : BC->getBinaryFunctions()) {3584      BinaryFunction &Function = BFI.second;3585      if (Function.empty())3586        continue;3587 3588      Function.print(BC->outs(), "after attaching profile");3589    }3590  }3591 3592  if (!opts::SaveProfile.empty() && !BAT->enabledFor(InputFile)) {3593    YAMLProfileWriter PW(opts::SaveProfile);3594    PW.writeProfile(*this);3595  }3596  if (opts::AggregateOnly &&3597      opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML &&3598      !BAT->enabledFor(InputFile)) {3599    YAMLProfileWriter PW(opts::OutputFilename);3600    PW.writeProfile(*this);3601  }3602 3603  // Release memory used by profile reader.3604  ProfileReader.reset();3605 3606  if (opts::AggregateOnly) {3607    PrintProgramStats PPS(&*BAT);3608    BC->logBOLTErrorsAndQuitOnFatal(PPS.runOnFunctions(*BC));3609    TimerGroup::printAll(outs());3610    exit(0);3611  }3612}3613 3614void RewriteInstance::disassembleFunctions() {3615  NamedRegionTimer T("disassembleFunctions", "disassemble functions",3616                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3617  for (auto &BFI : BC->getBinaryFunctions()) {3618    BinaryFunction &Function = BFI.second;3619 3620    ErrorOr<ArrayRef<uint8_t>> FunctionData = Function.getData();3621    if (!FunctionData) {3622      BC->errs() << "BOLT-ERROR: corresponding section is non-executable or "3623                 << "empty for function " << Function << '\n';3624      exit(1);3625    }3626 3627    // Treat zero-sized functions as non-simple ones.3628    if (Function.getSize() == 0) {3629      Function.setSimple(false);3630      continue;3631    }3632 3633    // Offset of the function in the file.3634    const auto *FileBegin =3635        reinterpret_cast<const uint8_t *>(InputFile->getData().data());3636    Function.setFileOffset(FunctionData->begin() - FileBegin);3637 3638    if (!shouldDisassemble(Function)) {3639      NamedRegionTimer T("scan", "scan functions", "buildfuncs",3640                         "Scan Binary Functions", opts::TimeBuild);3641      Function.scanExternalRefs();3642      Function.setSimple(false);3643      continue;3644    }3645 3646    bool DisasmFailed{false};3647    handleAllErrors(Function.disassemble(), [&](const BOLTError &E) {3648      DisasmFailed = true;3649      if (E.isFatal()) {3650        E.log(BC->errs());3651        exit(1);3652      }3653      if (opts::processAllFunctions()) {3654        BC->errs() << BC->generateBugReportMessage(3655            "function cannot be properly disassembled. "3656            "Unable to continue in relocation mode.",3657            Function);3658        exit(1);3659      }3660      if (opts::Verbosity >= 1)3661        BC->outs() << "BOLT-INFO: could not disassemble function " << Function3662                   << ". Will ignore.\n";3663      // Forcefully ignore the function.3664      Function.scanExternalRefs();3665      Function.setIgnored();3666    });3667 3668    if (DisasmFailed)3669      continue;3670 3671    if (opts::PrintAll || opts::PrintDisasm)3672      Function.print(BC->outs(), "after disassembly");3673  }3674 3675  BC->processInterproceduralReferences();3676  BC->populateJumpTables();3677 3678  for (auto &BFI : BC->getBinaryFunctions()) {3679    BinaryFunction &Function = BFI.second;3680 3681    if (!shouldDisassemble(Function))3682      continue;3683 3684    Function.postProcessEntryPoints();3685    Function.postProcessJumpTables();3686  }3687 3688  BC->clearJumpTableTempData();3689  BC->adjustCodePadding();3690 3691  for (auto &BFI : BC->getBinaryFunctions()) {3692    BinaryFunction &Function = BFI.second;3693 3694    if (!shouldDisassemble(Function))3695      continue;3696 3697    if (!Function.isSimple()) {3698      assert((!BC->HasRelocations || Function.getSize() == 0 ||3699              Function.hasIndirectTargetToSplitFragment()) &&3700             "unexpected non-simple function in relocation mode");3701      continue;3702    }3703 3704    // Fill in CFI information for this function3705    if (!Function.trapsOnEntry() && !CFIRdWrt->fillCFIInfoFor(Function)) {3706      if (BC->HasRelocations) {3707        BC->errs() << BC->generateBugReportMessage("unable to fill CFI.",3708                                                   Function);3709        exit(1);3710      } else {3711        BC->errs() << "BOLT-WARNING: unable to fill CFI for function "3712                   << Function << ". Skipping.\n";3713        Function.setSimple(false);3714        continue;3715      }3716    }3717 3718    // Check if fillCFIInfoFor removed any OpNegateRAState CFIs from the3719    // function.3720    if (Function.containedNegateRAState()) {3721      if (!opts::UpdateBranchProtection) {3722        BC->errs()3723            << "BOLT-ERROR: --update-branch-protection is set to false, but "3724            << Function.getPrintName() << " contains .cfi-negate-ra-state\n";3725        exit(1);3726      }3727    }3728 3729    // Parse LSDA.3730    if (Function.getLSDAAddress() != 0 &&3731        !BC->getFragmentsToSkip().count(&Function)) {3732      ErrorOr<BinarySection &> LSDASection =3733          BC->getSectionForAddress(Function.getLSDAAddress());3734      check_error(LSDASection.getError(), "failed to get LSDA section");3735      ArrayRef<uint8_t> LSDAData = ArrayRef<uint8_t>(3736          LSDASection->getData(), LSDASection->getContents().size());3737      BC->logBOLTErrorsAndQuitOnFatal(3738          Function.parseLSDA(LSDAData, LSDASection->getAddress()));3739    }3740  }3741}3742 3743void RewriteInstance::buildFunctionsCFG() {3744  NamedRegionTimer T("buildCFG", "buildCFG", "buildfuncs",3745                     "Build Binary Functions", opts::TimeBuild);3746 3747  // Create annotation indices to allow lock-free execution3748  BC->MIB->getOrCreateAnnotationIndex("JTIndexReg");3749  BC->MIB->getOrCreateAnnotationIndex("NOP");3750 3751  ParallelUtilities::WorkFuncWithAllocTy WorkFun =3752      [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId) {3753        bool HadErrors{false};3754        handleAllErrors(BF.buildCFG(AllocId), [&](const BOLTError &E) {3755          if (!E.getMessage().empty())3756            E.log(BC->errs());3757          if (E.isFatal())3758            exit(1);3759          HadErrors = true;3760        });3761 3762        if (HadErrors)3763          return;3764 3765        if (opts::PrintAll) {3766          auto L = BC->scopeLock();3767          BF.print(BC->outs(), "while building cfg");3768        }3769      };3770 3771  ParallelUtilities::PredicateTy SkipPredicate = [&](const BinaryFunction &BF) {3772    return !shouldDisassemble(BF) || !BF.isSimple();3773  };3774 3775  ParallelUtilities::runOnEachFunctionWithUniqueAllocId(3776      *BC, ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFun,3777      SkipPredicate, "disassembleFunctions-buildCFG",3778      /*ForceSequential*/ opts::SequentialDisassembly || opts::PrintAll);3779 3780  BC->postProcessSymbolTable();3781}3782 3783void RewriteInstance::postProcessFunctions() {3784  // We mark fragments as non-simple here, not during disassembly,3785  // So we can build their CFGs.3786  BC->skipMarkedFragments();3787  BC->clearFragmentsToSkip();3788 3789  BC->TotalScore = 0;3790  BC->SumExecutionCount = 0;3791  for (auto &BFI : BC->getBinaryFunctions()) {3792    BinaryFunction &Function = BFI.second;3793 3794    // Set function as non-simple if it has dynamic relocations3795    // in constant island, we don't want this function to be optimized3796    // e.g. function splitting is unsupported.3797    if (Function.hasDynamicRelocationAtIsland())3798      Function.setSimple(false);3799 3800    if (Function.empty())3801      continue;3802 3803    Function.postProcessCFG();3804 3805    if (opts::PrintAll || opts::PrintCFG)3806      Function.print(BC->outs(), "after building cfg");3807 3808    if (opts::shouldDumpDot(Function))3809      Function.dumpGraphForPass("00_build-cfg");3810 3811    if (opts::PrintLoopInfo) {3812      Function.calculateLoopInfo();3813      Function.printLoopInfo(BC->outs());3814    }3815 3816    BC->TotalScore += Function.getFunctionScore();3817    BC->SumExecutionCount += Function.getKnownExecutionCount();3818  }3819 3820  if (opts::PrintGlobals) {3821    BC->outs() << "BOLT-INFO: Global symbols:\n";3822    BC->printGlobalSymbols(BC->outs());3823  }3824}3825 3826void RewriteInstance::runOptimizationPasses() {3827  NamedRegionTimer T("runOptimizationPasses", "run optimization passes",3828                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3829  BC->logBOLTErrorsAndQuitOnFatal(BinaryFunctionPassManager::runAllPasses(*BC));3830}3831 3832void RewriteInstance::runBinaryAnalyses() {3833  NamedRegionTimer T("runBinaryAnalyses", "run binary analysis passes",3834                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3835  BinaryFunctionPassManager Manager(*BC);3836  // FIXME: add a pass that warns about which functions do not have CFG,3837  // and therefore, analysis is most likely to be less accurate.3838  using GSK = opts::GadgetScannerKind;3839  using PAuthScanner = PAuthGadgetScanner::Analysis;3840 3841  // If no command line option was given, act as if "all" was specified.3842  bool RunAll = !opts::GadgetScannersToRun.getBits() ||3843                opts::GadgetScannersToRun.isSet(GSK::GS_ALL);3844 3845  if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PAUTH)) {3846    Manager.registerPass(3847        std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/false));3848  } else if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PACRET)) {3849    Manager.registerPass(3850        std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/true));3851  }3852 3853  BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses());3854}3855 3856void RewriteInstance::preregisterSections() {3857  // Preregister sections before emission to set their order in the output.3858  const unsigned ROFlags = BinarySection::getFlags(/*IsReadOnly*/ true,3859                                                   /*IsText*/ false,3860                                                   /*IsAllocatable*/ true);3861  if (BinarySection *EHFrameSection = getSection(getEHFrameSectionName())) {3862    // New .eh_frame.3863    BC->registerOrUpdateSection(getNewSecPrefix() + getEHFrameSectionName(),3864                                ELF::SHT_PROGBITS, ROFlags);3865    // Fully register a relocatable copy of the original .eh_frame.3866    BC->registerSection(".relocated.eh_frame", *EHFrameSection);3867  }3868  BC->registerOrUpdateSection(getNewSecPrefix() + ".gcc_except_table",3869                              ELF::SHT_PROGBITS, ROFlags);3870  BC->registerOrUpdateSection(getNewSecPrefix() + ".rodata", ELF::SHT_PROGBITS,3871                              ROFlags);3872  BC->registerOrUpdateSection(getNewSecPrefix() + ".rodata.cold",3873                              ELF::SHT_PROGBITS, ROFlags);3874}3875 3876void RewriteInstance::emitAndLink() {3877  NamedRegionTimer T("emitAndLink", "emit and link", TimerGroupName,3878                     TimerGroupDesc, opts::TimeRewrite);3879 3880  SmallString<0> ObjectBuffer;3881  raw_svector_ostream OS(ObjectBuffer);3882 3883  // Implicitly MCObjectStreamer takes ownership of MCAsmBackend (MAB)3884  // and MCCodeEmitter (MCE). ~MCObjectStreamer() will delete these3885  // two instances.3886  std::unique_ptr<MCStreamer> Streamer = BC->createStreamer(OS);3887 3888  if (EHFrameSection) {3889    if (opts::UseOldText || opts::StrictMode) {3890      // The section is going to be regenerated from scratch.3891      // Empty the contents, but keep the section reference.3892      EHFrameSection->clearContents();3893    } else {3894      // Make .eh_frame relocatable.3895      relocateEHFrameSection();3896    }3897  }3898 3899  emitBinaryContext(*Streamer, *BC, getOrgSecPrefix());3900 3901  Streamer->finish();3902  if (Streamer->getContext().hadError()) {3903    BC->errs() << "BOLT-ERROR: Emission failed.\n";3904    exit(1);3905  }3906 3907  if (opts::KeepTmp) {3908    SmallString<128> OutObjectPath;3909    sys::fs::getPotentiallyUniqueTempFileName("output", "o", OutObjectPath);3910    std::error_code EC;3911    raw_fd_ostream FOS(OutObjectPath, EC);3912    check_error(EC, "cannot create output object file");3913    FOS << ObjectBuffer;3914    BC->outs()3915        << "BOLT-INFO: intermediary output object file saved for debugging "3916           "purposes: "3917        << OutObjectPath << "\n";3918  }3919 3920  ErrorOr<BinarySection &> TextSection =3921      BC->getUniqueSectionByName(BC->getMainCodeSectionName());3922  if (BC->HasRelocations && TextSection)3923    BC->renameSection(*TextSection,3924                      getOrgSecPrefix() + BC->getMainCodeSectionName());3925 3926  //////////////////////////////////////////////////////////////////////////////3927  // Assign addresses to new sections.3928  //////////////////////////////////////////////////////////////////////////////3929 3930  // Get output object as ObjectFile.3931  std::unique_ptr<MemoryBuffer> ObjectMemBuffer =3932      MemoryBuffer::getMemBuffer(ObjectBuffer, "in-memory object file", false);3933 3934  auto EFMM = std::make_unique<ExecutableFileMemoryManager>(*BC);3935  EFMM->setNewSecPrefix(getNewSecPrefix());3936  EFMM->setOrgSecPrefix(getOrgSecPrefix());3937 3938  Linker = std::make_unique<JITLinkLinker>(*BC, std::move(EFMM));3939  Linker->loadObject(ObjectMemBuffer->getMemBufferRef(),3940                     [this](auto MapSection) { mapFileSections(MapSection); });3941 3942  // Update output addresses based on the new section map and3943  // layout. Only do this for the object created by ourselves.3944  updateOutputValues(*Linker);3945 3946  if (opts::UpdateDebugSections) {3947    DebugInfoRewriter->updateLineTableOffsets(3948        static_cast<MCObjectStreamer &>(*Streamer).getAssembler());3949  }3950 3951  if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary()) {3952    StartLinkingRuntimeLib = true;3953    RtLibrary->link(*BC, ToolPath, *Linker, [this](auto MapSection) {3954      // Map newly registered sections.3955      this->mapAllocatableSections(MapSection);3956    });3957  }3958 3959  // Once the code is emitted, we can rename function sections to actual3960  // output sections and de-register sections used for emission.3961  for (BinaryFunction *Function : BC->getAllBinaryFunctions()) {3962    ErrorOr<BinarySection &> Section = Function->getCodeSection();3963    if (Section &&3964        (Function->getImageAddress() == 0 || Function->getImageSize() == 0))3965      continue;3966 3967    // Restore origin section for functions that were emitted or supposed to3968    // be emitted to patch sections.3969    if (Section)3970      BC->deregisterSection(*Section);3971    assert(Function->getOriginSectionName() && "expected origin section");3972    Function->CodeSectionName = Function->getOriginSectionName()->str();3973    for (const FunctionFragment &FF :3974         Function->getLayout().getSplitFragments()) {3975      if (ErrorOr<BinarySection &> ColdSection =3976              Function->getCodeSection(FF.getFragmentNum()))3977        BC->deregisterSection(*ColdSection);3978    }3979    if (Function->getLayout().isSplit())3980      Function->setColdCodeSectionName(getBOLTTextSectionName());3981  }3982 3983  if (opts::PrintCacheMetrics) {3984    BC->outs() << "BOLT-INFO: cache metrics after emitting functions:\n";3985    CacheMetrics::printAll(BC->outs(), BC->getSortedFunctions());3986  }3987}3988 3989void RewriteInstance::finalizeMetadataPreEmit() {3990  NamedRegionTimer T("finalizemetadata-preemit", "finalize metadata pre-emit",3991                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3992  MetadataManager.runFinalizersPreEmit();3993}3994 3995void RewriteInstance::updateMetadata() {3996  NamedRegionTimer T("updatemetadata-postemit", "update metadata post-emit",3997                     TimerGroupName, TimerGroupDesc, opts::TimeRewrite);3998  MetadataManager.runFinalizersAfterEmit();3999 4000  if (opts::UpdateDebugSections) {4001    NamedRegionTimer T("updateDebugInfo", "update debug info", TimerGroupName,4002                       TimerGroupDesc, opts::TimeRewrite);4003    DebugInfoRewriter->updateDebugInfo();4004  }4005 4006  if (opts::WriteBoltInfoSection)4007    addBoltInfoSection();4008}4009 4010void RewriteInstance::mapFileSections(BOLTLinker::SectionMapper MapSection) {4011  BC->deregisterUnusedSections();4012 4013  // If no new .eh_frame was written, remove relocated original .eh_frame.4014  BinarySection *RelocatedEHFrameSection =4015      getSection(".relocated" + getEHFrameSectionName());4016  if (RelocatedEHFrameSection && RelocatedEHFrameSection->hasValidSectionID()) {4017    BinarySection *NewEHFrameSection =4018        getSection(getNewSecPrefix() + getEHFrameSectionName());4019    if (!NewEHFrameSection || !NewEHFrameSection->isFinalized()) {4020      // JITLink will still have to process relocations for the section, hence4021      // we need to assign it the address that wouldn't result in relocation4022      // processing failure.4023      MapSection(*RelocatedEHFrameSection, NextAvailableAddress);4024      BC->deregisterSection(*RelocatedEHFrameSection);4025    }4026  }4027 4028  mapCodeSections(MapSection);4029 4030  // Map the rest of the sections.4031  mapAllocatableSections(MapSection);4032 4033  if (!BC->BOLTReserved.empty()) {4034    const uint64_t AllocatedSize =4035        NextAvailableAddress - BC->BOLTReserved.start();4036    if (BC->BOLTReserved.size() < AllocatedSize) {4037      BC->errs() << "BOLT-ERROR: reserved space (" << BC->BOLTReserved.size()4038                 << " byte" << (BC->BOLTReserved.size() == 1 ? "" : "s")4039                 << ") is smaller than required for new allocations ("4040                 << AllocatedSize << " bytes)\n";4041      exit(1);4042    }4043  }4044}4045 4046std::vector<BinarySection *> RewriteInstance::getCodeSections() {4047  std::vector<BinarySection *> CodeSections;4048  for (BinarySection &Section : BC->textSections())4049    if (Section.hasValidSectionID())4050      CodeSections.emplace_back(&Section);4051 4052  auto compareSections = [&](const BinarySection *A, const BinarySection *B) {4053    // If both A and B have names starting with ".text.cold", then4054    // - if opts::HotFunctionsAtEnd is true, we want order4055    //   ".text.cold.T", ".text.cold.T-1", ... ".text.cold.1", ".text.cold"4056    // - if opts::HotFunctionsAtEnd is false, we want order4057    //   ".text.cold", ".text.cold.1", ... ".text.cold.T-1", ".text.cold.T"4058    if (A->getName().starts_with(BC->getColdCodeSectionName()) &&4059        B->getName().starts_with(BC->getColdCodeSectionName())) {4060      if (A->getName().size() != B->getName().size())4061        return (opts::HotFunctionsAtEnd)4062                   ? (A->getName().size() > B->getName().size())4063                   : (A->getName().size() < B->getName().size());4064      return (opts::HotFunctionsAtEnd) ? (A->getName() > B->getName())4065                                       : (A->getName() < B->getName());4066    }4067 4068    // Place movers before anything else.4069    if (A->getName() == BC->getHotTextMoverSectionName())4070      return true;4071    if (B->getName() == BC->getHotTextMoverSectionName())4072      return false;4073 4074    // Depending on opts::HotFunctionsAtEnd, place main and warm sections in4075    // order.4076    if (opts::HotFunctionsAtEnd) {4077      if (B->getName() == BC->getMainCodeSectionName())4078        return true;4079      if (A->getName() == BC->getMainCodeSectionName())4080        return false;4081      return (B->getName() == BC->getWarmCodeSectionName());4082    } else {4083      if (A->getName() == BC->getMainCodeSectionName())4084        return true;4085      if (B->getName() == BC->getMainCodeSectionName())4086        return false;4087      return (A->getName() == BC->getWarmCodeSectionName());4088    }4089  };4090 4091  // Determine the order of sections.4092  llvm::stable_sort(CodeSections, compareSections);4093 4094  return CodeSections;4095}4096 4097void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {4098  if (!BC->HasRelocations) {4099    mapCodeSectionsInPlace(MapSection);4100    return;4101  }4102 4103  // Map sections for functions with pre-assigned addresses.4104  for (BinaryFunction *InjectedFunction : BC->getInjectedBinaryFunctions()) {4105    const uint64_t OutputAddress = InjectedFunction->getOutputAddress();4106    if (!OutputAddress)4107      continue;4108 4109    ErrorOr<BinarySection &> FunctionSection =4110        InjectedFunction->getCodeSection();4111    assert(FunctionSection && "function should have section");4112    FunctionSection->setOutputAddress(OutputAddress);4113    MapSection(*FunctionSection, OutputAddress);4114    InjectedFunction->setImageAddress(FunctionSection->getAllocAddress());4115    InjectedFunction->setImageSize(FunctionSection->getOutputSize());4116  }4117 4118  // Populate the list of sections to be allocated.4119  std::vector<BinarySection *> CodeSections = getCodeSections();4120 4121  // Remove sections that were pre-allocated (patch sections).4122  llvm::erase_if(CodeSections, [](BinarySection *Section) {4123    return Section->getOutputAddress();4124  });4125  LLVM_DEBUG(dbgs() << "Code sections in the order of output:\n";4126             for (const BinarySection *Section : CodeSections) dbgs()4127             << Section->getName() << '\n';);4128 4129  uint64_t PaddingSize = 0; // size of padding required at the end4130 4131  // Allocate sections starting at a given Address.4132  auto allocateAt = [&](uint64_t Address) {4133    const char *LastNonColdSectionName = BC->HasWarmSection4134                                             ? BC->getWarmCodeSectionName()4135                                             : BC->getMainCodeSectionName();4136    for (BinarySection *Section : CodeSections) {4137      Address = alignTo(Address, Section->getAlignment());4138      Section->setOutputAddress(Address);4139      Address += Section->getOutputSize();4140 4141      // Hugify: Additional huge page from right side due to4142      // weird ASLR mapping addresses (4KB aligned)4143      if (opts::Hugify && !BC->HasFixedLoadAddress &&4144          Section->getName() == LastNonColdSectionName)4145        Address = alignTo(Address, Section->getAlignment());4146    }4147 4148    // Make sure we allocate enough space for huge pages.4149    ErrorOr<BinarySection &> TextSection =4150        BC->getUniqueSectionByName(LastNonColdSectionName);4151    if (opts::HotText && TextSection && TextSection->hasValidSectionID()) {4152      uint64_t HotTextEnd =4153          TextSection->getOutputAddress() + TextSection->getOutputSize();4154      HotTextEnd = alignTo(HotTextEnd, BC->PageAlign);4155      if (HotTextEnd > Address) {4156        PaddingSize = HotTextEnd - Address;4157        Address = HotTextEnd;4158      }4159    }4160    return Address;4161  };4162 4163  // Try to allocate sections before the \p Address and return an address for4164  // the allocation of the first section, or 0 if [0, Address) range is not4165  // big enough to fit all sections.4166  auto allocateBefore = [&](uint64_t Address) -> uint64_t {4167    for (BinarySection *Section : llvm::reverse(CodeSections)) {4168      if (Section->getOutputSize() > Address)4169        return 0;4170      Address -= Section->getOutputSize();4171      Address = alignDown(Address, Section->getAlignment());4172      Section->setOutputAddress(Address);4173    }4174    return Address;4175  };4176 4177  // Check if we can fit code in the original .text4178  bool AllocationDone = false;4179  if (opts::UseOldText) {4180    uint64_t StartAddress;4181    uint64_t EndAddress;4182    if (opts::HotFunctionsAtEnd) {4183      EndAddress = BC->OldTextSectionAddress + BC->OldTextSectionSize;4184      StartAddress = allocateBefore(EndAddress);4185    } else {4186      StartAddress = BC->OldTextSectionAddress;4187      EndAddress = allocateAt(BC->OldTextSectionAddress);4188    }4189 4190    const uint64_t CodeSize = EndAddress - StartAddress;4191    if (CodeSize <= BC->OldTextSectionSize) {4192      BC->outs() << "BOLT-INFO: using original .text for new code with 0x"4193                 << Twine::utohexstr(opts::AlignText) << " alignment";4194      if (StartAddress != BC->OldTextSectionAddress)4195        BC->outs() << " at 0x" << Twine::utohexstr(StartAddress);4196      BC->outs() << '\n';4197      AllocationDone = true;4198    } else {4199      BC->errs() << "BOLT-WARNING: --use-old-text failed. The original .text "4200                    "too small to fit the new code using 0x"4201                 << Twine::utohexstr(opts::AlignText) << " alignment. "4202                 << CodeSize << " bytes needed, have " << BC->OldTextSectionSize4203                 << " bytes available. Rebuilding without --use-old-text may "4204                    "produce a smaller binary\n";4205      opts::UseOldText = false;4206    }4207  }4208 4209  if (!AllocationDone)4210    NextAvailableAddress = allocateAt(NextAvailableAddress);4211 4212  // Do the mapping for ORC layer based on the allocation.4213  for (BinarySection *Section : CodeSections) {4214    LLVM_DEBUG(dbgs() << "BOLT: mapping " << Section->getName() << " at 0x"4215                      << Twine::utohexstr(Section->getAllocAddress())4216                      << " to 0x"4217                      << Twine::utohexstr(Section->getOutputAddress()) << '\n');4218    MapSection(*Section, Section->getOutputAddress());4219    Section->setOutputFileOffset(4220        getFileOffsetForAddress(Section->getOutputAddress()));4221  }4222 4223  // Check if we need to insert a padding section for hot text.4224  if (PaddingSize && !opts::UseOldText)4225    BC->outs() << "BOLT-INFO: padding code to 0x"4226               << Twine::utohexstr(NextAvailableAddress)4227               << " to accommodate hot text\n";4228}4229 4230void RewriteInstance::mapCodeSectionsInPlace(4231    BOLTLinker::SectionMapper MapSection) {4232  // Processing in non-relocation mode.4233  uint64_t NewTextSectionStartAddress = NextAvailableAddress;4234 4235  for (auto &BFI : BC->getBinaryFunctions()) {4236    BinaryFunction &Function = BFI.second;4237    if (!Function.isEmitted())4238      continue;4239 4240    ErrorOr<BinarySection &> FuncSection = Function.getCodeSection();4241    assert(FuncSection && "cannot find section for function");4242    FuncSection->setOutputAddress(Function.getAddress());4243    LLVM_DEBUG(dbgs() << "BOLT: mapping 0x"4244                      << Twine::utohexstr(FuncSection->getAllocAddress())4245                      << " to 0x" << Twine::utohexstr(Function.getAddress())4246                      << '\n');4247    MapSection(*FuncSection, Function.getAddress());4248    Function.setImageAddress(FuncSection->getAllocAddress());4249    Function.setImageSize(FuncSection->getOutputSize());4250    assert(Function.getImageSize() <= Function.getMaxSize() &&4251           "Unexpected large function");4252 4253    if (!Function.isSplit())4254      continue;4255 4256    assert(Function.getLayout().isHotColdSplit() &&4257           "Cannot allocate more than two fragments per function in "4258           "non-relocation mode.");4259 4260    FunctionFragment &FF =4261        Function.getLayout().getFragment(FragmentNum::cold());4262    ErrorOr<BinarySection &> ColdSection =4263        Function.getCodeSection(FF.getFragmentNum());4264    assert(ColdSection && "cannot find section for cold part");4265    // Cold fragments are aligned at 16 bytes.4266    NextAvailableAddress = alignTo(NextAvailableAddress, 16);4267    FF.setAddress(NextAvailableAddress);4268    FF.setImageAddress(ColdSection->getAllocAddress());4269    FF.setImageSize(ColdSection->getOutputSize());4270    FF.setFileOffset(getFileOffsetForAddress(NextAvailableAddress));4271    ColdSection->setOutputAddress(FF.getAddress());4272 4273    LLVM_DEBUG(4274        dbgs() << formatv(4275            "BOLT: mapping cold fragment {0:x+} to {1:x+} with size {2:x+}\n",4276            FF.getImageAddress(), FF.getAddress(), FF.getImageSize()));4277    MapSection(*ColdSection, FF.getAddress());4278 4279    NextAvailableAddress += FF.getImageSize();4280  }4281 4282  // Add the new text section aggregating all existing code sections.4283  // This is pseudo-section that serves a purpose of creating a corresponding4284  // entry in section header table.4285  const uint64_t NewTextSectionSize =4286      NextAvailableAddress - NewTextSectionStartAddress;4287  if (NewTextSectionSize) {4288    const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true,4289                                                   /*IsText=*/true,4290                                                   /*IsAllocatable=*/true);4291    BinarySection &Section =4292      BC->registerOrUpdateSection(getBOLTTextSectionName(),4293                                  ELF::SHT_PROGBITS,4294                                  Flags,4295                                  /*Data=*/nullptr,4296                                  NewTextSectionSize,4297                                  16);4298    Section.setOutputAddress(NewTextSectionStartAddress);4299    Section.setOutputFileOffset(4300        getFileOffsetForAddress(NewTextSectionStartAddress));4301  }4302}4303 4304void RewriteInstance::mapAllocatableSections(4305    BOLTLinker::SectionMapper MapSection) {4306 4307  if (opts::UseOldText || opts::StrictMode) {4308    auto tryRewriteSection = [&](BinarySection &OldSection,4309                                 BinarySection &NewSection) {4310      if (OldSection.getSize() < NewSection.getOutputSize())4311        return;4312 4313      BC->outs() << "BOLT-INFO: rewriting " << OldSection.getName()4314                 << " in-place\n";4315 4316      NewSection.setOutputAddress(OldSection.getAddress());4317      NewSection.setOutputFileOffset(OldSection.getInputFileOffset());4318      MapSection(NewSection, OldSection.getAddress());4319 4320      // Pad contents with zeros.4321      NewSection.addPadding(OldSection.getSize() - NewSection.getOutputSize());4322 4323      // Prevent the original section name from appearing in the section header4324      // table.4325      OldSection.setAnonymous(true);4326    };4327 4328    if (EHFrameSection) {4329      BinarySection *NewEHFrameSection =4330          getSection(getNewSecPrefix() + getEHFrameSectionName());4331      assert(NewEHFrameSection && "New contents expected for .eh_frame");4332      tryRewriteSection(*EHFrameSection, *NewEHFrameSection);4333    }4334    BinarySection *EHSection = getSection(".gcc_except_table");4335    BinarySection *NewEHSection =4336        getSection(getNewSecPrefix() + ".gcc_except_table");4337    if (EHSection) {4338      assert(NewEHSection && "New contents expected for .gcc_except_table");4339      tryRewriteSection(*EHSection, *NewEHSection);4340    }4341  }4342 4343  // Allocate read-only sections first, then writable sections.4344  enum : uint8_t { ST_READONLY, ST_READWRITE };4345  for (uint8_t SType = ST_READONLY; SType <= ST_READWRITE; ++SType) {4346    const uint64_t LastNextAvailableAddress = NextAvailableAddress;4347    if (SType == ST_READWRITE) {4348      // Align R+W segment to regular page size4349      NextAvailableAddress = alignTo(NextAvailableAddress, BC->RegularPageSize);4350      NewWritableSegmentAddress = NextAvailableAddress;4351    }4352 4353    for (BinarySection &Section : BC->allocatableSections()) {4354      if (Section.isLinkOnly())4355        continue;4356 4357      if (!Section.hasValidSectionID())4358        continue;4359 4360      if (Section.isWritable() == (SType == ST_READONLY))4361        continue;4362 4363      if (Section.getOutputAddress()) {4364        LLVM_DEBUG({4365          dbgs() << "BOLT-DEBUG: section " << Section.getName()4366                 << " is already mapped at 0x"4367                 << Twine::utohexstr(Section.getOutputAddress()) << '\n';4368        });4369        continue;4370      }4371 4372      if (Section.hasSectionRef()) {4373        LLVM_DEBUG({4374          dbgs() << "BOLT-DEBUG: mapping original section " << Section.getName()4375                 << " to 0x" << Twine::utohexstr(Section.getAddress()) << '\n';4376        });4377        Section.setOutputAddress(Section.getAddress());4378        Section.setOutputFileOffset(Section.getInputFileOffset());4379        MapSection(Section, Section.getAddress());4380      } else {4381        uint64_t Alignment = Section.getAlignment();4382        if (opts::Instrument && StartLinkingRuntimeLib) {4383          Alignment = BC->RegularPageSize;4384          StartLinkingRuntimeLib = false;4385        }4386        NextAvailableAddress = alignTo(NextAvailableAddress, Alignment);4387 4388        LLVM_DEBUG({4389          dbgs() << "BOLT-DEBUG: mapping section " << Section.getName()4390                 << " (0x" << Twine::utohexstr(Section.getAllocAddress())4391                 << ") to 0x" << Twine::utohexstr(NextAvailableAddress) << ":0x"4392                 << Twine::utohexstr(NextAvailableAddress +4393                                     Section.getOutputSize())4394                 << '\n';4395        });4396 4397        MapSection(Section, NextAvailableAddress);4398        Section.setOutputAddress(NextAvailableAddress);4399        Section.setOutputFileOffset(4400            getFileOffsetForAddress(NextAvailableAddress));4401 4402        NextAvailableAddress += Section.getOutputSize();4403      }4404    }4405 4406    if (SType == ST_READONLY) {4407      if (NewTextSegmentAddress)4408        NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;4409    } else if (SType == ST_READWRITE) {4410      NewWritableSegmentSize = NextAvailableAddress - NewWritableSegmentAddress;4411      // Restore NextAvailableAddress if no new writable sections4412      if (!NewWritableSegmentSize)4413        NextAvailableAddress = LastNextAvailableAddress;4414    }4415  }4416}4417 4418void RewriteInstance::updateOutputValues(const BOLTLinker &Linker) {4419  if (std::optional<AddressMap> Map = AddressMap::parse(*BC))4420    BC->setIOAddressMap(std::move(*Map));4421 4422  for (BinaryFunction *Function : BC->getAllBinaryFunctions())4423    Function->updateOutputValues(Linker);4424}4425 4426void RewriteInstance::updateSegmentInfo() {4427  // NOTE Currently .eh_frame_hdr appends to the last segment, recalculate4428  // last segments size based on the NextAvailableAddress variable.4429  if (!NewWritableSegmentSize) {4430    if (NewTextSegmentAddress)4431      NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;4432  } else {4433    NewWritableSegmentSize = NextAvailableAddress - NewWritableSegmentAddress;4434  }4435 4436  if (NewTextSegmentSize) {4437    SegmentInfo TextSegment = {NewTextSegmentAddress,4438                               NewTextSegmentSize,4439                               NewTextSegmentOffset,4440                               NewTextSegmentSize,4441                               BC->PageAlign,4442                               true,4443                               false};4444    if (!opts::Instrument) {4445      BC->NewSegments.push_back(TextSegment);4446    } else {4447      ErrorOr<BinarySection &> Sec =4448          BC->getUniqueSectionByName(".bolt.instr.counters");4449      assert(Sec && "expected one and only one `.bolt.instr.counters` section");4450      const uint64_t Addr = Sec->getOutputAddress();4451      const uint64_t Offset = Sec->getOutputFileOffset();4452      const uint64_t Size = Sec->getOutputSize();4453      assert(Addr > TextSegment.Address &&4454             Addr + Size < TextSegment.Address + TextSegment.Size &&4455             "`.bolt.instr.counters` section is expected to be included in the "4456             "new text segment");4457 4458      // Set correct size for the previous header since we are breaking the4459      // new text segment into three segments.4460      uint64_t Delta = Addr - TextSegment.Address;4461      TextSegment.Size = Delta;4462      TextSegment.FileSize = Delta;4463      BC->NewSegments.push_back(TextSegment);4464 4465      // Create RW segment that includes the `.bolt.instr.counters` section.4466      SegmentInfo RWSegment = {Addr,  Size, Offset, Size, BC->RegularPageSize,4467                               false, true};4468      BC->NewSegments.push_back(RWSegment);4469 4470      // Create RX segment that includes all RX sections from runtime library.4471      const uint64_t AddrRX = alignTo(Addr + Size, BC->RegularPageSize);4472      const uint64_t OffsetRX = alignTo(Offset + Size, BC->RegularPageSize);4473      const uint64_t SizeRX =4474          NewTextSegmentSize - (AddrRX - TextSegment.Address);4475      SegmentInfo RXSegment = {4476          AddrRX, SizeRX, OffsetRX, SizeRX, BC->RegularPageSize, true, false};4477      BC->NewSegments.push_back(RXSegment);4478    }4479  }4480 4481  if (NewWritableSegmentSize) {4482    SegmentInfo DataSegmentInfo = {4483        NewWritableSegmentAddress,4484        NewWritableSegmentSize,4485        getFileOffsetForAddress(NewWritableSegmentAddress),4486        NewWritableSegmentSize,4487        BC->RegularPageSize,4488        false,4489        true};4490    BC->NewSegments.push_back(DataSegmentInfo);4491  }4492}4493 4494void RewriteInstance::patchELFPHDRTable() {4495  auto ELF64LEFile = cast<ELF64LEObjectFile>(InputFile);4496  const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();4497  raw_fd_ostream &OS = Out->os();4498 4499  Phnum = Obj.getHeader().e_phnum;4500 4501  if (BC->NewSegments.empty()) {4502    BC->outs() << "BOLT-INFO: not adding new segments\n";4503    return;4504  }4505 4506  if (opts::UseGnuStack) {4507    assert(!PHDRTableAddress && "unexpected address for program header table");4508    if (BC->NewSegments.size() > 1) {4509      BC->errs() << "BOLT-ERROR: unable to add writable segment\n";4510      exit(1);4511    }4512  } else {4513    Phnum += BC->NewSegments.size();4514  }4515 4516  if (!PHDRTableOffset)4517    PHDRTableOffset = Obj.getHeader().e_phoff;4518 4519  const uint64_t SavedPos = OS.tell();4520  OS.seek(PHDRTableOffset);4521 4522  auto createPhdr = [](const SegmentInfo &SI) {4523    ELF64LEPhdrTy Phdr;4524    Phdr.p_type = ELF::PT_LOAD;4525    Phdr.p_offset = SI.FileOffset;4526    Phdr.p_vaddr = SI.Address;4527    Phdr.p_paddr = SI.Address;4528    Phdr.p_filesz = SI.FileSize;4529    Phdr.p_memsz = SI.Size;4530    Phdr.p_flags = ELF::PF_R;4531    if (SI.IsExecutable)4532      Phdr.p_flags |= ELF::PF_X;4533    if (SI.IsWritable)4534      Phdr.p_flags |= ELF::PF_W;4535    Phdr.p_align = SI.Alignment;4536 4537    return Phdr;4538  };4539 4540  auto writeNewSegmentPhdrs = [&]() {4541    for (const SegmentInfo &SI : BC->NewSegments) {4542      ELF64LEPhdrTy Phdr = createPhdr(SI);4543      OS.write(reinterpret_cast<const char *>(&Phdr), sizeof(Phdr));4544    }4545  };4546 4547  bool ModdedGnuStack = false;4548  bool AddedSegment = false;4549 4550  // Copy existing program headers with modifications.4551  for (const ELF64LE::Phdr &Phdr : cantFail(Obj.program_headers())) {4552    ELF64LE::Phdr NewPhdr = Phdr;4553    switch (Phdr.p_type) {4554    case ELF::PT_PHDR:4555      if (PHDRTableAddress) {4556        NewPhdr.p_offset = PHDRTableOffset;4557        NewPhdr.p_vaddr = PHDRTableAddress;4558        NewPhdr.p_paddr = PHDRTableAddress;4559        NewPhdr.p_filesz = sizeof(NewPhdr) * Phnum;4560        NewPhdr.p_memsz = sizeof(NewPhdr) * Phnum;4561      }4562      break;4563    case ELF::PT_GNU_EH_FRAME: {4564      ErrorOr<BinarySection &> EHFrameHdrSec = BC->getUniqueSectionByName(4565          getNewSecPrefix() + getEHFrameHdrSectionName());4566      if (EHFrameHdrSec && EHFrameHdrSec->isAllocatable() &&4567          EHFrameHdrSec->isFinalized()) {4568        NewPhdr.p_offset = EHFrameHdrSec->getOutputFileOffset();4569        NewPhdr.p_vaddr = EHFrameHdrSec->getOutputAddress();4570        NewPhdr.p_paddr = EHFrameHdrSec->getOutputAddress();4571        NewPhdr.p_filesz = EHFrameHdrSec->getOutputSize();4572        NewPhdr.p_memsz = EHFrameHdrSec->getOutputSize();4573      }4574      break;4575    }4576    case ELF::PT_GNU_STACK:4577      if (opts::UseGnuStack) {4578        // Overwrite the header with the new segment header.4579        assert(BC->NewSegments.size() == 1 &&4580               "Expected exactly one new segment");4581        NewPhdr = createPhdr(BC->NewSegments.front());4582        ModdedGnuStack = true;4583      }4584      break;4585    case ELF::PT_DYNAMIC:4586      if (!opts::UseGnuStack) {4587        // Insert new headers before DYNAMIC.4588        writeNewSegmentPhdrs();4589        AddedSegment = true;4590      }4591      break;4592    }4593    OS.write(reinterpret_cast<const char *>(&NewPhdr), sizeof(NewPhdr));4594  }4595 4596  if (!opts::UseGnuStack && !AddedSegment) {4597    // Append new headers to the end of the table.4598    writeNewSegmentPhdrs();4599  }4600 4601  if (opts::UseGnuStack && !ModdedGnuStack) {4602    BC->errs()4603        << "BOLT-ERROR: could not find PT_GNU_STACK program header to modify\n";4604    exit(1);4605  }4606 4607  OS.seek(SavedPos);4608}4609 4610namespace {4611 4612/// Write padding to \p OS such that its current \p Offset becomes aligned4613/// at \p Alignment. Return new (aligned) offset.4614uint64_t appendPadding(raw_pwrite_stream &OS, uint64_t Offset,4615                       uint64_t Alignment) {4616  if (!Alignment)4617    return Offset;4618 4619  const uint64_t PaddingSize =4620      offsetToAlignment(Offset, llvm::Align(Alignment));4621  for (unsigned I = 0; I < PaddingSize; ++I)4622    OS.write((unsigned char)0);4623  return Offset + PaddingSize;4624}4625 4626}4627 4628void RewriteInstance::rewriteNoteSections() {4629  auto ELF64LEFile = cast<ELF64LEObjectFile>(InputFile);4630  const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();4631  raw_fd_ostream &OS = Out->os();4632 4633  uint64_t NextAvailableOffset = std::max(4634      getFileOffsetForAddress(NextAvailableAddress), FirstNonAllocatableOffset);4635  OS.seek(NextAvailableOffset);4636 4637  // Copy over non-allocatable section contents and update file offsets.4638  for (const ELF64LE::Shdr &Section : cantFail(Obj.sections())) {4639    if (Section.sh_type == ELF::SHT_NULL)4640      continue;4641    if (Section.sh_flags & ELF::SHF_ALLOC)4642      continue;4643 4644    SectionRef SecRef = ELF64LEFile->toSectionRef(&Section);4645    BinarySection *BSec = BC->getSectionForSectionRef(SecRef);4646    assert(BSec && !BSec->isAllocatable() &&4647           "Matching non-allocatable BinarySection should exist.");4648 4649    StringRef SectionName =4650        cantFail(Obj.getSectionName(Section), "cannot get section name");4651    if (shouldStrip(Section, SectionName))4652      continue;4653 4654    // Insert padding as needed.4655    NextAvailableOffset =4656        appendPadding(OS, NextAvailableOffset, Section.sh_addralign);4657 4658    // New section size.4659    uint64_t Size = 0;4660    bool DataWritten = false;4661    // Copy over section contents unless it's one of the sections we overwrite.4662    if (!willOverwriteSection(SectionName)) {4663      Size = Section.sh_size;4664      StringRef Dataref = InputFile->getData().substr(Section.sh_offset, Size);4665      std::string Data;4666      if (BSec->getPatcher()) {4667        Data = BSec->getPatcher()->patchBinary(Dataref);4668        Dataref = StringRef(Data);4669      }4670 4671      // Section was expanded, so need to treat it as overwrite.4672      if (Size != Dataref.size()) {4673        BSec = &BC->registerOrUpdateNoteSection(4674            SectionName, copyByteArray(Dataref), Dataref.size());4675        Size = 0;4676      } else {4677        OS << Dataref;4678        DataWritten = true;4679 4680        // Add padding as the section extension might rely on the alignment.4681        Size = appendPadding(OS, Size, Section.sh_addralign);4682      }4683    }4684 4685    // Perform section post-processing.4686    assert(BSec->getAlignment() <= Section.sh_addralign &&4687           "alignment exceeds value in file");4688 4689    if (BSec->getAllocAddress()) {4690      assert(!DataWritten && "Writing section twice.");4691      (void)DataWritten;4692      Size += BSec->write(OS);4693    }4694 4695    BSec->setOutputFileOffset(NextAvailableOffset);4696    BSec->flushPendingRelocations(OS, [this](const MCSymbol *S) {4697      return getNewValueForSymbol(S->getName());4698    });4699 4700    // Section contents are no longer needed, but we need to update the size so4701    // that it will be reflected in the section header table.4702    BSec->updateContents(nullptr, Size);4703 4704    NextAvailableOffset += Size;4705  }4706 4707  // Write new note sections.4708  for (BinarySection &Section : BC->nonAllocatableSections()) {4709    if (Section.getOutputFileOffset() || !Section.getAllocAddress())4710      continue;4711 4712    assert(!Section.hasPendingRelocations() && "cannot have pending relocs");4713 4714    NextAvailableOffset =4715        appendPadding(OS, NextAvailableOffset, Section.getAlignment());4716    Section.setOutputFileOffset(NextAvailableOffset);4717 4718    LLVM_DEBUG(4719        dbgs() << "BOLT-DEBUG: writing out new section " << Section.getName()4720               << " of size " << Section.getOutputSize() << " at offset 0x"4721               << Twine::utohexstr(Section.getOutputFileOffset()) << '\n');4722 4723    NextAvailableOffset += Section.write(OS);4724  }4725}4726 4727template <typename ELFT>4728void RewriteInstance::finalizeSectionStringTable(ELFObjectFile<ELFT> *File) {4729  // Pre-populate section header string table.4730  for (const BinarySection &Section : BC->sections())4731    if (!Section.isAnonymous())4732      SHStrTab.add(Section.getOutputName());4733  SHStrTab.finalize();4734 4735  const size_t SHStrTabSize = SHStrTab.getSize();4736  uint8_t *DataCopy = new uint8_t[SHStrTabSize];4737  memset(DataCopy, 0, SHStrTabSize);4738  SHStrTab.write(DataCopy);4739  BC->registerOrUpdateNoteSection(".shstrtab",4740                                  DataCopy,4741                                  SHStrTabSize,4742                                  /*Alignment=*/1,4743                                  /*IsReadOnly=*/true,4744                                  ELF::SHT_STRTAB);4745}4746 4747void RewriteInstance::addBoltInfoSection() {4748  std::string DescStr;4749  raw_string_ostream DescOS(DescStr);4750 4751  DescOS << "BOLT revision: " << BoltRevision << ", "4752         << "command line:";4753  for (int I = 0; I < Argc; ++I)4754    DescOS << " " << Argv[I];4755 4756  // Encode as GNU GOLD VERSION so it is easily printable by 'readelf -n'4757  const std::string BoltInfo =4758      BinarySection::encodeELFNote("GNU", DescStr, 4 /*NT_GNU_GOLD_VERSION*/);4759  BC->registerOrUpdateNoteSection(".note.bolt_info", copyByteArray(BoltInfo),4760                                  BoltInfo.size(),4761                                  /*Alignment=*/1,4762                                  /*IsReadOnly=*/true, ELF::SHT_NOTE);4763}4764 4765void RewriteInstance::addBATSection() {4766  BC->registerOrUpdateNoteSection(BoltAddressTranslation::SECTION_NAME, nullptr,4767                                  0,4768                                  /*Alignment=*/1,4769                                  /*IsReadOnly=*/true, ELF::SHT_NOTE);4770}4771 4772void RewriteInstance::encodeBATSection() {4773  std::string DescStr;4774  raw_string_ostream DescOS(DescStr);4775 4776  BAT->write(*BC, DescOS);4777 4778  const std::string BoltInfo =4779      BinarySection::encodeELFNote("BOLT", DescStr, BinarySection::NT_BOLT_BAT);4780  BC->registerOrUpdateNoteSection(BoltAddressTranslation::SECTION_NAME,4781                                  copyByteArray(BoltInfo), BoltInfo.size(),4782                                  /*Alignment=*/1,4783                                  /*IsReadOnly=*/true, ELF::SHT_NOTE);4784  BC->outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size()4785             << '\n';4786}4787 4788template <typename ELFShdrTy>4789bool RewriteInstance::shouldStrip(const ELFShdrTy &Section,4790                                  StringRef SectionName) {4791  // Strip non-allocatable relocation sections.4792  if (!(Section.sh_flags & ELF::SHF_ALLOC) && Section.sh_type == ELF::SHT_RELA)4793    return true;4794 4795  // Strip debug sections if not updating them.4796  if (isDebugSection(SectionName) && !opts::UpdateDebugSections)4797    return true;4798 4799  // Strip symtab section if needed4800  if (opts::RemoveSymtab && Section.sh_type == ELF::SHT_SYMTAB)4801    return true;4802 4803  return false;4804}4805 4806template <typename ELFT>4807std::vector<typename object::ELFObjectFile<ELFT>::Elf_Shdr>4808RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File,4809                                   std::vector<uint32_t> &NewSectionIndex) {4810  using ELFShdrTy = typename ELFObjectFile<ELFT>::Elf_Shdr;4811  const ELFFile<ELFT> &Obj = File->getELFFile();4812  typename ELFT::ShdrRange Sections = cantFail(Obj.sections());4813 4814  // Keep track of section header entries attached to the corresponding section.4815  std::vector<std::pair<BinarySection *, ELFShdrTy>> OutputSections;4816  auto addSection = [&](const ELFShdrTy &Section, BinarySection &BinSec) {4817    ELFShdrTy NewSection = Section;4818    NewSection.sh_name = SHStrTab.getOffset(BinSec.getOutputName());4819    OutputSections.emplace_back(&BinSec, std::move(NewSection));4820  };4821 4822  // Copy over entries for original allocatable sections using modified name.4823  for (const ELFShdrTy &Section : Sections) {4824    // Always ignore this section.4825    if (Section.sh_type == ELF::SHT_NULL) {4826      OutputSections.emplace_back(nullptr, Section);4827      continue;4828    }4829 4830    if (!(Section.sh_flags & ELF::SHF_ALLOC))4831      continue;4832 4833    SectionRef SecRef = File->toSectionRef(&Section);4834    BinarySection *BinSec = BC->getSectionForSectionRef(SecRef);4835    assert(BinSec && "Matching BinarySection should exist.");4836 4837    // Exclude anonymous sections.4838    if (BinSec->isAnonymous())4839      continue;4840 4841    addSection(Section, *BinSec);4842  }4843 4844  for (BinarySection &Section : BC->allocatableSections()) {4845    if (!Section.isFinalized())4846      continue;4847 4848    if (Section.hasSectionRef() || Section.isAnonymous()) {4849      if (opts::Verbosity)4850        BC->outs() << "BOLT-INFO: not writing section header for section "4851                   << Section.getOutputName() << '\n';4852      continue;4853    }4854 4855    if (opts::Verbosity >= 1)4856      BC->outs() << "BOLT-INFO: writing section header for "4857                 << Section.getOutputName() << '\n';4858    ELFShdrTy NewSection;4859    NewSection.sh_type = ELF::SHT_PROGBITS;4860    NewSection.sh_addr = Section.getOutputAddress();4861    NewSection.sh_offset = Section.getOutputFileOffset();4862    NewSection.sh_size = Section.getOutputSize();4863    NewSection.sh_entsize = 0;4864    NewSection.sh_flags = Section.getELFFlags();4865    NewSection.sh_link = 0;4866    NewSection.sh_info = 0;4867    NewSection.sh_addralign = Section.getAlignment();4868    addSection(NewSection, Section);4869  }4870 4871  // Sort all allocatable sections by their offset.4872  llvm::stable_sort(OutputSections, [](const auto &A, const auto &B) {4873    return A.second.sh_offset < B.second.sh_offset;4874  });4875 4876  // Fix section sizes to prevent overlapping.4877  ELFShdrTy *PrevSection = nullptr;4878  BinarySection *PrevBinSec = nullptr;4879  for (auto &SectionKV : OutputSections) {4880    ELFShdrTy &Section = SectionKV.second;4881 4882    // Ignore NOBITS sections as they don't take any space in the file.4883    if (Section.sh_type == ELF::SHT_NOBITS)4884      continue;4885 4886    // Note that address continuity is not guaranteed as sections could be4887    // placed in different loadable segments.4888    if (PrevSection &&4889        PrevSection->sh_offset + PrevSection->sh_size > Section.sh_offset) {4890      if (opts::Verbosity > 1)4891        BC->outs() << "BOLT-INFO: adjusting size for section "4892                   << PrevBinSec->getOutputName() << '\n';4893      PrevSection->sh_size = Section.sh_offset - PrevSection->sh_offset;4894    }4895 4896    PrevSection = &Section;4897    PrevBinSec = SectionKV.first;4898  }4899 4900  uint64_t LastFileOffset = 0;4901 4902  // Copy over entries for non-allocatable sections performing necessary4903  // adjustments.4904  for (const ELFShdrTy &Section : Sections) {4905    if (Section.sh_type == ELF::SHT_NULL)4906      continue;4907    if (Section.sh_flags & ELF::SHF_ALLOC)4908      continue;4909 4910    StringRef SectionName =4911        cantFail(Obj.getSectionName(Section), "cannot get section name");4912 4913    if (shouldStrip(Section, SectionName))4914      continue;4915 4916    SectionRef SecRef = File->toSectionRef(&Section);4917    BinarySection *BinSec = BC->getSectionForSectionRef(SecRef);4918    assert(BinSec && "Matching BinarySection should exist.");4919 4920    ELFShdrTy NewSection = Section;4921    NewSection.sh_offset = BinSec->getOutputFileOffset();4922    NewSection.sh_size = BinSec->getOutputSize();4923 4924    if (NewSection.sh_type == ELF::SHT_SYMTAB)4925      NewSection.sh_info = NumLocalSymbols;4926 4927    addSection(NewSection, *BinSec);4928 4929    LastFileOffset = BinSec->getOutputFileOffset();4930  }4931 4932  // Create entries for new non-allocatable sections.4933  for (BinarySection &Section : BC->nonAllocatableSections()) {4934    if (Section.getOutputFileOffset() <= LastFileOffset)4935      continue;4936 4937    if (opts::Verbosity >= 1)4938      BC->outs() << "BOLT-INFO: writing section header for "4939                 << Section.getOutputName() << '\n';4940 4941    ELFShdrTy NewSection;4942    NewSection.sh_type = Section.getELFType();4943    NewSection.sh_addr = 0;4944    NewSection.sh_offset = Section.getOutputFileOffset();4945    NewSection.sh_size = Section.getOutputSize();4946    NewSection.sh_entsize = 0;4947    NewSection.sh_flags = Section.getELFFlags();4948    NewSection.sh_link = 0;4949    NewSection.sh_info = 0;4950    NewSection.sh_addralign = Section.getAlignment();4951 4952    addSection(NewSection, Section);4953  }4954 4955  // Assign indices to sections.4956  for (uint32_t Index = 1; Index < OutputSections.size(); ++Index)4957    OutputSections[Index].first->setIndex(Index);4958 4959  // Update section index mapping4960  NewSectionIndex.clear();4961  NewSectionIndex.resize(Sections.size(), 0);4962  for (const ELFShdrTy &Section : Sections) {4963    if (Section.sh_type == ELF::SHT_NULL)4964      continue;4965 4966    size_t OrgIndex = std::distance(Sections.begin(), &Section);4967 4968    SectionRef SecRef = File->toSectionRef(&Section);4969    BinarySection *BinSec = BC->getSectionForSectionRef(SecRef);4970    assert(BinSec && "BinarySection should exist for an input section.");4971 4972    // Some sections are stripped4973    if (!BinSec->hasValidIndex())4974      continue;4975 4976    NewSectionIndex[OrgIndex] = BinSec->getIndex();4977  }4978 4979  std::vector<ELFShdrTy> SectionsOnly(OutputSections.size());4980  llvm::copy(llvm::make_second_range(OutputSections), SectionsOnly.begin());4981 4982  return SectionsOnly;4983}4984 4985// Rewrite section header table inserting new entries as needed. The sections4986// header table size itself may affect the offsets of other sections,4987// so we are placing it at the end of the binary.4988//4989// As we rewrite entries we need to track how many sections were inserted4990// as it changes the sh_link value. We map old indices to new ones for4991// existing sections.4992template <typename ELFT>4993void RewriteInstance::patchELFSectionHeaderTable(ELFObjectFile<ELFT> *File) {4994  using ELFShdrTy = typename ELFObjectFile<ELFT>::Elf_Shdr;4995  using ELFEhdrTy = typename ELFObjectFile<ELFT>::Elf_Ehdr;4996  raw_fd_ostream &OS = Out->os();4997  const ELFFile<ELFT> &Obj = File->getELFFile();4998 4999  // Mapping from old section indices to new ones5000  std::vector<uint32_t> NewSectionIndex;5001  std::vector<ELFShdrTy> OutputSections =5002      getOutputSections(File, NewSectionIndex);5003  LLVM_DEBUG(5004    dbgs() << "BOLT-DEBUG: old to new section index mapping:\n";5005    for (uint64_t I = 0; I < NewSectionIndex.size(); ++I)5006      dbgs() << "  " << I << " -> " << NewSectionIndex[I] << '\n';5007  );5008 5009  // Align starting address for section header table. There's no architecutal5010  // need to align this, it is just for pleasant human readability.5011  uint64_t SHTOffset = OS.tell();5012  SHTOffset = appendPadding(OS, SHTOffset, 16);5013 5014  // Write all section header entries while patching section references.5015  for (ELFShdrTy &Section : OutputSections) {5016    Section.sh_link = NewSectionIndex[Section.sh_link];5017    if (Section.sh_type == ELF::SHT_REL || Section.sh_type == ELF::SHT_RELA)5018      Section.sh_info = NewSectionIndex[Section.sh_info];5019    OS.write(reinterpret_cast<const char *>(&Section), sizeof(Section));5020  }5021 5022  // Fix ELF header.5023  ELFEhdrTy NewEhdr = Obj.getHeader();5024 5025  if (BC->HasRelocations) {5026    RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary();5027    if (RtLibrary && opts::RuntimeLibInitHook == opts::RLIH_ENTRY_POINT) {5028      NewEhdr.e_entry = RtLibrary->getRuntimeStartAddress();5029      BC->outs()5030          << "BOLT-INFO: runtime library initialization was hooked via ELF "5031             "Header Entry Point, set to 0x"5032          << Twine::utohexstr(NewEhdr.e_entry) << "\n";5033    } else5034      NewEhdr.e_entry = getNewFunctionAddress(NewEhdr.e_entry);5035    assert((NewEhdr.e_entry || !Obj.getHeader().e_entry) &&5036           "cannot find new address for entry point");5037  }5038  if (PHDRTableOffset) {5039    NewEhdr.e_phoff = PHDRTableOffset;5040    NewEhdr.e_phnum = Phnum;5041  }5042  NewEhdr.e_shoff = SHTOffset;5043  NewEhdr.e_shnum = OutputSections.size();5044  NewEhdr.e_shstrndx = NewSectionIndex[NewEhdr.e_shstrndx];5045  OS.pwrite(reinterpret_cast<const char *>(&NewEhdr), sizeof(NewEhdr), 0);5046}5047 5048template <typename ELFT, typename WriteFuncTy, typename StrTabFuncTy>5049void RewriteInstance::updateELFSymbolTable(5050    ELFObjectFile<ELFT> *File, bool IsDynSym,5051    const typename object::ELFObjectFile<ELFT>::Elf_Shdr &SymTabSection,5052    const std::vector<uint32_t> &NewSectionIndex, WriteFuncTy Write,5053    StrTabFuncTy AddToStrTab) {5054  const ELFFile<ELFT> &Obj = File->getELFFile();5055  using ELFSymTy = typename ELFObjectFile<ELFT>::Elf_Sym;5056 5057  StringRef StringSection =5058      cantFail(Obj.getStringTableForSymtab(SymTabSection));5059 5060  unsigned NumHotTextSymsUpdated = 0;5061  unsigned NumHotDataSymsUpdated = 0;5062 5063  std::map<const BinaryFunction *, uint64_t> IslandSizes;5064  auto getConstantIslandSize = [&IslandSizes](const BinaryFunction &BF) {5065    auto Itr = IslandSizes.find(&BF);5066    if (Itr != IslandSizes.end())5067      return Itr->second;5068    return IslandSizes[&BF] = BF.estimateConstantIslandSize();5069  };5070 5071  // Symbols for the new symbol table.5072  std::vector<ELFSymTy> Symbols;5073 5074  bool EmittedColdFileSymbol = false;5075 5076  auto getNewSectionIndex = [&](uint32_t OldIndex) {5077    // For dynamic symbol table, the section index could be wrong on the input,5078    // and its value is ignored by the runtime if it's different from5079    // SHN_UNDEF and SHN_ABS.5080    // However, we still need to update dynamic symbol table, so return a5081    // section index, even though the index is broken.5082    if (IsDynSym && OldIndex >= NewSectionIndex.size())5083      return OldIndex;5084 5085    assert(OldIndex < NewSectionIndex.size() && "section index out of bounds");5086    const uint32_t NewIndex = NewSectionIndex[OldIndex];5087 5088    // We may have stripped the section that dynsym was referencing due to5089    // the linker bug. In that case return the old index avoiding marking5090    // the symbol as undefined.5091    if (IsDynSym && NewIndex != OldIndex && NewIndex == ELF::SHN_UNDEF)5092      return OldIndex;5093    return NewIndex;5094  };5095 5096  // Get the extra symbol name of a split fragment; used in addExtraSymbols.5097  auto getSplitSymbolName = [&](const FunctionFragment &FF,5098                                const ELFSymTy &FunctionSymbol) {5099    SmallString<256> SymbolName;5100    if (BC->HasWarmSection)5101      SymbolName =5102          formatv("{0}.{1}", cantFail(FunctionSymbol.getName(StringSection)),5103                  FF.getFragmentNum() == FragmentNum::warm() ? "warm" : "cold");5104    else5105      SymbolName = formatv("{0}.cold.{1}",5106                           cantFail(FunctionSymbol.getName(StringSection)),5107                           FF.getFragmentNum().get() - 1);5108    return SymbolName;5109  };5110 5111  // Add extra symbols for the function.5112  //5113  // Note that addExtraSymbols() could be called multiple times for the same5114  // function with different FunctionSymbol matching the main function entry5115  // point.5116  auto addExtraSymbols = [&](const BinaryFunction &Function,5117                             const ELFSymTy &FunctionSymbol) {5118    if (Function.isFolded()) {5119      BinaryFunction *ICFParent = Function.getFoldedIntoFunction();5120      while (ICFParent->isFolded())5121        ICFParent = ICFParent->getFoldedIntoFunction();5122      ELFSymTy ICFSymbol = FunctionSymbol;5123      SmallVector<char, 256> Buf;5124      ICFSymbol.st_name =5125          AddToStrTab(Twine(cantFail(FunctionSymbol.getName(StringSection)))5126                          .concat(".icf.0")5127                          .toStringRef(Buf));5128      ICFSymbol.st_value = ICFParent->getOutputAddress();5129      ICFSymbol.st_size = ICFParent->getOutputSize();5130      ICFSymbol.st_shndx = ICFParent->getCodeSection()->getIndex();5131      Symbols.emplace_back(ICFSymbol);5132    }5133    if (Function.isSplit()) {5134      // Prepend synthetic FILE symbol to prevent local cold fragments from5135      // colliding with existing symbols with the same name.5136      if (!EmittedColdFileSymbol &&5137          FunctionSymbol.getBinding() == ELF::STB_GLOBAL) {5138        ELFSymTy FileSymbol;5139        FileSymbol.st_shndx = ELF::SHN_ABS;5140        FileSymbol.st_name = AddToStrTab(getBOLTFileSymbolName());5141        FileSymbol.st_value = 0;5142        FileSymbol.st_size = 0;5143        FileSymbol.st_other = 0;5144        FileSymbol.setBindingAndType(ELF::STB_LOCAL, ELF::STT_FILE);5145        Symbols.emplace_back(FileSymbol);5146        EmittedColdFileSymbol = true;5147      }5148      for (const FunctionFragment &FF :5149           Function.getLayout().getSplitFragments()) {5150        if (FF.getAddress()) {5151          ELFSymTy NewColdSym = FunctionSymbol;5152          const SmallString<256> SymbolName =5153              getSplitSymbolName(FF, FunctionSymbol);5154          NewColdSym.st_name = AddToStrTab(SymbolName);5155          NewColdSym.st_shndx =5156              Function.getCodeSection(FF.getFragmentNum())->getIndex();5157          NewColdSym.st_value = FF.getAddress();5158          NewColdSym.st_size = FF.getImageSize();5159          NewColdSym.setBindingAndType(ELF::STB_LOCAL, ELF::STT_FUNC);5160          Symbols.emplace_back(NewColdSym);5161        }5162      }5163    }5164    if (Function.hasConstantIsland()) {5165      uint64_t DataMark = Function.getOutputDataAddress();5166      uint64_t CISize = getConstantIslandSize(Function);5167      uint64_t CodeMark = DataMark + CISize;5168      ELFSymTy DataMarkSym = FunctionSymbol;5169      DataMarkSym.st_name = AddToStrTab("$d");5170      DataMarkSym.st_value = DataMark;5171      DataMarkSym.st_size = 0;5172      DataMarkSym.setType(ELF::STT_NOTYPE);5173      DataMarkSym.setBinding(ELF::STB_LOCAL);5174      ELFSymTy CodeMarkSym = DataMarkSym;5175      CodeMarkSym.st_name = AddToStrTab("$x");5176      CodeMarkSym.st_value = CodeMark;5177      Symbols.emplace_back(DataMarkSym);5178      Symbols.emplace_back(CodeMarkSym);5179    }5180    if (Function.hasConstantIsland() && Function.isSplit()) {5181      uint64_t DataMark = Function.getOutputColdDataAddress();5182      uint64_t CISize = getConstantIslandSize(Function);5183      uint64_t CodeMark = DataMark + CISize;5184      ELFSymTy DataMarkSym = FunctionSymbol;5185      DataMarkSym.st_name = AddToStrTab("$d");5186      DataMarkSym.st_value = DataMark;5187      DataMarkSym.st_size = 0;5188      DataMarkSym.setType(ELF::STT_NOTYPE);5189      DataMarkSym.setBinding(ELF::STB_LOCAL);5190      ELFSymTy CodeMarkSym = DataMarkSym;5191      CodeMarkSym.st_name = AddToStrTab("$x");5192      CodeMarkSym.st_value = CodeMark;5193      Symbols.emplace_back(DataMarkSym);5194      Symbols.emplace_back(CodeMarkSym);5195    }5196  };5197 5198  // For regular (non-dynamic) symbol table, exclude symbols referring5199  // to non-allocatable sections.5200  auto shouldStrip = [&](const ELFSymTy &Symbol) {5201    if (Symbol.isAbsolute() || !Symbol.isDefined())5202      return false;5203 5204    // If we cannot link the symbol to a section, leave it as is.5205    Expected<const typename ELFT::Shdr *> Section =5206        Obj.getSection(Symbol.st_shndx);5207    if (!Section)5208      return false;5209 5210    // Remove the section symbol if the corresponding section was stripped.5211    if (Symbol.getType() == ELF::STT_SECTION) {5212      if (!getNewSectionIndex(Symbol.st_shndx))5213        return true;5214      return false;5215    }5216 5217    // Symbols in non-allocatable sections are typically remnants of relocations5218    // emitted under "-emit-relocs" linker option. Delete those as we delete5219    // relocations against non-allocatable sections.5220    if (!((*Section)->sh_flags & ELF::SHF_ALLOC))5221      return true;5222 5223    return false;5224  };5225 5226  for (const ELFSymTy &Symbol : cantFail(Obj.symbols(&SymTabSection))) {5227    // For regular (non-dynamic) symbol table strip unneeded symbols.5228    if (!IsDynSym && shouldStrip(Symbol))5229      continue;5230 5231    const BinaryFunction *Function =5232        BC->getBinaryFunctionAtAddress(Symbol.st_value);5233    // Ignore false function references, e.g. when the section address matches5234    // the address of the function.5235    if (Function && Symbol.getType() == ELF::STT_SECTION)5236      Function = nullptr;5237 5238    // For non-dynamic symtab, make sure the symbol section matches that of5239    // the function. It can mismatch e.g. if the symbol is a section marker5240    // in which case we treat the symbol separately from the function.5241    // For dynamic symbol table, the section index could be wrong on the input,5242    // and its value is ignored by the runtime if it's different from5243    // SHN_UNDEF and SHN_ABS.5244    if (!IsDynSym && Function &&5245        Symbol.st_shndx !=5246            Function->getOriginSection()->getSectionRef().getIndex())5247      Function = nullptr;5248 5249    // Create a new symbol based on the existing symbol.5250    ELFSymTy NewSymbol = Symbol;5251 5252    // Handle special symbols based on their name.5253    Expected<StringRef> SymbolName = Symbol.getName(StringSection);5254    assert(SymbolName && "cannot get symbol name");5255 5256    auto updateSymbolValue = [&](const StringRef Name,5257                                 std::optional<uint64_t> Value = std::nullopt) {5258      NewSymbol.st_value = Value ? *Value : getNewValueForSymbol(Name);5259      NewSymbol.st_shndx = ELF::SHN_ABS;5260      BC->outs() << "BOLT-INFO: setting " << Name << " to 0x"5261                 << Twine::utohexstr(NewSymbol.st_value) << '\n';5262    };5263 5264    if (*SymbolName == "__hot_start" || *SymbolName == "__hot_end") {5265      if (opts::HotText) {5266        updateSymbolValue(*SymbolName);5267        ++NumHotTextSymsUpdated;5268      }5269      goto registerSymbol;5270    }5271 5272    if (*SymbolName == "__hot_data_start" || *SymbolName == "__hot_data_end") {5273      if (opts::HotData) {5274        updateSymbolValue(*SymbolName);5275        ++NumHotDataSymsUpdated;5276      }5277      goto registerSymbol;5278    }5279 5280    if (*SymbolName == "_end") {5281      if (NextAvailableAddress > Symbol.st_value)5282        updateSymbolValue(*SymbolName, NextAvailableAddress);5283      goto registerSymbol;5284    }5285 5286    if (Function) {5287      // If the symbol matched a function that was not emitted, update the5288      // corresponding section index but otherwise leave it unchanged.5289      if (Function->isEmitted()) {5290        NewSymbol.st_value = Function->getOutputAddress();5291        NewSymbol.st_size = Function->getOutputSize();5292        NewSymbol.st_shndx = Function->getCodeSection()->getIndex();5293      } else if (Symbol.st_shndx < ELF::SHN_LORESERVE) {5294        NewSymbol.st_shndx = getNewSectionIndex(Symbol.st_shndx);5295      }5296 5297      // Add new symbols to the symbol table if necessary.5298      if (!IsDynSym)5299        addExtraSymbols(*Function, NewSymbol);5300    } else {5301      // Check if the function symbol matches address inside a function, i.e.5302      // it marks a secondary entry point.5303      Function =5304          (Symbol.getType() == ELF::STT_FUNC)5305              ? BC->getBinaryFunctionContainingAddress(Symbol.st_value,5306                                                       /*CheckPastEnd=*/false,5307                                                       /*UseMaxSize=*/true)5308              : nullptr;5309 5310      if (Function && Function->isEmitted()) {5311        assert(Function->getLayout().isHotColdSplit() &&5312               "Adding symbols based on cold fragment when there are more than "5313               "2 fragments");5314        const uint64_t OutputAddress =5315            Function->translateInputToOutputAddress(Symbol.st_value);5316 5317        NewSymbol.st_value = OutputAddress;5318        // Force secondary entry points to have zero size.5319        NewSymbol.st_size = 0;5320 5321        // Find fragment containing entrypoint5322        FunctionLayout::fragment_const_iterator FF = llvm::find_if(5323            Function->getLayout().fragments(), [&](const FunctionFragment &FF) {5324              uint64_t Lo = FF.getAddress();5325              uint64_t Hi = Lo + FF.getImageSize();5326              return Lo <= OutputAddress && OutputAddress < Hi;5327            });5328 5329        if (FF == Function->getLayout().fragment_end()) {5330          assert(5331              OutputAddress >= Function->getCodeSection()->getOutputAddress() &&5332              OutputAddress < (Function->getCodeSection()->getOutputAddress() +5333                               Function->getCodeSection()->getOutputSize()) &&5334              "Cannot locate fragment containing secondary entrypoint");5335          FF = Function->getLayout().fragment_begin();5336        }5337 5338        NewSymbol.st_shndx =5339            Function->getCodeSection(FF->getFragmentNum())->getIndex();5340      } else {5341        // Check if the symbol belongs to moved data object and update it.5342        BinaryData *BD = opts::ReorderData.empty()5343                             ? nullptr5344                             : BC->getBinaryDataAtAddress(Symbol.st_value);5345        if (BD && BD->isMoved() && !BD->isJumpTable()) {5346          assert((!BD->getSize() || !Symbol.st_size ||5347                  Symbol.st_size == BD->getSize()) &&5348                 "sizes must match");5349 5350          BinarySection &OutputSection = BD->getOutputSection();5351          assert(OutputSection.getIndex());5352          LLVM_DEBUG(dbgs()5353                     << "BOLT-DEBUG: moving " << BD->getName() << " from "5354                     << *BC->getSectionNameForAddress(Symbol.st_value) << " ("5355                     << Symbol.st_shndx << ") to " << OutputSection.getName()5356                     << " (" << OutputSection.getIndex() << ")\n");5357          NewSymbol.st_shndx = OutputSection.getIndex();5358          NewSymbol.st_value = BD->getOutputAddress();5359        } else {5360          // Otherwise just update the section for the symbol.5361          if (Symbol.st_shndx < ELF::SHN_LORESERVE)5362            NewSymbol.st_shndx = getNewSectionIndex(Symbol.st_shndx);5363        }5364 5365        // Detect local syms in the text section that we didn't update5366        // and that were preserved by the linker to support relocations against5367        // .text. Remove them from the symtab.5368        if (Symbol.getType() == ELF::STT_NOTYPE &&5369            Symbol.getBinding() == ELF::STB_LOCAL && Symbol.st_size == 0) {5370          if (BC->getBinaryFunctionContainingAddress(Symbol.st_value,5371                                                     /*CheckPastEnd=*/false,5372                                                     /*UseMaxSize=*/true)) {5373            // Can only delete the symbol if not patching. Such symbols should5374            // not exist in the dynamic symbol table.5375            assert(!IsDynSym && "cannot delete symbol");5376            continue;5377          }5378        }5379      }5380    }5381 5382  registerSymbol:5383    if (IsDynSym)5384      Write((&Symbol - cantFail(Obj.symbols(&SymTabSection)).begin()) *5385                sizeof(ELFSymTy),5386            NewSymbol);5387    else5388      Symbols.emplace_back(NewSymbol);5389  }5390 5391  if (IsDynSym) {5392    assert(Symbols.empty());5393    return;5394  }5395 5396  // Add symbols of injected functions5397  for (BinaryFunction *Function : BC->getInjectedBinaryFunctions()) {5398    if (Function->isAnonymous())5399      continue;5400    ELFSymTy NewSymbol;5401    BinarySection *OriginSection = Function->getOriginSection();5402    NewSymbol.st_shndx =5403        OriginSection5404            ? getNewSectionIndex(OriginSection->getSectionRef().getIndex())5405            : Function->getCodeSection()->getIndex();5406    NewSymbol.st_value = Function->getOutputAddress();5407    NewSymbol.st_name = AddToStrTab(Function->getOneName());5408    NewSymbol.st_size = Function->getOutputSize();5409    NewSymbol.st_other = 0;5410    NewSymbol.setBindingAndType(ELF::STB_LOCAL, ELF::STT_FUNC);5411    Symbols.emplace_back(NewSymbol);5412 5413    if (Function->isSplit()) {5414      assert(Function->getLayout().isHotColdSplit() &&5415             "Adding symbols based on cold fragment when there are more than "5416             "2 fragments");5417      ELFSymTy NewColdSym = NewSymbol;5418      NewColdSym.setType(ELF::STT_NOTYPE);5419      SmallVector<char, 256> Buf;5420      NewColdSym.st_name = AddToStrTab(5421          Twine(Function->getPrintName()).concat(".cold.0").toStringRef(Buf));5422      const FunctionFragment &ColdFF =5423          Function->getLayout().getFragment(FragmentNum::cold());5424      NewColdSym.st_value = ColdFF.getAddress();5425      NewColdSym.st_size = ColdFF.getImageSize();5426      Symbols.emplace_back(NewColdSym);5427    }5428  }5429 5430  auto AddSymbol = [&](const StringRef &Name, uint64_t Address) {5431    if (!Address)5432      return;5433 5434    ELFSymTy Symbol;5435    Symbol.st_value = Address;5436    Symbol.st_shndx = ELF::SHN_ABS;5437    Symbol.st_name = AddToStrTab(Name);5438    Symbol.st_size = 0;5439    Symbol.st_other = 0;5440    Symbol.setBindingAndType(ELF::STB_WEAK, ELF::STT_NOTYPE);5441 5442    BC->outs() << "BOLT-INFO: setting " << Name << " to 0x"5443               << Twine::utohexstr(Symbol.st_value) << '\n';5444 5445    Symbols.emplace_back(Symbol);5446  };5447 5448  // Add runtime library start and fini address symbols5449  if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary()) {5450    AddSymbol("__bolt_runtime_start", RtLibrary->getRuntimeStartAddress());5451    AddSymbol("__bolt_runtime_fini", RtLibrary->getRuntimeFiniAddress());5452  }5453 5454  assert((!NumHotTextSymsUpdated || NumHotTextSymsUpdated == 2) &&5455         "either none or both __hot_start/__hot_end symbols were expected");5456  assert((!NumHotDataSymsUpdated || NumHotDataSymsUpdated == 2) &&5457         "either none or both __hot_data_start/__hot_data_end symbols were "5458         "expected");5459 5460  auto AddEmittedSymbol = [&](const StringRef &Name) {5461    AddSymbol(Name, getNewValueForSymbol(Name));5462  };5463 5464  if (opts::HotText && !NumHotTextSymsUpdated) {5465    AddEmittedSymbol("__hot_start");5466    AddEmittedSymbol("__hot_end");5467  }5468 5469  if (opts::HotData && !NumHotDataSymsUpdated) {5470    AddEmittedSymbol("__hot_data_start");5471    AddEmittedSymbol("__hot_data_end");5472  }5473 5474  // Put local symbols at the beginning.5475  llvm::stable_sort(Symbols, [](const ELFSymTy &A, const ELFSymTy &B) {5476    if (A.getBinding() == ELF::STB_LOCAL && B.getBinding() != ELF::STB_LOCAL)5477      return true;5478    return false;5479  });5480 5481  for (const ELFSymTy &Symbol : Symbols)5482    Write(0, Symbol);5483}5484 5485template <typename ELFT>5486void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {5487  const ELFFile<ELFT> &Obj = File->getELFFile();5488  using ELFShdrTy = typename ELFObjectFile<ELFT>::Elf_Shdr;5489  using ELFSymTy = typename ELFObjectFile<ELFT>::Elf_Sym;5490 5491  // Compute a preview of how section indices will change after rewriting, so5492  // we can properly update the symbol table based on new section indices.5493  std::vector<uint32_t> NewSectionIndex;5494  getOutputSections(File, NewSectionIndex);5495 5496  // Update dynamic symbol table.5497  const ELFShdrTy *DynSymSection = nullptr;5498  for (const ELFShdrTy &Section : cantFail(Obj.sections())) {5499    if (Section.sh_type == ELF::SHT_DYNSYM) {5500      DynSymSection = &Section;5501      break;5502    }5503  }5504  assert((DynSymSection || BC->IsStaticExecutable) &&5505         "dynamic symbol table expected");5506  if (DynSymSection) {5507    updateELFSymbolTable(5508        File,5509        /*IsDynSym=*/true,5510        *DynSymSection,5511        NewSectionIndex,5512        [&](size_t Offset, const ELFSymTy &Sym) {5513          Out->os().pwrite(reinterpret_cast<const char *>(&Sym),5514                           sizeof(ELFSymTy),5515                           DynSymSection->sh_offset + Offset);5516        },5517        [](StringRef) -> size_t { return 0; });5518  }5519 5520  if (opts::RemoveSymtab)5521    return;5522 5523  // (re)create regular symbol table.5524  const ELFShdrTy *SymTabSection = nullptr;5525  for (const ELFShdrTy &Section : cantFail(Obj.sections())) {5526    if (Section.sh_type == ELF::SHT_SYMTAB) {5527      SymTabSection = &Section;5528      break;5529    }5530  }5531  if (!SymTabSection) {5532    BC->errs() << "BOLT-WARNING: no symbol table found\n";5533    return;5534  }5535 5536  const ELFShdrTy *StrTabSection =5537      cantFail(Obj.getSection(SymTabSection->sh_link));5538  std::string NewContents;5539  std::string NewStrTab = std::string(5540      File->getData().substr(StrTabSection->sh_offset, StrTabSection->sh_size));5541  StringRef SecName = cantFail(Obj.getSectionName(*SymTabSection));5542  StringRef StrSecName = cantFail(Obj.getSectionName(*StrTabSection));5543 5544  NumLocalSymbols = 0;5545  updateELFSymbolTable(5546      File,5547      /*IsDynSym=*/false,5548      *SymTabSection,5549      NewSectionIndex,5550      [&](size_t Offset, const ELFSymTy &Sym) {5551        if (Sym.getBinding() == ELF::STB_LOCAL)5552          ++NumLocalSymbols;5553        NewContents.append(reinterpret_cast<const char *>(&Sym),5554                           sizeof(ELFSymTy));5555      },5556      [&](StringRef Str) {5557        size_t Idx = NewStrTab.size();5558        NewStrTab.append(NameResolver::restore(Str).str());5559        NewStrTab.append(1, '\0');5560        return Idx;5561      });5562 5563  BC->registerOrUpdateNoteSection(SecName,5564                                  copyByteArray(NewContents),5565                                  NewContents.size(),5566                                  /*Alignment=*/1,5567                                  /*IsReadOnly=*/true,5568                                  ELF::SHT_SYMTAB);5569 5570  BC->registerOrUpdateNoteSection(StrSecName,5571                                  copyByteArray(NewStrTab),5572                                  NewStrTab.size(),5573                                  /*Alignment=*/1,5574                                  /*IsReadOnly=*/true,5575                                  ELF::SHT_STRTAB);5576}5577 5578template <typename ELFT>5579void RewriteInstance::patchELFAllocatableRelrSection(5580    ELFObjectFile<ELFT> *File) {5581  if (!DynamicRelrAddress)5582    return;5583 5584  raw_fd_ostream &OS = Out->os();5585  const uint8_t PSize = BC->AsmInfo->getCodePointerSize();5586  const uint64_t MaxDelta = ((CHAR_BIT * DynamicRelrEntrySize) - 1) * PSize;5587 5588  auto FixAddend = [&](const BinarySection &Section, const Relocation &Rel,5589                       uint64_t FileOffset) {5590    // Fix relocation symbol value in place if no static relocation found5591    // on the same address. We won't check the BF relocations here since it5592    // is rare case and no optimization is required.5593    if (Section.getRelocationAt(Rel.Offset))5594      return;5595 5596    // No fixup needed if symbol address was not changed5597    const uint64_t Addend = getNewFunctionOrDataAddress(Rel.Addend);5598    if (!Addend)5599      return;5600 5601    OS.pwrite(reinterpret_cast<const char *>(&Addend), PSize, FileOffset);5602  };5603 5604  // Fill new relative relocation offsets set5605  std::set<uint64_t> RelOffsets;5606  for (const BinarySection &Section : BC->allocatableSections()) {5607    const uint64_t SectionInputAddress = Section.getAddress();5608    uint64_t SectionAddress = Section.getOutputAddress();5609    if (!SectionAddress)5610      SectionAddress = SectionInputAddress;5611 5612    for (const Relocation &Rel : Section.dynamicRelocations()) {5613      if (!Rel.isRelative())5614        continue;5615 5616      uint64_t RelOffset =5617          getNewFunctionOrDataAddress(SectionInputAddress + Rel.Offset);5618 5619      RelOffset = RelOffset == 0 ? SectionAddress + Rel.Offset : RelOffset;5620      assert((RelOffset & 1) == 0 && "Wrong relocation offset");5621      RelOffsets.emplace(RelOffset);5622      FixAddend(Section, Rel, RelOffset);5623    }5624  }5625 5626  ErrorOr<BinarySection &> Section =5627      BC->getSectionForAddress(*DynamicRelrAddress);5628  assert(Section && "cannot get .relr.dyn section");5629  assert(Section->isRelr() && "Expected section to be SHT_RELR type");5630  uint64_t RelrDynOffset = Section->getInputFileOffset();5631  const uint64_t RelrDynEndOffset = RelrDynOffset + Section->getSize();5632 5633  auto WriteRelr = [&](uint64_t Value) {5634    if (RelrDynOffset + DynamicRelrEntrySize > RelrDynEndOffset) {5635      BC->errs() << "BOLT-ERROR: Offset overflow for relr.dyn section\n";5636      exit(1);5637    }5638 5639    OS.pwrite(reinterpret_cast<const char *>(&Value), DynamicRelrEntrySize,5640              RelrDynOffset);5641    RelrDynOffset += DynamicRelrEntrySize;5642  };5643 5644  for (auto RelIt = RelOffsets.begin(); RelIt != RelOffsets.end();) {5645    WriteRelr(*RelIt);5646    uint64_t Base = *RelIt++ + PSize;5647    while (1) {5648      uint64_t Bitmap = 0;5649      for (; RelIt != RelOffsets.end(); ++RelIt) {5650        const uint64_t Delta = *RelIt - Base;5651        if (Delta >= MaxDelta || Delta % PSize)5652          break;5653 5654        Bitmap |= (1ULL << (Delta / PSize));5655      }5656 5657      if (!Bitmap)5658        break;5659 5660      WriteRelr((Bitmap << 1) | 1);5661      Base += MaxDelta;5662    }5663  }5664 5665  // Fill the rest of the section with empty bitmap value5666  while (RelrDynOffset != RelrDynEndOffset)5667    WriteRelr(1);5668}5669 5670template <typename ELFT>5671void5672RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {5673  using Elf_Rela = typename ELFT::Rela;5674  raw_fd_ostream &OS = Out->os();5675  const ELFFile<ELFT> &EF = File->getELFFile();5676 5677  uint64_t RelDynOffset = 0, RelDynEndOffset = 0;5678  uint64_t RelPltOffset = 0, RelPltEndOffset = 0;5679 5680  auto setSectionFileOffsets = [&](uint64_t Address, uint64_t &Start,5681                                   uint64_t &End) {5682    ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);5683    assert(Section && "cannot get relocation section");5684    Start = Section->getInputFileOffset();5685    End = Start + Section->getSize();5686  };5687 5688  if (!DynamicRelocationsAddress && !PLTRelocationsAddress)5689    return;5690 5691  if (DynamicRelocationsAddress)5692    setSectionFileOffsets(*DynamicRelocationsAddress, RelDynOffset,5693                          RelDynEndOffset);5694 5695  if (PLTRelocationsAddress)5696    setSectionFileOffsets(*PLTRelocationsAddress, RelPltOffset,5697                          RelPltEndOffset);5698 5699  DynamicRelativeRelocationsCount = 0;5700 5701  auto writeRela = [&OS](const Elf_Rela *RelA, uint64_t &Offset) {5702    OS.pwrite(reinterpret_cast<const char *>(RelA), sizeof(*RelA), Offset);5703    Offset += sizeof(*RelA);5704  };5705 5706  auto writeRelocations = [&](bool PatchRelative) {5707    for (BinarySection &Section : BC->allocatableSections()) {5708      const uint64_t SectionInputAddress = Section.getAddress();5709      uint64_t SectionAddress = Section.getOutputAddress();5710      if (!SectionAddress)5711        SectionAddress = SectionInputAddress;5712 5713      for (const Relocation &Rel : Section.dynamicRelocations()) {5714        const bool IsRelative = Rel.isRelative();5715        if (PatchRelative != IsRelative)5716          continue;5717 5718        if (IsRelative)5719          ++DynamicRelativeRelocationsCount;5720 5721        Elf_Rela NewRelA;5722        MCSymbol *Symbol = Rel.Symbol;5723        uint32_t SymbolIdx = 0;5724        uint64_t Addend = Rel.Addend;5725        uint64_t RelOffset =5726            getNewFunctionOrDataAddress(SectionInputAddress + Rel.Offset);5727 5728        RelOffset = RelOffset == 0 ? SectionAddress + Rel.Offset : RelOffset;5729        if (Rel.Symbol) {5730          SymbolIdx = getOutputDynamicSymbolIndex(Symbol);5731        } else {5732          // Usually this case is used for R_*_(I)RELATIVE relocations5733          const uint64_t Address = getNewFunctionOrDataAddress(Addend);5734          if (Address)5735            Addend = Address;5736        }5737 5738        NewRelA.setSymbolAndType(SymbolIdx, Rel.Type, EF.isMips64EL());5739        NewRelA.r_offset = RelOffset;5740        NewRelA.r_addend = Addend;5741 5742        const bool IsJmpRel = IsJmpRelocation.contains(Rel.Type);5743        uint64_t &Offset = IsJmpRel ? RelPltOffset : RelDynOffset;5744        const uint64_t &EndOffset =5745            IsJmpRel ? RelPltEndOffset : RelDynEndOffset;5746        if (!Offset || !EndOffset) {5747          BC->errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n";5748          exit(1);5749        }5750 5751        if (Offset + sizeof(NewRelA) > EndOffset) {5752          BC->errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n";5753          exit(1);5754        }5755 5756        writeRela(&NewRelA, Offset);5757      }5758    }5759  };5760 5761  // Place R_*_RELATIVE relocations in RELA section if RELR is not presented.5762  // The dynamic linker expects all R_*_RELATIVE relocations in RELA5763  // to be emitted first.5764  if (!DynamicRelrAddress)5765    writeRelocations(/* PatchRelative */ true);5766  writeRelocations(/* PatchRelative */ false);5767 5768  auto fillNone = [&](uint64_t &Offset, uint64_t EndOffset) {5769    if (!Offset)5770      return;5771 5772    typename ELFObjectFile<ELFT>::Elf_Rela RelA;5773    RelA.setSymbolAndType(0, Relocation::getNone(), EF.isMips64EL());5774    RelA.r_offset = 0;5775    RelA.r_addend = 0;5776    while (Offset < EndOffset)5777      writeRela(&RelA, Offset);5778 5779    assert(Offset == EndOffset && "Unexpected section overflow");5780  };5781 5782  // Fill the rest of the sections with R_*_NONE relocations5783  fillNone(RelDynOffset, RelDynEndOffset);5784  fillNone(RelPltOffset, RelPltEndOffset);5785}5786 5787template <typename ELFT>5788void RewriteInstance::patchELFGOT(ELFObjectFile<ELFT> *File) {5789  raw_fd_ostream &OS = Out->os();5790 5791  SectionRef GOTSection;5792  for (const SectionRef &Section : File->sections()) {5793    StringRef SectionName = cantFail(Section.getName());5794    if (SectionName == ".got") {5795      GOTSection = Section;5796      break;5797    }5798  }5799  if (!GOTSection.getObject()) {5800    if (!BC->IsStaticExecutable)5801      BC->errs() << "BOLT-INFO: no .got section found\n";5802    return;5803  }5804 5805  StringRef GOTContents = cantFail(GOTSection.getContents());5806  for (const uint64_t *GOTEntry =5807           reinterpret_cast<const uint64_t *>(GOTContents.data());5808       GOTEntry < reinterpret_cast<const uint64_t *>(GOTContents.data() +5809                                                     GOTContents.size());5810       ++GOTEntry) {5811    if (uint64_t NewAddress = getNewFunctionAddress(*GOTEntry)) {5812      LLVM_DEBUG(dbgs() << "BOLT-DEBUG: patching GOT entry 0x"5813                        << Twine::utohexstr(*GOTEntry) << " with 0x"5814                        << Twine::utohexstr(NewAddress) << '\n');5815      OS.pwrite(reinterpret_cast<const char *>(&NewAddress), sizeof(NewAddress),5816                reinterpret_cast<const char *>(GOTEntry) -5817                    File->getData().data());5818    }5819  }5820}5821 5822template <typename ELFT>5823void RewriteInstance::patchELFDynamic(ELFObjectFile<ELFT> *File) {5824  if (BC->IsStaticExecutable)5825    return;5826 5827  const ELFFile<ELFT> &Obj = File->getELFFile();5828  raw_fd_ostream &OS = Out->os();5829 5830  using Elf_Phdr = typename ELFFile<ELFT>::Elf_Phdr;5831  using Elf_Dyn = typename ELFFile<ELFT>::Elf_Dyn;5832 5833  // Locate DYNAMIC by looking through program headers.5834  uint64_t DynamicOffset = 0;5835  const Elf_Phdr *DynamicPhdr = nullptr;5836  for (const Elf_Phdr &Phdr : cantFail(Obj.program_headers())) {5837    if (Phdr.p_type == ELF::PT_DYNAMIC) {5838      DynamicOffset = Phdr.p_offset;5839      DynamicPhdr = &Phdr;5840      assert(Phdr.p_memsz == Phdr.p_filesz && "dynamic sizes should match");5841      break;5842    }5843  }5844  assert(DynamicPhdr && "missing dynamic in ELF binary");5845 5846  bool ZNowSet = false;5847 5848  // Go through all dynamic entries and patch functions addresses with5849  // new ones.5850  typename ELFT::DynRange DynamicEntries =5851      cantFail(Obj.dynamicEntries(), "error accessing dynamic table");5852  auto DTB = DynamicEntries.begin();5853  for (const Elf_Dyn &Dyn : DynamicEntries) {5854    Elf_Dyn NewDE = Dyn;5855    bool ShouldPatch = true;5856    switch (Dyn.d_tag) {5857    default:5858      ShouldPatch = false;5859      break;5860    case ELF::DT_RELACOUNT:5861      NewDE.d_un.d_val = DynamicRelativeRelocationsCount;5862      break;5863    case ELF::DT_INIT:5864    case ELF::DT_FINI: {5865      if (BC->HasRelocations) {5866        if (uint64_t NewAddress = getNewFunctionAddress(Dyn.getPtr())) {5867          LLVM_DEBUG(dbgs() << "BOLT-DEBUG: patching dynamic entry of type "5868                            << Dyn.getTag() << '\n');5869          NewDE.d_un.d_ptr = NewAddress;5870        }5871      }5872      RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary();5873      if (RtLibrary && Dyn.getTag() == ELF::DT_FINI) {5874        if (uint64_t Addr = RtLibrary->getRuntimeFiniAddress()) {5875          NewDE.d_un.d_ptr = Addr;5876          BC->outs()5877              << "BOLT-INFO: runtime library finalization was hooked via "5878                 "DT_FINI, set to 0x"5879              << Twine::utohexstr(Addr) << "\n";5880        }5881      }5882      if (RtLibrary && Dyn.getTag() == ELF::DT_INIT &&5883          (!BC->HasInterpHeader ||5884           opts::RuntimeLibInitHook == opts::RLIH_INIT)) {5885        if (auto Addr = RtLibrary->getRuntimeStartAddress()) {5886          NewDE.d_un.d_ptr = Addr;5887          BC->outs()5888              << "BOLT-INFO: runtime library initialization was hooked via "5889                 "DT_INIT, set to 0x"5890              << Twine::utohexstr(Addr) << "\n";5891        }5892      }5893      break;5894    }5895    case ELF::DT_FLAGS:5896      if (BC->RequiresZNow) {5897        NewDE.d_un.d_val |= ELF::DF_BIND_NOW;5898        ZNowSet = true;5899      }5900      break;5901    case ELF::DT_FLAGS_1:5902      if (BC->RequiresZNow) {5903        NewDE.d_un.d_val |= ELF::DF_1_NOW;5904        ZNowSet = true;5905      }5906      break;5907    }5908    if (ShouldPatch)5909      OS.pwrite(reinterpret_cast<const char *>(&NewDE), sizeof(NewDE),5910                DynamicOffset + (&Dyn - DTB) * sizeof(Dyn));5911  }5912 5913  if (BC->RequiresZNow && !ZNowSet) {5914    BC->errs()5915        << "BOLT-ERROR: output binary requires immediate relocation "5916           "processing which depends on DT_FLAGS or DT_FLAGS_1 presence in "5917           ".dynamic. Please re-link the binary with -znow.\n";5918    exit(1);5919  }5920}5921 5922template <typename ELFT>5923Error RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) {5924  const ELFFile<ELFT> &Obj = File->getELFFile();5925 5926  using Elf_Phdr = typename ELFFile<ELFT>::Elf_Phdr;5927  using Elf_Dyn = typename ELFFile<ELFT>::Elf_Dyn;5928 5929  // Locate DYNAMIC by looking through program headers.5930  const Elf_Phdr *DynamicPhdr = nullptr;5931  for (const Elf_Phdr &Phdr : cantFail(Obj.program_headers())) {5932    if (Phdr.p_type == ELF::PT_DYNAMIC) {5933      DynamicPhdr = &Phdr;5934      break;5935    }5936  }5937 5938  if (!DynamicPhdr) {5939    BC->outs() << "BOLT-INFO: static input executable detected\n";5940    // TODO: static PIE executable might have dynamic header5941    BC->IsStaticExecutable = true;5942    return Error::success();5943  }5944 5945  if (DynamicPhdr->p_memsz != DynamicPhdr->p_filesz)5946    return createStringError(errc::executable_format_error,5947                             "dynamic section sizes should match");5948 5949  // Go through all dynamic entries to locate entries of interest.5950  auto DynamicEntriesOrErr = Obj.dynamicEntries();5951  if (!DynamicEntriesOrErr)5952    return DynamicEntriesOrErr.takeError();5953  typename ELFT::DynRange DynamicEntries = DynamicEntriesOrErr.get();5954 5955  for (const Elf_Dyn &Dyn : DynamicEntries) {5956    switch (Dyn.d_tag) {5957    case ELF::DT_INIT:5958      BC->InitAddress = Dyn.getPtr();5959      break;5960    case ELF::DT_INIT_ARRAY:5961      BC->InitArrayAddress = Dyn.getPtr();5962      break;5963    case ELF::DT_INIT_ARRAYSZ:5964      BC->InitArraySize = Dyn.getPtr();5965      break;5966    case ELF::DT_FINI:5967      BC->FiniAddress = Dyn.getPtr();5968      break;5969    case ELF::DT_FINI_ARRAY:5970      BC->FiniArrayAddress = Dyn.getPtr();5971      break;5972    case ELF::DT_FINI_ARRAYSZ:5973      BC->FiniArraySize = Dyn.getPtr();5974      break;5975    case ELF::DT_RELA:5976      DynamicRelocationsAddress = Dyn.getPtr();5977      break;5978    case ELF::DT_RELASZ:5979      DynamicRelocationsSize = Dyn.getVal();5980      break;5981    case ELF::DT_JMPREL:5982      PLTRelocationsAddress = Dyn.getPtr();5983      break;5984    case ELF::DT_PLTRELSZ:5985      PLTRelocationsSize = Dyn.getVal();5986      break;5987    case ELF::DT_RELACOUNT:5988      DynamicRelativeRelocationsCount = Dyn.getVal();5989      break;5990    case ELF::DT_RELR:5991      DynamicRelrAddress = Dyn.getPtr();5992      break;5993    case ELF::DT_RELRSZ:5994      DynamicRelrSize = Dyn.getVal();5995      break;5996    case ELF::DT_RELRENT:5997      DynamicRelrEntrySize = Dyn.getVal();5998      break;5999    }6000  }6001 6002  if (!DynamicRelocationsAddress || !DynamicRelocationsSize) {6003    DynamicRelocationsAddress.reset();6004    DynamicRelocationsSize = 0;6005  }6006 6007  if (!PLTRelocationsAddress || !PLTRelocationsSize) {6008    PLTRelocationsAddress.reset();6009    PLTRelocationsSize = 0;6010  }6011 6012  if (!DynamicRelrAddress || !DynamicRelrSize) {6013    DynamicRelrAddress.reset();6014    DynamicRelrSize = 0;6015  } else if (!DynamicRelrEntrySize) {6016    BC->errs() << "BOLT-ERROR: expected DT_RELRENT to be presented "6017               << "in DYNAMIC section\n";6018    exit(1);6019  } else if (DynamicRelrSize % DynamicRelrEntrySize) {6020    BC->errs() << "BOLT-ERROR: expected RELR table size to be divisible "6021               << "by RELR entry size\n";6022    exit(1);6023  }6024 6025  return Error::success();6026}6027 6028uint64_t RewriteInstance::getNewFunctionAddress(uint64_t OldAddress) {6029  const BinaryFunction *Function = BC->getBinaryFunctionAtAddress(OldAddress);6030  if (!Function)6031    return 0;6032 6033  return Function->getOutputAddress();6034}6035 6036uint64_t RewriteInstance::getNewFunctionOrDataAddress(uint64_t OldAddress) {6037  if (uint64_t Function = getNewFunctionAddress(OldAddress))6038    return Function;6039 6040  const BinaryData *BD = BC->getBinaryDataAtAddress(OldAddress);6041  if (BD && BD->isMoved())6042    return BD->getOutputAddress();6043 6044  if (const BinaryFunction *BF =6045          BC->getBinaryFunctionContainingAddress(OldAddress)) {6046    if (BF->isEmitted()) {6047      // If OldAddress is the another entry point of6048      // the function, then BOLT could get the new address.6049      if (BF->isMultiEntry()) {6050        for (const BinaryBasicBlock &BB : *BF)6051          if (BB.isEntryPoint() &&6052              (BF->getAddress() + BB.getOffset()) == OldAddress)6053            return BB.getOutputStartAddress();6054      }6055      BC->errs() << "BOLT-ERROR: unable to get new address corresponding to "6056                    "input address 0x"6057                 << Twine::utohexstr(OldAddress) << " in function " << *BF6058                 << ". Consider adding this function to --skip-funcs=...\n";6059      exit(1);6060    }6061  }6062 6063  return 0;6064}6065 6066void RewriteInstance::rewriteFile() {6067  std::error_code EC;6068  Out = std::make_unique<ToolOutputFile>(opts::OutputFilename, EC,6069                                         sys::fs::OF_None);6070  check_error(EC, "cannot create output executable file");6071 6072  raw_fd_ostream &OS = Out->os();6073 6074  // Copy allocatable part of the input.6075  OS << InputFile->getData().substr(0, FirstNonAllocatableOffset);6076 6077  auto Streamer = BC->createStreamer(OS);6078  // Make sure output stream has enough reserved space, otherwise6079  // pwrite() will fail.6080  uint64_t Offset = std::max(getFileOffsetForAddress(NextAvailableAddress),6081                             FirstNonAllocatableOffset);6082  Offset = OS.seek(Offset);6083  assert((Offset != (uint64_t)-1) && "Error resizing output file");6084 6085  // Overwrite functions with fixed output address. This is mostly used by6086  // non-relocation mode, with one exception: injected functions are covered6087  // here in both modes.6088  uint64_t CountOverwrittenFunctions = 0;6089  uint64_t OverwrittenScore = 0;6090  for (BinaryFunction *Function : BC->getAllBinaryFunctions()) {6091    if (Function->getImageAddress() == 0 || Function->getImageSize() == 0)6092      continue;6093 6094    assert(Function->getImageSize() <= Function->getMaxSize() &&6095           "Unexpected large function");6096 6097    const auto HasAddress = [](const FunctionFragment &FF) {6098      return FF.empty() ||6099             (FF.getImageAddress() != 0 && FF.getImageSize() != 0);6100    };6101    const bool SplitFragmentsHaveAddress =6102        llvm::all_of(Function->getLayout().getSplitFragments(), HasAddress);6103    if (Function->isSplit() && !SplitFragmentsHaveAddress) {6104      const auto HasNoAddress = [](const FunctionFragment &FF) {6105        return FF.getImageAddress() == 0 && FF.getImageSize() == 0;6106      };6107      assert(llvm::all_of(Function->getLayout().getSplitFragments(),6108                          HasNoAddress) &&6109             "Some split fragments have an address while others do not");6110      (void)HasNoAddress;6111      continue;6112    }6113 6114    OverwrittenScore += Function->getFunctionScore();6115    ++CountOverwrittenFunctions;6116 6117    // Overwrite function in the output file.6118    if (opts::Verbosity >= 2)6119      BC->outs() << "BOLT: rewriting function \"" << *Function << "\"\n";6120 6121    OS.pwrite(reinterpret_cast<char *>(Function->getImageAddress()),6122              Function->getImageSize(), Function->getFileOffset());6123 6124    // Write nops at the end of the function.6125    if (Function->getMaxSize() != std::numeric_limits<uint64_t>::max()) {6126      uint64_t Pos = OS.tell();6127      OS.seek(Function->getFileOffset() + Function->getImageSize());6128      BC->MAB->writeNopData(6129          OS, Function->getMaxSize() - Function->getImageSize(), &*BC->STI);6130 6131      OS.seek(Pos);6132    }6133 6134    if (!Function->isSplit())6135      continue;6136 6137    // Write cold part6138    if (opts::Verbosity >= 2) {6139      BC->outs() << formatv("BOLT: rewriting function \"{0}\" (split parts)\n",6140                            *Function);6141    }6142 6143    for (const FunctionFragment &FF :6144         Function->getLayout().getSplitFragments()) {6145      OS.pwrite(reinterpret_cast<char *>(FF.getImageAddress()),6146                FF.getImageSize(), FF.getFileOffset());6147    }6148  }6149 6150  // Print function statistics for non-relocation mode.6151  if (!BC->HasRelocations) {6152    BC->outs() << "BOLT: " << CountOverwrittenFunctions << " out of "6153               << BC->getBinaryFunctions().size()6154               << " functions were overwritten.\n";6155    if (BC->TotalScore != 0) {6156      double Coverage = OverwrittenScore / (double)BC->TotalScore * 100.0;6157      BC->outs() << format("BOLT-INFO: rewritten functions cover %.2lf",6158                           Coverage)6159                 << "% of the execution count of simple functions of "6160                    "this binary\n";6161    }6162  }6163 6164  if (BC->HasRelocations && opts::TrapOldCode) {6165    uint64_t SavedPos = OS.tell();6166    // Overwrite function body to make sure we never execute these instructions.6167    for (auto &BFI : BC->getBinaryFunctions()) {6168      BinaryFunction &BF = BFI.second;6169      if (!BF.getFileOffset() || !BF.isEmitted())6170        continue;6171      OS.seek(BF.getFileOffset());6172      StringRef TrapInstr = BC->MIB->getTrapFillValue();6173      unsigned NInstr = BF.getMaxSize() / TrapInstr.size();6174      for (unsigned I = 0; I < NInstr; ++I)6175        OS.write(TrapInstr.data(), TrapInstr.size());6176    }6177    OS.seek(SavedPos);6178  }6179 6180  // Write all allocatable sections - reloc-mode text is written here as well6181  for (BinarySection &Section : BC->allocatableSections()) {6182    if (!Section.isFinalized() || !Section.getOutputData()) {6183      LLVM_DEBUG(if (opts::Verbosity > 1) {6184        dbgs() << "BOLT-INFO: new section is finalized or !getOutputData, skip "6185               << Section.getName() << '\n';6186      });6187      continue;6188    }6189    if (Section.isLinkOnly()) {6190      LLVM_DEBUG(if (opts::Verbosity > 1) {6191        dbgs() << "BOLT-INFO: new section is link only, skip "6192               << Section.getName() << '\n';6193      });6194      continue;6195    }6196 6197    if (opts::Verbosity >= 1)6198      BC->outs() << "BOLT: writing new section " << Section.getName()6199                 << "\n data at 0x"6200                 << Twine::utohexstr(Section.getAllocAddress()) << "\n of size "6201                 << Section.getOutputSize() << "\n at offset "6202                 << Section.getOutputFileOffset() << " with content size "6203                 << Section.getOutputContents().size() << '\n';6204    OS.seek(Section.getOutputFileOffset());6205    Section.write(OS);6206  }6207 6208  for (BinarySection &Section : BC->allocatableSections())6209    Section.flushPendingRelocations(OS, [this](const MCSymbol *S) {6210      return getNewValueForSymbol(S->getName());6211    });6212 6213  // If .eh_frame is present create .eh_frame_hdr.6214  if (EHFrameSection)6215    writeEHFrameHeader();6216 6217  // Add BOLT Addresses Translation maps to allow profile collection to6218  // happen in the output binary6219  if (opts::EnableBAT)6220    addBATSection();6221 6222  // Patch program header table.6223  if (!BC->IsLinuxKernel) {6224    updateSegmentInfo();6225    patchELFPHDRTable();6226  }6227 6228  // Finalize memory image of section string table.6229  finalizeSectionStringTable();6230 6231  // Update symbol tables.6232  patchELFSymTabs();6233 6234  if (opts::EnableBAT)6235    encodeBATSection();6236 6237  // Copy non-allocatable sections once allocatable part is finished.6238  rewriteNoteSections();6239 6240  if (BC->HasRelocations) {6241    patchELFAllocatableRelaSections();6242    patchELFAllocatableRelrSection();6243    patchELFGOT();6244  }6245 6246  // Patch dynamic section/segment.6247  patchELFDynamic();6248 6249  // Update ELF book-keeping info.6250  patchELFSectionHeaderTable();6251 6252  if (opts::PrintSections) {6253    BC->outs() << "BOLT-INFO: Sections after processing:\n";6254    BC->printSections(BC->outs());6255  }6256 6257  Out->keep();6258  EC = sys::fs::setPermissions(6259      opts::OutputFilename,6260      static_cast<sys::fs::perms>(sys::fs::perms::all_all &6261                                  ~sys::fs::getUmask()));6262  check_error(EC, "cannot set permissions of output file");6263}6264 6265void RewriteInstance::writeEHFrameHeader() {6266  BinarySection *NewEHFrameSection =6267      getSection(getNewSecPrefix() + getEHFrameSectionName());6268 6269  // No need to update the header if no new .eh_frame was created.6270  if (!NewEHFrameSection)6271    return;6272 6273  DWARFDebugFrame NewEHFrame(BC->TheTriple->getArch(), true,6274                             NewEHFrameSection->getOutputAddress());6275  Error E = NewEHFrame.parse(DWARFDataExtractor(6276      NewEHFrameSection->getOutputContents(), BC->AsmInfo->isLittleEndian(),6277      BC->AsmInfo->getCodePointerSize()));6278  check_error(std::move(E), "failed to parse EH frame");6279 6280  uint64_t RelocatedEHFrameAddress = 0;6281  StringRef RelocatedEHFrameContents;6282  BinarySection *RelocatedEHFrameSection =6283      getSection(".relocated" + getEHFrameSectionName());6284  if (RelocatedEHFrameSection) {6285    RelocatedEHFrameAddress = RelocatedEHFrameSection->getOutputAddress();6286    RelocatedEHFrameContents = RelocatedEHFrameSection->getOutputContents();6287  }6288  DWARFDebugFrame RelocatedEHFrame(BC->TheTriple->getArch(), true,6289                                   RelocatedEHFrameAddress);6290  Error Er = RelocatedEHFrame.parse(DWARFDataExtractor(6291      RelocatedEHFrameContents, BC->AsmInfo->isLittleEndian(),6292      BC->AsmInfo->getCodePointerSize()));6293  check_error(std::move(Er), "failed to parse EH frame");6294 6295  LLVM_DEBUG(dbgs() << "BOLT: writing a new " << getEHFrameHdrSectionName()6296                    << '\n');6297 6298  // Try to overwrite the original .eh_frame_hdr if the size permits.6299  uint64_t EHFrameHdrOutputAddress = 0;6300  uint64_t EHFrameHdrFileOffset = 0;6301  std::vector<char> NewEHFrameHdr;6302  BinarySection *OldEHFrameHdrSection = getSection(getEHFrameHdrSectionName());6303  if (OldEHFrameHdrSection) {6304    NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(6305        RelocatedEHFrame, NewEHFrame, OldEHFrameHdrSection->getAddress());6306    if (NewEHFrameHdr.size() <= OldEHFrameHdrSection->getSize()) {6307      BC->outs() << "BOLT-INFO: rewriting " << getEHFrameHdrSectionName()6308                 << " in-place\n";6309      EHFrameHdrOutputAddress = OldEHFrameHdrSection->getAddress();6310      EHFrameHdrFileOffset = OldEHFrameHdrSection->getInputFileOffset();6311    } else {6312      OldEHFrameHdrSection->setOutputName(getOrgSecPrefix() +6313                                          getEHFrameHdrSectionName());6314      OldEHFrameHdrSection = nullptr;6315    }6316  }6317 6318  // If there was not enough space, allocate more memory for .eh_frame_hdr.6319  if (!OldEHFrameHdrSection) {6320    NextAvailableAddress =6321        appendPadding(Out->os(), NextAvailableAddress, EHFrameHdrAlign);6322 6323    EHFrameHdrOutputAddress = NextAvailableAddress;6324    EHFrameHdrFileOffset = getFileOffsetForAddress(NextAvailableAddress);6325 6326    NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(6327        RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress);6328 6329    NextAvailableAddress += NewEHFrameHdr.size();6330    if (!BC->BOLTReserved.empty() &&6331        (NextAvailableAddress > BC->BOLTReserved.end())) {6332      BC->errs() << "BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName()6333                 << " into reserved space\n";6334      exit(1);6335    }6336 6337    // Create a new entry in the section header table.6338    const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true,6339                                                   /*IsText=*/false,6340                                                   /*IsAllocatable=*/true);6341    BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection(6342        getNewSecPrefix() + getEHFrameHdrSectionName(), ELF::SHT_PROGBITS,6343        Flags, nullptr, NewEHFrameHdr.size(), /*Alignment=*/1);6344    EHFrameHdrSec.setOutputFileOffset(EHFrameHdrFileOffset);6345    EHFrameHdrSec.setOutputAddress(EHFrameHdrOutputAddress);6346    EHFrameHdrSec.setOutputName(getEHFrameHdrSectionName());6347  }6348 6349  Out->os().seek(EHFrameHdrFileOffset);6350  Out->os().write(NewEHFrameHdr.data(), NewEHFrameHdr.size());6351 6352  // Pad the contents if overwriting in-place.6353  if (OldEHFrameHdrSection)6354    Out->os().write_zeros(OldEHFrameHdrSection->getSize() -6355                          NewEHFrameHdr.size());6356 6357  // Merge new .eh_frame with the relocated original so that gdb can locate all6358  // FDEs.6359  if (RelocatedEHFrameSection) {6360    const uint64_t NewEHFrameSectionSize =6361        RelocatedEHFrameSection->getOutputAddress() +6362        RelocatedEHFrameSection->getOutputSize() -6363        NewEHFrameSection->getOutputAddress();6364    NewEHFrameSection->updateContents(NewEHFrameSection->getOutputData(),6365                                      NewEHFrameSectionSize);6366    BC->deregisterSection(*RelocatedEHFrameSection);6367  }6368 6369  LLVM_DEBUG(dbgs() << "BOLT-DEBUG: size of .eh_frame after merge is "6370                    << NewEHFrameSection->getOutputSize() << '\n');6371}6372 6373uint64_t RewriteInstance::getNewValueForSymbol(const StringRef Name) {6374  auto Value = Linker->lookupSymbolInfo(Name);6375  if (Value)6376    return Value->Address;6377 6378  // Return the original value if we haven't emitted the symbol.6379  BinaryData *BD = BC->getBinaryDataByName(Name);6380  if (!BD)6381    return 0;6382 6383  return BD->getAddress();6384}6385 6386uint64_t RewriteInstance::getFileOffsetForAddress(uint64_t Address) const {6387  // Check if it's possibly part of the new segment.6388  if (NewTextSegmentAddress && Address >= NewTextSegmentAddress)6389    return Address - NewTextSegmentAddress + NewTextSegmentOffset;6390 6391  // Find an existing segment that matches the address.6392  const auto SegmentInfoI = BC->SegmentMapInfo.upper_bound(Address);6393  if (SegmentInfoI == BC->SegmentMapInfo.begin())6394    return 0;6395 6396  const SegmentInfo &SegmentInfo = std::prev(SegmentInfoI)->second;6397  if (Address < SegmentInfo.Address ||6398      Address >= SegmentInfo.Address + SegmentInfo.FileSize)6399    return 0;6400 6401  return SegmentInfo.FileOffset + Address - SegmentInfo.Address;6402}6403 6404bool RewriteInstance::willOverwriteSection(StringRef SectionName) {6405  if (llvm::is_contained(SectionsToOverwrite, SectionName))6406    return true;6407  if (llvm::is_contained(DebugSectionsToOverwrite, SectionName))6408    return true;6409 6410  ErrorOr<BinarySection &> Section = BC->getUniqueSectionByName(SectionName);6411  return Section && Section->isAllocatable() && Section->isFinalized();6412}6413 6414bool RewriteInstance::isDebugSection(StringRef SectionName) {6415  if (SectionName.starts_with(".debug_") ||6416      SectionName.starts_with(".zdebug_") || SectionName == ".gdb_index" ||6417      SectionName == ".stab" || SectionName == ".stabstr")6418    return true;6419 6420  return false;6421}6422