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