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