1 //===- bolt/Rewrite/RewriteInstance.h - ELF rewriter ------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Interface to control an instance of a binary rewriting process. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef BOLT_REWRITE_REWRITE_INSTANCE_H 14 #define BOLT_REWRITE_REWRITE_INSTANCE_H 15 16 #include "bolt/Core/BinaryContext.h" 17 #include "bolt/Core/Linker.h" 18 #include "bolt/Rewrite/MetadataManager.h" 19 #include "bolt/Utils/NameResolver.h" 20 #include "llvm/MC/StringTableBuilder.h" 21 #include "llvm/Object/ELFObjectFile.h" 22 #include "llvm/Object/ObjectFile.h" 23 #include "llvm/Support/Error.h" 24 #include "llvm/Support/Regex.h" 25 #include <map> 26 #include <set> 27 #include <unordered_map> 28 29 namespace llvm { 30 31 class ToolOutputFile; 32 33 namespace bolt { 34 35 class BoltAddressTranslation; 36 class CFIReaderWriter; 37 class DWARFRewriter; 38 class ProfileReaderBase; 39 40 /// This class encapsulates all data necessary to carry on binary reading, 41 /// disassembly, CFG building, BB reordering (among other binary-level 42 /// optimizations) and rewriting. It also has the logic to coordinate such 43 /// events. 44 class RewriteInstance { 45 public: 46 // This constructor has complex initialization that can fail during 47 // construction. Constructors can’t return errors, so clients must test \p Err 48 // after the object is constructed. Use `create` method instead. 49 RewriteInstance(llvm::object::ELFObjectFileBase *File, const int Argc, 50 const char *const *Argv, StringRef ToolPath, 51 raw_ostream &Stdout, raw_ostream &Stderr, Error &Err); 52 53 static Expected<std::unique_ptr<RewriteInstance>> 54 create(llvm::object::ELFObjectFileBase *File, const int Argc, 55 const char *const *Argv, StringRef ToolPath, 56 raw_ostream &Stdout = llvm::outs(), 57 raw_ostream &Stderr = llvm::errs()); 58 ~RewriteInstance(); 59 60 /// Assign profile from \p Filename to this instance. 61 Error setProfile(StringRef Filename); 62 63 /// Run all the necessary steps to read, optimize and rewrite the binary. 64 Error run(); 65 66 /// Diff this instance against another one. Non-const since we may run passes 67 /// to fold identical functions. 68 void compare(RewriteInstance &RI2); 69 70 /// Return binary context. 71 const BinaryContext &getBinaryContext() const { return *BC; } 72 73 /// Return total score of all functions for this instance. 74 uint64_t getTotalScore() const { return BC->TotalScore; } 75 76 /// Return the name of the input file. 77 StringRef getInputFilename() const { 78 assert(InputFile && "cannot have an instance without a file"); 79 return InputFile->getFileName(); 80 } 81 82 /// If this instance uses a profile, return appropriate profile reader. 83 const ProfileReaderBase *getProfileReader() const { 84 return ProfileReader.get(); 85 } 86 87 private: 88 /// Populate array of binary functions and other objects of interest 89 /// from meta data in the file. 90 void discoverFileObjects(); 91 92 /// Check if the input binary has a space reserved for BOLT and use it for new 93 /// section allocations if found. 94 void discoverBOLTReserved(); 95 96 /// Check whether we should use DT_FINI or DT_FINI_ARRAY for instrumentation. 97 /// DT_FINI is preferred; DT_FINI_ARRAY is only used when no DT_FINI entry was 98 /// found. 99 Error discoverRtFiniAddress(); 100 101 /// If DT_FINI_ARRAY is used for instrumentation, update the relocation of its 102 /// first entry to point to the instrumentation library's fini address. 103 void updateRtFiniReloc(); 104 105 /// Create and initialize metadata rewriters for this instance. 106 void initializeMetadataManager(); 107 108 /// Process fragments, locate parent functions. 109 void registerFragments(); 110 111 /// Read info from special sections. E.g. eh_frame and .gcc_except_table 112 /// for exception and stack unwinding information. 113 Error readSpecialSections(); 114 115 /// Adjust supplied command-line options based on input data. 116 void adjustCommandLineOptions(); 117 118 /// Process runtime relocations. 119 void processDynamicRelocations(); 120 121 /// Process input relocations. 122 void processRelocations(); 123 124 /// Read relocations from a given section. 125 void readDynamicRelocations(const object::SectionRef &Section, bool IsJmpRel); 126 127 /// Read relocations from a given RELR section. 128 void readDynamicRelrRelocations(BinarySection &Section); 129 130 /// Print relocation information. 131 void printRelocationInfo(const RelocationRef &Rel, StringRef SymbolName, 132 uint64_t SymbolAddress, uint64_t Addend, 133 uint64_t ExtractedValue) const; 134 135 /// Read relocations from a given section. 136 void readRelocations(const object::SectionRef &Section); 137 138 /// Handle one relocation. 139 void handleRelocation(const object::SectionRef &RelocatedSection, 140 const RelocationRef &Rel); 141 142 /// Mark functions that are not meant for processing as ignored. 143 void selectFunctionsToProcess(); 144 145 /// Read information from debug sections. 146 void readDebugInfo(); 147 148 /// Read profile data without having disassembled functions available. 149 void preprocessProfileData(); 150 151 void processProfileDataPreCFG(); 152 153 /// Associate profile data with functions and data objects. 154 void processProfileData(); 155 156 /// Disassemble each function in the binary and associate it with a 157 /// BinaryFunction object, preparing all information necessary for binary 158 /// optimization. 159 void disassembleFunctions(); 160 161 void buildFunctionsCFG(); 162 163 void postProcessFunctions(); 164 165 void preregisterSections(); 166 167 /// run analyses requested in binary analysis mode. 168 void runBinaryAnalyses(); 169 170 /// Run optimizations that operate at the binary, or post-linker, level. 171 void runOptimizationPasses(); 172 173 /// Write code and data into an intermediary object file, map virtual to real 174 /// addresses and link the object file, resolving all relocations and 175 /// performing final relaxation. 176 void emitAndLink(); 177 178 /// Link additional runtime code to support instrumentation. 179 void linkRuntime(); 180 181 /// Process metadata in sections before functions are discovered. 182 void processSectionMetadata(); 183 184 /// Process metadata in special sections before CFG is built for functions. 185 void processMetadataPreCFG(); 186 187 /// Process metadata in special sections after CFG is built for functions. 188 void processMetadataPostCFG(); 189 190 /// Make changes to metadata before the binary is emitted. 191 void finalizeMetadataPreEmit(); 192 193 /// Update debug and other auxiliary information in the file. 194 void updateMetadata(); 195 196 /// Return the list of code sections in the output order. 197 std::vector<BinarySection *> getCodeSections(); 198 199 /// Map all sections to their final addresses. 200 void mapFileSections(BOLTLinker::SectionMapper MapSection); 201 202 /// Map code sections generated by BOLT. 203 void mapCodeSections(BOLTLinker::SectionMapper MapSection); 204 205 /// Map the rest of allocatable sections. 206 void mapAllocatableSections(BOLTLinker::SectionMapper MapSection); 207 208 /// Update output object's values based on the final \p Layout. 209 void updateOutputValues(const BOLTLinker &Linker); 210 211 /// Rewrite back all functions (hopefully optimized) that fit in the original 212 /// memory footprint for that function. If the function is now larger and does 213 /// not fit in the binary, reject it and preserve the original version of the 214 /// function. If we couldn't understand the function for some reason in 215 /// disassembleFunctions(), also preserve the original version. 216 void rewriteFile(); 217 218 /// Return address of a function in the new binary corresponding to 219 /// \p OldAddress address in the original binary. 220 uint64_t getNewFunctionAddress(uint64_t OldAddress); 221 222 /// Return address of a function or moved data in the new binary 223 /// corresponding to \p OldAddress address in the original binary. 224 uint64_t getNewFunctionOrDataAddress(uint64_t OldAddress); 225 226 /// Return value for the symbol \p Name in the output. 227 uint64_t getNewValueForSymbol(const StringRef Name); 228 229 /// Check for PT_GNU_RELRO segment presence, mark covered sections as 230 /// (dynamically) read-only (written once), as specified in LSB Chapter 12: 231 /// "segment which may be made read-only after relocations have been 232 /// processed". 233 void markGnuRelroSections(); 234 235 /// Detect addresses and offsets available in the binary for allocating 236 /// new sections. 237 Error discoverStorage(); 238 239 /// Adjust function sizes and set proper maximum size values after the whole 240 /// symbol table has been processed. 241 void adjustFunctionBoundaries(); 242 243 /// Make .eh_frame section relocatable. 244 void relocateEHFrameSection(); 245 246 /// Analyze relocation \p Rel. 247 /// Return true if the relocation was successfully processed, false otherwise. 248 /// The \p SymbolName, \p SymbolAddress, \p Addend and \p ExtractedValue 249 /// parameters will be set on success. The \p Skip argument indicates 250 /// that the relocation was analyzed, but it must not be processed. 251 bool analyzeRelocation(const object::RelocationRef &Rel, uint64_t &RType, 252 std::string &SymbolName, bool &IsSectionRelocation, 253 uint64_t &SymbolAddress, int64_t &Addend, 254 uint64_t &ExtractedValue, bool &Skip) const; 255 256 /// Rewrite non-allocatable sections with modifications. 257 void rewriteNoteSections(); 258 259 /// Write .eh_frame_hdr. 260 void writeEHFrameHeader(); 261 262 /// Disassemble and create function entries for PLT. 263 void disassemblePLT(); 264 265 /// Auxiliary function to create .plt BinaryFunction on \p EntryAddres 266 /// with the \p EntrySize size. \p TargetAddress is the .got entry 267 /// associated address. 268 void createPLTBinaryFunction(uint64_t TargetAddress, uint64_t EntryAddress, 269 uint64_t EntrySize); 270 271 /// Disassemble PLT instruction. 272 void disassemblePLTInstruction(const BinarySection &Section, 273 uint64_t InstrOffset, MCInst &Instruction, 274 uint64_t &InstrSize); 275 276 /// Disassemble aarch64-specific .plt \p Section auxiliary function 277 void disassemblePLTSectionAArch64(BinarySection &Section); 278 279 /// Disassemble X86-specific .plt \p Section auxiliary function. \p EntrySize 280 /// is the expected .plt \p Section entry function size. 281 void disassemblePLTSectionX86(BinarySection &Section, uint64_t EntrySize); 282 283 /// Disassemble riscv-specific .plt \p Section auxiliary function 284 void disassemblePLTSectionRISCV(BinarySection &Section); 285 286 /// ELF-specific part. TODO: refactor into new class. 287 #define ELF_FUNCTION(TYPE, FUNC) \ 288 template <typename ELFT> TYPE FUNC(object::ELFObjectFile<ELFT> *Obj); \ 289 TYPE FUNC() { \ 290 if (auto *ELF32LE = dyn_cast<object::ELF32LEObjectFile>(InputFile)) \ 291 return FUNC(ELF32LE); \ 292 if (auto *ELF64LE = dyn_cast<object::ELF64LEObjectFile>(InputFile)) \ 293 return FUNC(ELF64LE); \ 294 if (auto *ELF32BE = dyn_cast<object::ELF32BEObjectFile>(InputFile)) \ 295 return FUNC(ELF32BE); \ 296 auto *ELF64BE = cast<object::ELF64BEObjectFile>(InputFile); \ 297 return FUNC(ELF64BE); \ 298 } 299 300 /// Patch ELF book-keeping info. 301 void patchELFPHDRTable(); 302 303 /// Create section header table. 304 ELF_FUNCTION(void, patchELFSectionHeaderTable); 305 306 /// Create the regular symbol table and patch dyn symbol tables. 307 ELF_FUNCTION(void, patchELFSymTabs); 308 309 /// Read dynamic section/segment of ELF. 310 ELF_FUNCTION(Error, readELFDynamic); 311 312 /// Patch dynamic section/segment of ELF. 313 ELF_FUNCTION(void, patchELFDynamic); 314 315 /// Patch .got 316 ELF_FUNCTION(void, patchELFGOT); 317 318 /// Patch allocatable relocation sections. 319 ELF_FUNCTION(void, patchELFAllocatableRelaSections); 320 321 /// Patch allocatable relr section. 322 ELF_FUNCTION(void, patchELFAllocatableRelrSection); 323 324 /// Finalize memory image of section header string table. 325 ELF_FUNCTION(void, finalizeSectionStringTable); 326 327 /// Return a list of all sections to include in the output binary. 328 /// Populate \p NewSectionIndex with a map of input to output indices. 329 template <typename ELFT> 330 std::vector<typename object::ELFObjectFile<ELFT>::Elf_Shdr> 331 getOutputSections(object::ELFObjectFile<ELFT> *File, 332 std::vector<uint32_t> &NewSectionIndex); 333 334 /// Return true if \p Section should be stripped from the output binary. 335 template <typename ELFShdrTy> 336 bool shouldStrip(const ELFShdrTy &Section, StringRef SectionName); 337 338 /// Write ELF symbol table using \p Write and \p AddToStrTab functions 339 /// based on the input file symbol table passed in \p SymTabSection. 340 /// \p IsDynSym is set to true for dynamic symbol table since we 341 /// are updating it in-place with minimal modifications. 342 template <typename ELFT, typename WriteFuncTy, typename StrTabFuncTy> 343 void updateELFSymbolTable( 344 object::ELFObjectFile<ELFT> *File, bool IsDynSym, 345 const typename object::ELFObjectFile<ELFT>::Elf_Shdr &SymTabSection, 346 const std::vector<uint32_t> &NewSectionIndex, WriteFuncTy Write, 347 StrTabFuncTy AddToStrTab); 348 349 /// Get output index in dynamic symbol table. 350 uint32_t getOutputDynamicSymbolIndex(const MCSymbol *Symbol) { 351 auto It = SymbolIndex.find(Symbol); 352 if (It != SymbolIndex.end()) 353 return It->second; 354 return 0; 355 } 356 357 /// Add a notes section containing the BOLT revision and command line options. 358 void addBoltInfoSection(); 359 360 /// Add a notes section containing the serialized BOLT Address Translation 361 /// maps that can be used to enable sampling of the output binary for the 362 /// purpose of generating BOLT profile data for the input binary. 363 void addBATSection(); 364 365 /// Loop over now emitted functions to write translation maps 366 void encodeBATSection(); 367 368 /// Return file offset corresponding to a virtual \p Address. 369 /// Return 0 if the address has no mapping in the file, including being 370 /// part of .bss section. 371 uint64_t getFileOffsetForAddress(uint64_t Address) const; 372 373 /// Return true if we will overwrite contents of the section instead 374 /// of appending contents to it. 375 bool willOverwriteSection(StringRef SectionName); 376 377 public: 378 /// Standard ELF sections we overwrite. 379 static constexpr const char *SectionsToOverwrite[] = { 380 ".shstrtab", 381 ".symtab", 382 ".strtab", 383 }; 384 385 /// Debug section to we overwrite while updating the debug info. 386 static std::vector<std::string> DebugSectionsToOverwrite; 387 388 /// Return true if the section holds debug information. 389 static bool isDebugSection(StringRef SectionName); 390 391 /// Adds Debug section to overwrite. 392 static void addToDebugSectionsToOverwrite(const char *Section) { 393 DebugSectionsToOverwrite.emplace_back(Section); 394 } 395 396 private: 397 /// Manage a pipeline of metadata handlers. 398 class MetadataManager MetadataManager; 399 400 static const char TimerGroupName[]; 401 402 static const char TimerGroupDesc[]; 403 404 /// Alignment value used for .eh_frame_hdr. 405 static constexpr uint64_t EHFrameHdrAlign = 4; 406 407 /// Sections created by BOLT will have an internal name that starts with the 408 /// following prefix. Note that the prefix is used for a section lookup 409 /// internally and the section name in the output might be different. 410 static StringRef getNewSecPrefix() { return ".bolt.new"; } 411 412 /// String to be added before the original section name. 413 /// 414 /// When BOLT creates a new section with the same name as the one in the 415 /// input file, it may need to preserve the original section. This prefix 416 /// will be added to the name of the original section. 417 static StringRef getOrgSecPrefix() { return ".bolt.org"; } 418 419 /// Section name used for extra BOLT code in addition to .text. 420 static StringRef getBOLTTextSectionName() { return ".bolt.text"; } 421 422 /// Symbol markers for BOLT reserved area. 423 static StringRef getBOLTReservedStart() { return "__bolt_reserved_start"; } 424 static StringRef getBOLTReservedEnd() { return "__bolt_reserved_end"; } 425 426 /// Common section names. 427 static StringRef getEHFrameSectionName() { return ".eh_frame"; } 428 static StringRef getEHFrameHdrSectionName() { return ".eh_frame_hdr"; } 429 static StringRef getRelaDynSectionName() { return ".rela.dyn"; } 430 431 /// FILE symbol name used for local fragments of global functions. 432 static StringRef getBOLTFileSymbolName() { return "bolt-pseudo.o"; } 433 434 /// An instance of the input binary we are processing, externally owned. 435 llvm::object::ELFObjectFileBase *InputFile; 436 437 /// Command line args used to process binary. 438 const int Argc; 439 const char *const *Argv; 440 StringRef ToolPath; 441 442 std::unique_ptr<ProfileReaderBase> ProfileReader; 443 444 std::unique_ptr<BinaryContext> BC; 445 std::unique_ptr<CFIReaderWriter> CFIRdWrt; 446 447 // Run ExecutionEngine linker with custom memory manager and symbol resolver. 448 std::unique_ptr<BOLTLinker> Linker; 449 450 /// Output file where we mix original code from the input binary and 451 /// optimized code for selected functions. 452 std::unique_ptr<ToolOutputFile> Out; 453 454 /// Offset in the input file where non-allocatable sections start. 455 uint64_t FirstNonAllocatableOffset{0}; 456 457 /// Information about program header table. 458 uint64_t PHDRTableAddress{0}; 459 uint64_t PHDRTableOffset{0}; 460 unsigned Phnum{0}; 461 462 /// New code segment info. 463 uint64_t NewTextSegmentAddress{0}; 464 uint64_t NewTextSegmentOffset{0}; 465 uint64_t NewTextSegmentSize{0}; 466 467 /// New writable segment info. 468 uint64_t NewWritableSegmentAddress{0}; 469 uint64_t NewWritableSegmentSize{0}; 470 471 /// Track next available address for new allocatable sections. 472 uint64_t NextAvailableAddress{0}; 473 474 /// Location and size of dynamic relocations. 475 std::optional<uint64_t> DynamicRelocationsAddress; 476 uint64_t DynamicRelocationsSize{0}; 477 uint64_t DynamicRelativeRelocationsCount{0}; 478 479 // Location and size of .relr.dyn relocations. 480 std::optional<uint64_t> DynamicRelrAddress; 481 uint64_t DynamicRelrSize{0}; 482 uint64_t DynamicRelrEntrySize{0}; 483 484 /// PLT relocations are special kind of dynamic relocations stored separately. 485 std::optional<uint64_t> PLTRelocationsAddress; 486 uint64_t PLTRelocationsSize{0}; 487 488 /// True if relocation of specified type came from .rela.plt 489 DenseMap<uint64_t, bool> IsJmpRelocation; 490 491 /// Index of specified symbol in the dynamic symbol table. NOTE Currently it 492 /// is filled and used only with the relocations-related symbols. 493 std::unordered_map<const MCSymbol *, uint32_t> SymbolIndex; 494 495 /// Store all non-zero symbols in this map for a quick address lookup. 496 std::multimap<uint64_t, llvm::object::SymbolRef> FileSymRefs; 497 498 /// FILE symbols used for disambiguating split function parents. 499 std::vector<ELFSymbolRef> FileSymbols; 500 501 std::unique_ptr<DWARFRewriter> DebugInfoRewriter; 502 503 std::unique_ptr<BoltAddressTranslation> BAT; 504 505 /// Number of local symbols in newly written symbol table. 506 uint64_t NumLocalSymbols{0}; 507 508 /// Information on special Procedure Linkage Table sections. There are 509 /// multiple variants generated by different linkers. 510 struct PLTSectionInfo { 511 const char *Name; 512 uint64_t EntrySize{0}; 513 }; 514 515 /// Different types of X86-64 PLT sections. 516 const PLTSectionInfo X86_64_PLTSections[5] = {{".plt", 16}, 517 {".plt.got", 8}, 518 {".plt.sec", 8}, 519 {".iplt", 16}, 520 {nullptr, 0}}; 521 522 /// AArch64 PLT sections. 523 const PLTSectionInfo AArch64_PLTSections[4] = { 524 {".plt"}, {".plt.got"}, {".iplt"}, {nullptr}}; 525 526 /// RISCV PLT sections. 527 const PLTSectionInfo RISCV_PLTSections[2] = {{".plt"}, {nullptr}}; 528 529 /// Return PLT information for a section with \p SectionName or nullptr 530 /// if the section is not PLT. 531 const PLTSectionInfo *getPLTSectionInfo(StringRef SectionName) { 532 const PLTSectionInfo *PLTSI = nullptr; 533 switch (BC->TheTriple->getArch()) { 534 default: 535 break; 536 case Triple::x86_64: 537 PLTSI = X86_64_PLTSections; 538 break; 539 case Triple::aarch64: 540 PLTSI = AArch64_PLTSections; 541 break; 542 case Triple::riscv64: 543 PLTSI = RISCV_PLTSections; 544 break; 545 } 546 for (; PLTSI && PLTSI->Name; ++PLTSI) 547 if (SectionName == PLTSI->Name) 548 return PLTSI; 549 550 return nullptr; 551 } 552 553 /// Exception handling and stack unwinding information in this binary. 554 ErrorOr<BinarySection &> EHFrameSection{std::errc::bad_address}; 555 556 /// Helper for accessing sections by name. 557 BinarySection *getSection(const Twine &Name) { 558 ErrorOr<BinarySection &> ErrOrSection = BC->getUniqueSectionByName(Name); 559 return ErrOrSection ? &ErrOrSection.get() : nullptr; 560 } 561 562 /// Section header string table. 563 StringTableBuilder SHStrTab; 564 565 /// A rewrite of strtab 566 std::string NewStrTab; 567 568 /// Number of processed to data relocations. Used to implement the 569 /// -max-relocations debugging option. 570 uint64_t NumDataRelocations{0}; 571 572 /// Number of failed to process relocations. 573 uint64_t NumFailedRelocations{0}; 574 575 NameResolver NR; 576 577 // Regex object matching split function names. 578 const Regex FunctionFragmentTemplate{"(.*)\\.(cold|warm)(\\.[0-9]+)?"}; 579 580 friend class RewriteInstanceDiff; 581 }; 582 583 MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch, 584 const MCInstrAnalysis *Analysis, 585 const MCInstrInfo *Info, 586 const MCRegisterInfo *RegInfo, 587 const MCSubtargetInfo *STI); 588 589 } // namespace bolt 590 } // namespace llvm 591 592 #endif 593