xref: /llvm-project/bolt/include/bolt/Rewrite/RewriteInstance.h (revision ceb7214be0287f536b292a41f8a7dc2e1467d72d)
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