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/Utils/NameResolver.h" 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/MC/StringTableBuilder.h" 20 #include "llvm/Object/ELFObjectFile.h" 21 #include "llvm/Object/ObjectFile.h" 22 #include "llvm/Support/Error.h" 23 #include <map> 24 #include <set> 25 #include <unordered_map> 26 27 namespace llvm { 28 29 class ToolOutputFile; 30 31 namespace bolt { 32 33 class BoltAddressTranslation; 34 class CFIReaderWriter; 35 class DWARFRewriter; 36 class ProfileReaderBase; 37 38 /// This class encapsulates all data necessary to carry on binary reading, 39 /// disassembly, CFG building, BB reordering (among other binary-level 40 /// optimizations) and rewriting. It also has the logic to coordinate such 41 /// events. 42 class RewriteInstance { 43 public: 44 // This constructor has complex initialization that can fail during 45 // construction. Constructors can’t return errors, so clients must test \p Err 46 // after the object is constructed. Use createRewriteInstance instead. 47 RewriteInstance(llvm::object::ELFObjectFileBase *File, const int Argc, 48 const char *const *Argv, StringRef ToolPath, Error &Err); 49 50 static Expected<std::unique_ptr<RewriteInstance>> 51 createRewriteInstance(llvm::object::ELFObjectFileBase *File, const int Argc, 52 const char *const *Argv, StringRef ToolPath); 53 ~RewriteInstance(); 54 55 /// Assign profile from \p Filename to this instance. 56 Error setProfile(StringRef Filename); 57 58 /// Run all the necessary steps to read, optimize and rewrite the binary. 59 Error run(); 60 61 /// Diff this instance against another one. Non-const since we may run passes 62 /// to fold identical functions. 63 void compare(RewriteInstance &RI2); 64 65 /// Return binary context. getBinaryContext()66 const BinaryContext &getBinaryContext() const { return *BC; } 67 68 /// Return total score of all functions for this instance. getTotalScore()69 uint64_t getTotalScore() const { return BC->TotalScore; } 70 71 /// Return the name of the input file. getInputFilename()72 StringRef getInputFilename() const { 73 assert(InputFile && "cannot have an instance without a file"); 74 return InputFile->getFileName(); 75 } 76 77 /// Set the build-id string if we did not fail to parse the contents of the 78 /// ELF note section containing build-id information. 79 void parseBuildID(); 80 81 /// The build-id is typically a stream of 20 bytes. Return these bytes in 82 /// printable hexadecimal form if they are available, or NoneType otherwise. 83 Optional<std::string> getPrintableBuildID() const; 84 85 /// If this instance uses a profile, return appropriate profile reader. getProfileReader()86 const ProfileReaderBase *getProfileReader() const { 87 return ProfileReader.get(); 88 } 89 90 private: 91 using ELF64LEPhdrTy = object::ELF64LEFile::Elf_Phdr; 92 93 /// Populate array of binary functions and other objects of interest 94 /// from meta data in the file. 95 void discoverFileObjects(); 96 97 /// Read info from special sections. E.g. eh_frame and .gcc_except_table 98 /// for exception and stack unwinding information. 99 Error readSpecialSections(); 100 101 /// Adjust supplied command-line options based on input data. 102 void adjustCommandLineOptions(); 103 104 /// Process runtime relocations. 105 void processDynamicRelocations(); 106 107 /// Process input relocations. 108 void processRelocations(); 109 110 /// Insert an LKMarker for a given code pointer \p PC from a non-code section 111 /// \p SectionName. 112 void insertLKMarker(uint64_t PC, uint64_t SectionOffset, 113 int32_t PCRelativeOffset, bool IsPCRelative, 114 StringRef SectionName); 115 116 /// Process linux kernel special sections and their relocations. 117 void processLKSections(); 118 119 /// Process special linux kernel section, __ex_table. 120 void processLKExTable(); 121 122 /// Process special linux kernel section, .pci_fixup. 123 void processLKPCIFixup(); 124 125 /// Process __ksymtab and __ksymtab_gpl. 126 void processLKKSymtab(bool IsGPL = false); 127 128 /// Process special linux kernel section, __bug_table. 129 void processLKBugTable(); 130 131 /// Process special linux kernel section, .smp_locks. 132 void processLKSMPLocks(); 133 134 /// Read relocations from a given section. 135 void readDynamicRelocations(const object::SectionRef &Section, bool IsJmpRel); 136 137 /// Read relocations from a given section. 138 void readRelocations(const object::SectionRef &Section); 139 140 /// Mark functions that are not meant for processing as ignored. 141 void selectFunctionsToProcess(); 142 143 /// Read information from debug sections. 144 void readDebugInfo(); 145 146 /// Read profile data without having disassembled functions available. 147 void preprocessProfileData(); 148 149 void processProfileDataPreCFG(); 150 151 /// Associate profile data with functions and data objects. 152 void processProfileData(); 153 154 /// Disassemble each function in the binary and associate it with a 155 /// BinaryFunction object, preparing all information necessary for binary 156 /// optimization. 157 void disassembleFunctions(); 158 159 void buildFunctionsCFG(); 160 161 void postProcessFunctions(); 162 163 /// Run optimizations that operate at the binary, or post-linker, level. 164 void runOptimizationPasses(); 165 166 /// Write code and data into an intermediary object file, map virtual to real 167 /// addresses and link the object file, resolving all relocations and 168 /// performing final relaxation. 169 void emitAndLink(); 170 171 /// Link additional runtime code to support instrumentation. 172 void linkRuntime(); 173 174 /// Update debug and other auxiliary information in the file. 175 void updateMetadata(); 176 177 /// Update SDTMarkers' locations for the output binary. 178 void updateSDTMarkers(); 179 180 /// Update LKMarkers' locations for the output binary. 181 void updateLKMarkers(); 182 183 /// Update address of MCDecodedPseudoProbe. 184 void updatePseudoProbes(); 185 186 /// Encode MCDecodedPseudoProbe. 187 void encodePseudoProbes(); 188 189 /// Return the list of code sections in the output order. 190 std::vector<BinarySection *> getCodeSections(); 191 192 /// Map all sections to their final addresses. 193 void mapCodeSections(RuntimeDyld &RTDyld); 194 void mapDataSections(RuntimeDyld &RTDyld); 195 void mapFileSections(RuntimeDyld &RTDyld); 196 void mapExtraSections(RuntimeDyld &RTDyld); 197 198 /// Update output object's values based on the final \p Layout. 199 void updateOutputValues(const MCAsmLayout &Layout); 200 201 /// Rewrite back all functions (hopefully optimized) that fit in the original 202 /// memory footprint for that function. If the function is now larger and does 203 /// not fit in the binary, reject it and preserve the original version of the 204 /// function. If we couldn't understand the function for some reason in 205 /// disassembleFunctions(), also preserve the original version. 206 void rewriteFile(); 207 208 /// Return address of a function in the new binary corresponding to 209 /// \p OldAddress address in the original binary. 210 uint64_t getNewFunctionAddress(uint64_t OldAddress); 211 212 /// Return address of a function or moved data in the new binary 213 /// corresponding to \p OldAddress address in the original binary. 214 uint64_t getNewFunctionOrDataAddress(uint64_t OldAddress); 215 216 /// Return value for the symbol \p Name in the output. 217 uint64_t getNewValueForSymbol(const StringRef Name); 218 219 /// Detect addresses and offsets available in the binary for allocating 220 /// new sections. 221 Error discoverStorage(); 222 223 /// Adjust function sizes and set proper maximum size values after the whole 224 /// symbol table has been processed. 225 void adjustFunctionBoundaries(); 226 227 /// Make .eh_frame section relocatable. 228 void relocateEHFrameSection(); 229 230 /// Analyze relocation \p Rel. 231 /// Return true if the relocation was successfully processed, false otherwise. 232 /// The \p SymbolName, \p SymbolAddress, \p Addend and \p ExtractedValue 233 /// parameters will be set on success. The \p Skip argument indicates 234 /// that the relocation was analyzed, but it must not be processed. 235 bool analyzeRelocation(const object::RelocationRef &Rel, uint64_t RType, 236 std::string &SymbolName, bool &IsSectionRelocation, 237 uint64_t &SymbolAddress, int64_t &Addend, 238 uint64_t &ExtractedValue, bool &Skip) const; 239 240 /// Rewrite non-allocatable sections with modifications. 241 void rewriteNoteSections(); 242 243 /// Write .eh_frame_hdr. 244 void writeEHFrameHeader(); 245 246 /// Disassemble and create function entries for PLT. 247 void disassemblePLT(); 248 249 /// Auxiliary function to create .plt BinaryFunction on \p EntryAddres 250 /// with the \p EntrySize size. \p TargetAddress is the .got entry 251 /// associated address. 252 void createPLTBinaryFunction(uint64_t TargetAddress, uint64_t EntryAddress, 253 uint64_t EntrySize); 254 255 /// Disassemble aarch64-specific .plt \p Section auxiliary function 256 void disassemblePLTSectionAArch64(BinarySection &Section); 257 258 /// Disassemble X86-specific .plt \p Section auxiliary function. \p EntrySize 259 /// is the expected .plt \p Section entry function size. 260 void disassemblePLTSectionX86(BinarySection &Section, uint64_t EntrySize); 261 262 /// ELF-specific part. TODO: refactor into new class. 263 #define ELF_FUNCTION(TYPE, FUNC) \ 264 template <typename ELFT> TYPE FUNC(object::ELFObjectFile<ELFT> *Obj); \ 265 TYPE FUNC() { \ 266 if (auto *ELF32LE = dyn_cast<object::ELF32LEObjectFile>(InputFile)) \ 267 return FUNC(ELF32LE); \ 268 if (auto *ELF64LE = dyn_cast<object::ELF64LEObjectFile>(InputFile)) \ 269 return FUNC(ELF64LE); \ 270 if (auto *ELF32BE = dyn_cast<object::ELF32BEObjectFile>(InputFile)) \ 271 return FUNC(ELF32BE); \ 272 auto *ELF64BE = cast<object::ELF64BEObjectFile>(InputFile); \ 273 return FUNC(ELF64BE); \ 274 } 275 276 /// Patch ELF book-keeping info. 277 void patchELFPHDRTable(); 278 279 /// Create section header table. 280 ELF_FUNCTION(void, patchELFSectionHeaderTable); 281 282 /// Create the regular symbol table and patch dyn symbol tables. 283 ELF_FUNCTION(void, patchELFSymTabs); 284 285 /// Read dynamic section/segment of ELF. 286 ELF_FUNCTION(Error, readELFDynamic); 287 288 /// Patch dynamic section/segment of ELF. 289 ELF_FUNCTION(void, patchELFDynamic); 290 291 /// Patch .got 292 ELF_FUNCTION(void, patchELFGOT); 293 294 /// Patch allocatable relocation sections. 295 ELF_FUNCTION(void, patchELFAllocatableRelaSections); 296 297 /// Finalize memory image of section header string table. 298 ELF_FUNCTION(void, finalizeSectionStringTable); 299 300 /// Return a name of the input file section in the output file. 301 template <typename ELFObjType, typename ELFShdrTy> 302 std::string getOutputSectionName(const ELFObjType &Obj, 303 const ELFShdrTy &Section); 304 305 /// Return a list of all sections to include in the output binary. 306 /// Populate \p NewSectionIndex with a map of input to output indices. 307 template <typename ELFT> 308 std::vector<typename object::ELFObjectFile<ELFT>::Elf_Shdr> 309 getOutputSections(object::ELFObjectFile<ELFT> *File, 310 std::vector<uint32_t> &NewSectionIndex); 311 312 /// Return true if \p Section should be stripped from the output binary. 313 template <typename ELFShdrTy> 314 bool shouldStrip(const ELFShdrTy &Section, StringRef SectionName); 315 316 /// Write ELF symbol table using \p Write and \p AddToStrTab functions 317 /// based on the input file symbol table passed in \p SymTabSection. 318 /// \p IsDynSym is set to true for dynamic symbol table since we 319 /// are updating it in-place with minimal modifications. 320 template <typename ELFT, typename WriteFuncTy, typename StrTabFuncTy> 321 void updateELFSymbolTable( 322 object::ELFObjectFile<ELFT> *File, bool IsDynSym, 323 const typename object::ELFObjectFile<ELFT>::Elf_Shdr &SymTabSection, 324 const std::vector<uint32_t> &NewSectionIndex, WriteFuncTy Write, 325 StrTabFuncTy AddToStrTab); 326 327 /// Get output index in dynamic symbol table. getOutputDynamicSymbolIndex(const MCSymbol * Symbol)328 uint32_t getOutputDynamicSymbolIndex(const MCSymbol *Symbol) { 329 auto It = SymbolIndex.find(Symbol); 330 if (It != SymbolIndex.end()) 331 return It->second; 332 return 0; 333 } 334 335 /// Add a notes section containing the BOLT revision and command line options. 336 void addBoltInfoSection(); 337 338 /// Add a notes section containing the serialized BOLT Address Translation 339 /// maps that can be used to enable sampling of the output binary for the 340 /// purpose of generating BOLT profile data for the input binary. 341 void addBATSection(); 342 343 /// Loop over now emitted functions to write translation maps 344 void encodeBATSection(); 345 346 /// Update the ELF note section containing the binary build-id to reflect 347 /// a new build-id, so tools can differentiate between the old and the 348 /// rewritten binary. 349 void patchBuildID(); 350 351 /// Return file offset corresponding to a given virtual address. getFileOffsetFor(uint64_t Address)352 uint64_t getFileOffsetFor(uint64_t Address) { 353 assert(Address >= NewTextSegmentAddress && 354 "address in not in the new text segment"); 355 return Address - NewTextSegmentAddress + NewTextSegmentOffset; 356 } 357 358 /// Return file offset corresponding to a virtual \p Address. 359 /// Return 0 if the address has no mapping in the file, including being 360 /// part of .bss section. 361 uint64_t getFileOffsetForAddress(uint64_t Address) const; 362 363 /// Return true if we will overwrite contents of the section instead 364 /// of appending contents to it. 365 bool willOverwriteSection(StringRef SectionName); 366 367 /// Parse .note.stapsdt section 368 void parseSDTNotes(); 369 370 /// Parse .pseudo_probe_desc section and .pseudo_probe section 371 /// Setup Pseudo probe decoder 372 void parsePseudoProbe(); 373 374 /// Print all SDT markers 375 void printSDTMarkers(); 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 /// Return true if the section holds linux kernel symbol information. 392 static bool isKSymtabSection(StringRef SectionName); 393 394 /// Adds Debug section to overwrite. addToDebugSectionsToOverwrite(const char * Section)395 static void addToDebugSectionsToOverwrite(const char *Section) { 396 DebugSectionsToOverwrite.emplace_back(Section); 397 } 398 399 private: 400 /// Get the contents of the LSDA section for this binary. 401 ArrayRef<uint8_t> getLSDAData(); 402 403 /// Get the mapped address of the LSDA section for this binary. 404 uint64_t getLSDAAddress(); 405 406 static const char TimerGroupName[]; 407 408 static const char TimerGroupDesc[]; 409 410 /// Alignment value used for .eh_frame_hdr. 411 static constexpr uint64_t EHFrameHdrAlign = 4; 412 413 /// String to be added before the original section name. 414 /// 415 /// When BOLT creates a new section with the same name as the one in the 416 /// input file, it may need to preserve the original section. This prefix 417 /// will be added to the name of the original section. getOrgSecPrefix()418 static StringRef getOrgSecPrefix() { return ".bolt.org"; } 419 420 /// Section name used for new code. getBOLTTextSectionName()421 static StringRef getBOLTTextSectionName() { return ".bolt.text"; } 422 423 /// An instance of the input binary we are processing, externally owned. 424 llvm::object::ELFObjectFileBase *InputFile; 425 426 /// Command line args used to process binary. 427 const int Argc; 428 const char *const *Argv; 429 StringRef ToolPath; 430 431 std::unique_ptr<ProfileReaderBase> ProfileReader; 432 433 std::unique_ptr<BinaryContext> BC; 434 std::unique_ptr<CFIReaderWriter> CFIRdWrt; 435 436 // Run ExecutionEngine linker with custom memory manager and symbol resolver. 437 std::unique_ptr<RuntimeDyld> RTDyld; 438 439 /// Output file where we mix original code from the input binary and 440 /// optimized code for selected functions. 441 std::unique_ptr<ToolOutputFile> Out; 442 443 /// Offset in the input file where non-allocatable sections start. 444 uint64_t FirstNonAllocatableOffset{0}; 445 446 /// Information about program header table. 447 uint64_t PHDRTableAddress{0}; 448 uint64_t PHDRTableOffset{0}; 449 unsigned Phnum{0}; 450 451 /// New code segment info. 452 uint64_t NewTextSegmentAddress{0}; 453 uint64_t NewTextSegmentOffset{0}; 454 uint64_t NewTextSegmentSize{0}; 455 456 /// Track next available address for new allocatable sections. 457 uint64_t NextAvailableAddress{0}; 458 459 /// Location and size of dynamic relocations. 460 Optional<uint64_t> DynamicRelocationsAddress; 461 uint64_t DynamicRelocationsSize{0}; 462 uint64_t DynamicRelativeRelocationsCount{0}; 463 464 /// PLT relocations are special kind of dynamic relocations stored separately. 465 Optional<uint64_t> PLTRelocationsAddress; 466 uint64_t PLTRelocationsSize{0}; 467 468 /// True if relocation of specified type came from .rela.plt 469 DenseMap<uint64_t, bool> IsJmpRelocation; 470 471 /// Index of specified symbol in the dynamic symbol table. NOTE Currently it 472 /// is filled and used only with the relocations-related symbols. 473 std::unordered_map<const MCSymbol *, uint32_t> SymbolIndex; 474 475 /// Store all non-zero symbols in this map for a quick address lookup. 476 std::map<uint64_t, llvm::object::SymbolRef> FileSymRefs; 477 478 std::unique_ptr<DWARFRewriter> DebugInfoRewriter; 479 480 std::unique_ptr<BoltAddressTranslation> BAT; 481 482 /// Number of local symbols in newly written symbol table. 483 uint64_t NumLocalSymbols{0}; 484 485 /// Information on special Procedure Linkage Table sections. There are 486 /// multiple variants generated by different linkers. 487 struct PLTSectionInfo { 488 const char *Name; 489 uint64_t EntrySize{0}; 490 }; 491 492 /// Different types of X86-64 PLT sections. 493 const PLTSectionInfo X86_64_PLTSections[4] = { 494 { ".plt", 16 }, 495 { ".plt.got", 8 }, 496 { ".plt.sec", 8 }, 497 { nullptr, 0 } 498 }; 499 500 /// AArch64 PLT sections. 501 const PLTSectionInfo AArch64_PLTSections[3] = { 502 {".plt"}, {".iplt"}, {nullptr}}; 503 504 /// Return PLT information for a section with \p SectionName or nullptr 505 /// if the section is not PLT. getPLTSectionInfo(StringRef SectionName)506 const PLTSectionInfo *getPLTSectionInfo(StringRef SectionName) { 507 const PLTSectionInfo *PLTSI = nullptr; 508 switch (BC->TheTriple->getArch()) { 509 default: 510 break; 511 case Triple::x86_64: 512 PLTSI = X86_64_PLTSections; 513 break; 514 case Triple::aarch64: 515 PLTSI = AArch64_PLTSections; 516 break; 517 } 518 for (; PLTSI && PLTSI->Name; ++PLTSI) 519 if (SectionName == PLTSI->Name) 520 return PLTSI; 521 522 return nullptr; 523 } 524 525 /// Exception handling and stack unwinding information in this binary. 526 ErrorOr<BinarySection &> LSDASection{std::errc::bad_address}; 527 ErrorOr<BinarySection &> EHFrameSection{std::errc::bad_address}; 528 529 /// .got.plt sections. 530 /// 531 /// Contains jump slots (addresses) indirectly referenced by 532 /// instructions in .plt section. 533 ErrorOr<BinarySection &> GOTPLTSection{std::errc::bad_address}; 534 535 /// .rela.plt section. 536 /// 537 /// Contains relocations against .got.plt. 538 ErrorOr<BinarySection &> RelaPLTSection{std::errc::bad_address}; 539 ErrorOr<BinarySection &> RelaDynSection{std::errc::bad_address}; 540 541 /// .note.gnu.build-id section. 542 ErrorOr<BinarySection &> BuildIDSection{std::errc::bad_address}; 543 544 /// .note.stapsdt section. 545 /// Contains information about statically defined tracing points 546 ErrorOr<BinarySection &> SDTSection{std::errc::bad_address}; 547 548 /// .pseudo_probe_desc section. 549 /// Contains information about pseudo probe description, like its related 550 /// function 551 ErrorOr<BinarySection &> PseudoProbeDescSection{std::errc::bad_address}; 552 553 /// .pseudo_probe section. 554 /// Contains information about pseudo probe details, like its address 555 ErrorOr<BinarySection &> PseudoProbeSection{std::errc::bad_address}; 556 557 /// A reference to the build-id bytes in the original binary 558 StringRef BuildID; 559 560 /// Keep track of functions we fail to write in the binary. We need to avoid 561 /// rewriting CFI info for these functions. 562 std::vector<uint64_t> FailedAddresses; 563 564 /// Keep track of which functions didn't fit in their original space in the 565 /// last emission, so that we may either decide to split or not optimize them. 566 std::set<uint64_t> LargeFunctions; 567 568 /// Section header string table. 569 StringTableBuilder SHStrTab; 570 std::vector<std::string> SHStrTabPool; 571 572 /// A rewrite of strtab 573 std::string NewStrTab; 574 575 /// Number of processed to data relocations. Used to implement the 576 /// -max-relocations debugging option. 577 uint64_t NumDataRelocations{0}; 578 579 /// Number of failed to process relocations. 580 uint64_t NumFailedRelocations{0}; 581 582 NameResolver NR; 583 584 friend class RewriteInstanceDiff; 585 }; 586 587 MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch, 588 const MCInstrAnalysis *Analysis, 589 const MCInstrInfo *Info, 590 const MCRegisterInfo *RegInfo); 591 592 } // namespace bolt 593 } // namespace llvm 594 595 #endif 596