1//===- bolt/Rewrite/RewriteInstance.cpp - ELF rewriter --------------------===//
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#include "bolt/Rewrite/RewriteInstance.h"
10#include "bolt/Core/AddressMap.h"
11#include "bolt/Core/BinaryContext.h"
12#include "bolt/Core/BinaryEmitter.h"
13#include "bolt/Core/BinaryFunction.h"
14#include "bolt/Core/DebugData.h"
15#include "bolt/Core/Exceptions.h"
16#include "bolt/Core/FunctionLayout.h"
17#include "bolt/Core/MCPlusBuilder.h"
18#include "bolt/Core/ParallelUtilities.h"
19#include "bolt/Core/Relocation.h"
20#include "bolt/Passes/BinaryPasses.h"
21#include "bolt/Passes/CacheMetrics.h"
22#include "bolt/Passes/IdenticalCodeFolding.h"
23#include "bolt/Passes/PAuthGadgetScanner.h"
24#include "bolt/Passes/ReorderFunctions.h"
25#include "bolt/Profile/BoltAddressTranslation.h"
26#include "bolt/Profile/DataAggregator.h"
27#include "bolt/Profile/DataReader.h"
28#include "bolt/Profile/YAMLProfileReader.h"
29#include "bolt/Profile/YAMLProfileWriter.h"
30#include "bolt/Rewrite/BinaryPassManager.h"
31#include "bolt/Rewrite/DWARFRewriter.h"
32#include "bolt/Rewrite/ExecutableFileMemoryManager.h"
33#include "bolt/Rewrite/JITLinkLinker.h"
34#include "bolt/Rewrite/MetadataRewriters.h"
35#include "bolt/RuntimeLibs/HugifyRuntimeLibrary.h"
36#include "bolt/RuntimeLibs/InstrumentationRuntimeLibrary.h"
37#include "bolt/Utils/CommandLineOpts.h"
38#include "bolt/Utils/Utils.h"
39#include "llvm/ADT/AddressRanges.h"
40#include "llvm/ADT/STLExtras.h"
41#include "llvm/DebugInfo/DWARF/DWARFContext.h"
42#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
43#include "llvm/MC/MCAsmBackend.h"
44#include "llvm/MC/MCAsmInfo.h"
45#include "llvm/MC/MCDisassembler/MCDisassembler.h"
46#include "llvm/MC/MCObjectStreamer.h"
47#include "llvm/MC/MCStreamer.h"
48#include "llvm/MC/MCSymbol.h"
49#include "llvm/MC/TargetRegistry.h"
50#include "llvm/Object/ObjectFile.h"
51#include "llvm/Support/Alignment.h"
52#include "llvm/Support/Casting.h"
53#include "llvm/Support/CommandLine.h"
54#include "llvm/Support/DataExtractor.h"
55#include "llvm/Support/Errc.h"
56#include "llvm/Support/Error.h"
57#include "llvm/Support/FileSystem.h"
58#include "llvm/Support/ManagedStatic.h"
59#include "llvm/Support/Timer.h"
60#include "llvm/Support/ToolOutputFile.h"
61#include "llvm/Support/raw_ostream.h"
62#include <algorithm>
63#include <fstream>
64#include <memory>
65#include <optional>
66#include <system_error>
67
68#undef DEBUG_TYPE
69#define DEBUG_TYPE "bolt"
70
71using namespace llvm;
72using namespace object;
73using namespace bolt;
74
75extern cl::opt<uint32_t> X86AlignBranchBoundary;
76extern cl::opt<bool> X86AlignBranchWithin32BBoundaries;
77
78namespace opts {
79
80extern cl::list<std::string> HotTextMoveSections;
81extern cl::opt<bool> Hugify;
82extern cl::opt<bool> Instrument;
83extern cl::opt<bool> KeepNops;
84extern cl::opt<bool> Lite;
85extern cl::list<std::string> ReorderData;
86extern cl::opt<bolt::ReorderFunctions::ReorderType> ReorderFunctions;
87extern cl::opt<bool> TerminalTrap;
88extern cl::opt<bool> TimeBuild;
89extern cl::opt<bool> TimeRewrite;
90extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,
91 llvm::bolt::DeprecatedICFNumericOptionParser>
92 ICF;
93
94static cl::opt<bool>
95 AllowStripped("allow-stripped",
96 cl::desc("allow processing of stripped binaries"), cl::Hidden,
97 cl::cat(BoltCategory));
98
99static cl::opt<bool> ForceToDataRelocations(
100 "force-data-relocations",
101 cl::desc("force relocations to data sections to always be processed"),
102
103 cl::Hidden, cl::cat(BoltCategory));
104
105static cl::opt<std::string>
106 BoltID("bolt-id",
107 cl::desc("add any string to tag this execution in the "
108 "output binary via bolt info section"),
109 cl::cat(BoltCategory));
110
111cl::opt<bool> DumpDotAll(
112 "dump-dot-all",
113 cl::desc("dump function CFGs to graphviz format after each stage;"
114 "enable '-print-loops' for color-coded blocks"),
115 cl::Hidden, cl::cat(BoltCategory));
116
117static cl::list<std::string>
118ForceFunctionNames("funcs",
119 cl::CommaSeparated,
120 cl::desc("limit optimizations to functions from the list"),
121 cl::value_desc("func1,func2,func3,..."),
122 cl::Hidden,
123 cl::cat(BoltCategory));
124
125static cl::opt<std::string>
126FunctionNamesFile("funcs-file",
127 cl::desc("file with list of functions to optimize"),
128 cl::Hidden,
129 cl::cat(BoltCategory));
130
131static cl::list<std::string> ForceFunctionNamesNR(
132 "funcs-no-regex", cl::CommaSeparated,
133 cl::desc("limit optimizations to functions from the list (non-regex)"),
134 cl::value_desc("func1,func2,func3,..."), cl::Hidden, cl::cat(BoltCategory));
135
136static cl::opt<std::string> FunctionNamesFileNR(
137 "funcs-file-no-regex",
138 cl::desc("file with list of functions to optimize (non-regex)"), cl::Hidden,
139 cl::cat(BoltCategory));
140
141cl::opt<bool>
142KeepTmp("keep-tmp",
143 cl::desc("preserve intermediate .o file"),
144 cl::Hidden,
145 cl::cat(BoltCategory));
146
147static cl::opt<unsigned>
148LiteThresholdPct("lite-threshold-pct",
149 cl::desc("threshold (in percent) for selecting functions to process in lite "
150 "mode. Higher threshold means fewer functions to process. E.g "
151 "threshold of 90 means only top 10 percent of functions with "
152 "profile will be processed."),
153 cl::init(Val: 0),
154 cl::ZeroOrMore,
155 cl::Hidden,
156 cl::cat(BoltOptCategory));
157
158static cl::opt<unsigned> LiteThresholdCount(
159 "lite-threshold-count",
160 cl::desc("similar to '-lite-threshold-pct' but specify threshold using "
161 "absolute function call count. I.e. limit processing to functions "
162 "executed at least the specified number of times."),
163 cl::init(Val: 0), cl::Hidden, cl::cat(BoltOptCategory));
164
165static cl::opt<unsigned>
166 MaxFunctions("max-funcs",
167 cl::desc("maximum number of functions to process"), cl::Hidden,
168 cl::cat(BoltCategory));
169
170static cl::opt<unsigned> MaxDataRelocations(
171 "max-data-relocations",
172 cl::desc("maximum number of data relocations to process"), cl::Hidden,
173 cl::cat(BoltCategory));
174
175cl::opt<bool> PrintAll("print-all",
176 cl::desc("print functions after each stage"), cl::Hidden,
177 cl::cat(BoltCategory));
178
179static cl::opt<bool>
180 PrintProfile("print-profile",
181 cl::desc("print functions after attaching profile"),
182 cl::Hidden, cl::cat(BoltCategory));
183
184cl::opt<bool> PrintCFG("print-cfg",
185 cl::desc("print functions after CFG construction"),
186 cl::Hidden, cl::cat(BoltCategory));
187
188cl::opt<bool> PrintDisasm("print-disasm",
189 cl::desc("print function after disassembly"),
190 cl::Hidden, cl::cat(BoltCategory));
191
192static cl::opt<bool>
193 PrintGlobals("print-globals",
194 cl::desc("print global symbols after disassembly"), cl::Hidden,
195 cl::cat(BoltCategory));
196
197extern cl::opt<bool> PrintSections;
198
199static cl::opt<bool> PrintLoopInfo("print-loops",
200 cl::desc("print loop related information"),
201 cl::Hidden, cl::cat(BoltCategory));
202
203static cl::opt<cl::boolOrDefault> RelocationMode(
204 "relocs", cl::desc("use relocations in the binary (default=autodetect)"),
205 cl::cat(BoltCategory));
206
207extern cl::opt<std::string> SaveProfile;
208
209static cl::list<std::string>
210SkipFunctionNames("skip-funcs",
211 cl::CommaSeparated,
212 cl::desc("list of functions to skip"),
213 cl::value_desc("func1,func2,func3,..."),
214 cl::Hidden,
215 cl::cat(BoltCategory));
216
217static cl::opt<std::string>
218SkipFunctionNamesFile("skip-funcs-file",
219 cl::desc("file with list of functions to skip"),
220 cl::Hidden,
221 cl::cat(BoltCategory));
222
223static cl::opt<bool> TrapOldCode(
224 "trap-old-code",
225 cl::desc("insert traps in old function bodies (relocation mode)"),
226 cl::Hidden, cl::cat(BoltCategory));
227
228static cl::opt<std::string> DWPPathName("dwp",
229 cl::desc("Path and name to DWP file."),
230 cl::Hidden, cl::init(Val: ""),
231 cl::cat(BoltCategory));
232
233static cl::opt<bool>
234UseGnuStack("use-gnu-stack",
235 cl::desc("use GNU_STACK program header for new segment (workaround for "
236 "issues with strip/objcopy)"),
237 cl::ZeroOrMore,
238 cl::cat(BoltCategory));
239
240static cl::opt<uint64_t> CustomAllocationVMA(
241 "custom-allocation-vma",
242 cl::desc("use a custom address at which new code will be put, "
243 "bypassing BOLT's logic to detect where to put code"),
244 cl::Hidden, cl::cat(BoltCategory));
245
246static cl::opt<bool>
247SequentialDisassembly("sequential-disassembly",
248 cl::desc("performs disassembly sequentially"),
249 cl::init(Val: false),
250 cl::cat(BoltOptCategory));
251
252static cl::opt<bool> WriteBoltInfoSection(
253 "bolt-info", cl::desc("write bolt info section in the output binary"),
254 cl::init(Val: true), cl::Hidden, cl::cat(BoltOutputCategory));
255
256cl::bits<GadgetScannerKind> GadgetScannersToRun(
257 "scanners", cl::desc("which gadget scanners to run"),
258 cl::values(
259 clEnumValN(GS_PACRET, "pacret",
260 "pac-ret: return address protection (subset of \"pauth\")"),
261 clEnumValN(GS_PAUTH, "pauth", "All Pointer Authentication scanners"),
262 clEnumValN(GS_ALL, "all", "All implemented scanners")),
263 cl::ZeroOrMore, cl::CommaSeparated, cl::cat(BinaryAnalysisCategory));
264
265} // namespace opts
266
267// FIXME: implement a better way to mark sections for replacement.
268constexpr const char *RewriteInstance::SectionsToOverwrite[];
269std::vector<std::string> RewriteInstance::DebugSectionsToOverwrite = {
270 ".debug_abbrev", ".debug_aranges", ".debug_line", ".debug_line_str",
271 ".debug_loc", ".debug_loclists", ".debug_ranges", ".debug_rnglists",
272 ".gdb_index", ".debug_addr", ".debug_abbrev", ".debug_info",
273 ".debug_types", ".pseudo_probe"};
274
275const char RewriteInstance::TimerGroupName[] = "rewrite";
276const char RewriteInstance::TimerGroupDesc[] = "Rewrite passes";
277
278namespace llvm {
279namespace bolt {
280
281extern const char *BoltRevision;
282
283// Weird location for createMCPlusBuilder, but this is here to avoid a
284// cyclic dependency of libCore (its natural place) and libTarget. libRewrite
285// can depend on libTarget, but not libCore. Since libRewrite is the only
286// user of this function, we define it here.
287MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch,
288 const MCInstrAnalysis *Analysis,
289 const MCInstrInfo *Info,
290 const MCRegisterInfo *RegInfo,
291 const MCSubtargetInfo *STI) {
292#ifdef X86_AVAILABLE
293 if (Arch == Triple::x86_64)
294 return createX86MCPlusBuilder(Analysis, Info, RegInfo, STI);
295#endif
296
297#ifdef AARCH64_AVAILABLE
298 if (Arch == Triple::aarch64)
299 return createAArch64MCPlusBuilder(Analysis, Info, RegInfo, STI);
300#endif
301
302#ifdef RISCV_AVAILABLE
303 if (Arch == Triple::riscv64)
304 return createRISCVMCPlusBuilder(Analysis, Info, RegInfo, STI);
305#endif
306
307 llvm_unreachable("architecture unsupported by MCPlusBuilder");
308}
309
310} // namespace bolt
311} // namespace llvm
312
313using ELF64LEPhdrTy = ELF64LEFile::Elf_Phdr;
314
315namespace {
316
317bool refersToReorderedSection(ErrorOr<BinarySection &> Section) {
318 return llvm::any_of(Range&: opts::ReorderData, P: [&](const std::string &SectionName) {
319 return Section && Section->getName() == SectionName;
320 });
321}
322
323} // anonymous namespace
324
325Expected<std::unique_ptr<RewriteInstance>>
326RewriteInstance::create(ELFObjectFileBase *File, const int Argc,
327 const char *const *Argv, StringRef ToolPath,
328 raw_ostream &Stdout, raw_ostream &Stderr) {
329 Error Err = Error::success();
330 auto RI = std::make_unique<RewriteInstance>(args&: File, args: Argc, args&: Argv, args&: ToolPath,
331 args&: Stdout, args&: Stderr, args&: Err);
332 if (Err)
333 return std::move(Err);
334 return std::move(RI);
335}
336
337RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc,
338 const char *const *Argv, StringRef ToolPath,
339 raw_ostream &Stdout, raw_ostream &Stderr,
340 Error &Err)
341 : InputFile(File), Argc(Argc), Argv(Argv), ToolPath(ToolPath),
342 SHStrTab(StringTableBuilder::ELF) {
343 ErrorAsOutParameter EAO(&Err);
344 auto ELF64LEFile = dyn_cast<ELF64LEObjectFile>(Val: InputFile);
345 if (!ELF64LEFile) {
346 Err = createStringError(EC: errc::not_supported,
347 S: "Only 64-bit LE ELF binaries are supported");
348 return;
349 }
350
351 bool IsPIC = false;
352 const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();
353 if (Obj.getHeader().e_type != ELF::ET_EXEC) {
354 Stdout << "BOLT-INFO: shared object or position-independent executable "
355 "detected\n";
356 IsPIC = true;
357 }
358
359 // Make sure we don't miss any output on core dumps.
360 Stdout.SetUnbuffered();
361 Stderr.SetUnbuffered();
362 LLVM_DEBUG(dbgs().SetUnbuffered());
363
364 // Read RISCV subtarget features from input file
365 std::unique_ptr<SubtargetFeatures> Features;
366 Triple TheTriple = File->makeTriple();
367 if (TheTriple.getArch() == llvm::Triple::riscv64) {
368 Expected<SubtargetFeatures> FeaturesOrErr = File->getFeatures();
369 if (auto E = FeaturesOrErr.takeError()) {
370 Err = std::move(E);
371 return;
372 } else {
373 Features.reset(p: new SubtargetFeatures(*FeaturesOrErr));
374 }
375 }
376
377 Relocation::Arch = TheTriple.getArch();
378 auto BCOrErr = BinaryContext::createBinaryContext(
379 TheTriple, SSP: std::make_shared<orc::SymbolStringPool>(), InputFileName: File->getFileName(),
380 Features: Features.get(), IsPIC,
381 DwCtx: DWARFContext::create(Obj: *File, RelocAction: DWARFContext::ProcessDebugRelocations::Ignore,
382 L: nullptr, DWPName: opts::DWPPathName,
383 RecoverableErrorHandler: WithColor::defaultErrorHandler,
384 WarningHandler: WithColor::defaultWarningHandler),
385 Logger: JournalingStreams{.Out: Stdout, .Err: Stderr});
386 if (Error E = BCOrErr.takeError()) {
387 Err = std::move(E);
388 return;
389 }
390 BC = std::move(BCOrErr.get());
391 BC->initializeTarget(TargetBuilder: std::unique_ptr<MCPlusBuilder>(
392 createMCPlusBuilder(Arch: BC->TheTriple->getArch(), Analysis: BC->MIA.get(),
393 Info: BC->MII.get(), RegInfo: BC->MRI.get(), STI: BC->STI.get())));
394
395 BAT = std::make_unique<BoltAddressTranslation>();
396
397 if (opts::UpdateDebugSections)
398 DebugInfoRewriter = std::make_unique<DWARFRewriter>(args&: *BC);
399
400 if (opts::Instrument)
401 BC->setRuntimeLibrary(std::make_unique<InstrumentationRuntimeLibrary>());
402 else if (opts::Hugify)
403 BC->setRuntimeLibrary(std::make_unique<HugifyRuntimeLibrary>());
404}
405
406RewriteInstance::~RewriteInstance() {}
407
408Error RewriteInstance::setProfile(StringRef Filename) {
409 if (!sys::fs::exists(Path: Filename))
410 return errorCodeToError(EC: make_error_code(E: errc::no_such_file_or_directory));
411
412 if (ProfileReader) {
413 // Already exists
414 return make_error<StringError>(Args: Twine("multiple profiles specified: ") +
415 ProfileReader->getFilename() + " and " +
416 Filename,
417 Args: inconvertibleErrorCode());
418 }
419
420 // Spawn a profile reader based on file contents.
421 if (DataAggregator::checkPerfDataMagic(FileName: Filename))
422 ProfileReader = std::make_unique<DataAggregator>(args&: Filename);
423 else if (YAMLProfileReader::isYAML(Filename))
424 ProfileReader = std::make_unique<YAMLProfileReader>(args&: Filename);
425 else
426 ProfileReader = std::make_unique<DataReader>(args&: Filename);
427
428 return Error::success();
429}
430
431/// Return true if the function \p BF should be disassembled.
432static bool shouldDisassemble(const BinaryFunction &BF) {
433 if (BF.isPseudo())
434 return false;
435
436 if (opts::processAllFunctions())
437 return true;
438
439 return !BF.isIgnored();
440}
441
442// Return if a section stored in the image falls into a segment address space.
443// If not, Set \p Overlap to true if there's a partial overlap.
444template <class ELFT>
445static bool checkOffsets(const typename ELFT::Phdr &Phdr,
446 const typename ELFT::Shdr &Sec, bool &Overlap) {
447 // SHT_NOBITS sections don't need to have an offset inside the segment.
448 if (Sec.sh_type == ELF::SHT_NOBITS)
449 return true;
450
451 // Only non-empty sections can be at the end of a segment.
452 uint64_t SectionSize = Sec.sh_size ? Sec.sh_size : 1ull;
453 AddressRange SectionAddressRange((uint64_t)Sec.sh_offset,
454 Sec.sh_offset + SectionSize);
455 AddressRange SegmentAddressRange(Phdr.p_offset,
456 Phdr.p_offset + Phdr.p_filesz);
457 if (SegmentAddressRange.contains(R: SectionAddressRange))
458 return true;
459
460 Overlap = SegmentAddressRange.intersects(R: SectionAddressRange);
461 return false;
462}
463
464// Check that an allocatable section belongs to a virtual address
465// space of a segment.
466template <class ELFT>
467static bool checkVMA(const typename ELFT::Phdr &Phdr,
468 const typename ELFT::Shdr &Sec, bool &Overlap) {
469 // Only non-empty sections can be at the end of a segment.
470 uint64_t SectionSize = Sec.sh_size ? Sec.sh_size : 1ull;
471 AddressRange SectionAddressRange((uint64_t)Sec.sh_addr,
472 Sec.sh_addr + SectionSize);
473 AddressRange SegmentAddressRange(Phdr.p_vaddr, Phdr.p_vaddr + Phdr.p_memsz);
474
475 if (SegmentAddressRange.contains(R: SectionAddressRange))
476 return true;
477 Overlap = SegmentAddressRange.intersects(R: SectionAddressRange);
478 return false;
479}
480
481void RewriteInstance::markGnuRelroSections() {
482 using ELFT = ELF64LE;
483 using ELFShdrTy = typename ELFObjectFile<ELFT>::Elf_Shdr;
484 auto ELF64LEFile = cast<ELF64LEObjectFile>(Val: InputFile);
485 const ELFFile<ELFT> &Obj = ELF64LEFile->getELFFile();
486
487 auto handleSection = [&](const ELFT::Phdr &Phdr, SectionRef SecRef) {
488 BinarySection *BinarySection = BC->getSectionForSectionRef(Section: SecRef);
489 // If the section is non-allocatable, ignore it for GNU_RELRO purposes:
490 // it can't be made read-only after runtime relocations processing.
491 if (!BinarySection || !BinarySection->isAllocatable())
492 return;
493 const ELFShdrTy *Sec = cantFail(ValOrErr: Obj.getSection(Index: SecRef.getIndex()));
494 bool ImageOverlap{false}, VMAOverlap{false};
495 bool ImageContains = checkOffsets<ELFT>(Phdr, Sec: *Sec, Overlap&: ImageOverlap);
496 bool VMAContains = checkVMA<ELFT>(Phdr, Sec: *Sec, Overlap&: VMAOverlap);
497 if (ImageOverlap) {
498 if (opts::Verbosity >= 1)
499 BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial file offset "
500 << "overlap with section " << BinarySection->getName()
501 << '\n';
502 return;
503 }
504 if (VMAOverlap) {
505 if (opts::Verbosity >= 1)
506 BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial VMA overlap "
507 << "with section " << BinarySection->getName() << '\n';
508 return;
509 }
510 if (!ImageContains || !VMAContains)
511 return;
512 BinarySection->setRelro();
513 if (opts::Verbosity >= 1)
514 BC->outs() << "BOLT-INFO: marking " << BinarySection->getName()
515 << " as GNU_RELRO\n";
516 };
517
518 for (const ELFT::Phdr &Phdr : cantFail(ValOrErr: Obj.program_headers()))
519 if (Phdr.p_type == ELF::PT_GNU_RELRO)
520 for (SectionRef SecRef : InputFile->sections())
521 handleSection(Phdr, SecRef);
522}
523
524Error RewriteInstance::discoverStorage() {
525 NamedRegionTimer T("discoverStorage", "discover storage", TimerGroupName,
526 TimerGroupDesc, opts::TimeRewrite);
527
528 auto ELF64LEFile = cast<ELF64LEObjectFile>(Val: InputFile);
529 const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();
530
531 BC->StartFunctionAddress = Obj.getHeader().e_entry;
532
533 NextAvailableAddress = 0;
534 uint64_t NextAvailableOffset = 0;
535 Expected<ELF64LE::PhdrRange> PHsOrErr = Obj.program_headers();
536 if (Error E = PHsOrErr.takeError())
537 return E;
538
539 ELF64LE::PhdrRange PHs = PHsOrErr.get();
540 for (const ELF64LE::Phdr &Phdr : PHs) {
541 switch (Phdr.p_type) {
542 case ELF::PT_LOAD:
543 BC->FirstAllocAddress = std::min(a: BC->FirstAllocAddress,
544 b: static_cast<uint64_t>(Phdr.p_vaddr));
545 NextAvailableAddress = std::max(a: NextAvailableAddress,
546 b: Phdr.p_vaddr + Phdr.p_memsz);
547 NextAvailableOffset = std::max(a: NextAvailableOffset,
548 b: Phdr.p_offset + Phdr.p_filesz);
549
550 BC->SegmentMapInfo[Phdr.p_vaddr] =
551 SegmentInfo{.Address: Phdr.p_vaddr,
552 .Size: Phdr.p_memsz,
553 .FileOffset: Phdr.p_offset,
554 .FileSize: Phdr.p_filesz,
555 .Alignment: Phdr.p_align,
556 .IsExecutable: (Phdr.p_flags & ELF::PF_X) != 0,
557 .IsWritable: (Phdr.p_flags & ELF::PF_W) != 0};
558 if (BC->TheTriple->getArch() == llvm::Triple::x86_64 &&
559 Phdr.p_vaddr >= BinaryContext::KernelStartX86_64)
560 BC->IsLinuxKernel = true;
561 break;
562 case ELF::PT_INTERP:
563 BC->HasInterpHeader = true;
564 break;
565 }
566 }
567
568 if (BC->IsLinuxKernel)
569 BC->outs() << "BOLT-INFO: Linux kernel binary detected\n";
570
571 for (const SectionRef &Section : InputFile->sections()) {
572 Expected<StringRef> SectionNameOrErr = Section.getName();
573 if (Error E = SectionNameOrErr.takeError())
574 return E;
575 StringRef SectionName = SectionNameOrErr.get();
576 if (SectionName == BC->getMainCodeSectionName()) {
577 BC->OldTextSectionAddress = Section.getAddress();
578 BC->OldTextSectionSize = Section.getSize();
579
580 Expected<StringRef> SectionContentsOrErr = Section.getContents();
581 if (Error E = SectionContentsOrErr.takeError())
582 return E;
583 StringRef SectionContents = SectionContentsOrErr.get();
584 BC->OldTextSectionOffset =
585 SectionContents.data() - InputFile->getData().data();
586 }
587
588 if (!opts::HeatmapMode &&
589 !(opts::AggregateOnly && BAT->enabledFor(InputFile)) &&
590 (SectionName.starts_with(Prefix: getOrgSecPrefix()) ||
591 SectionName == getBOLTTextSectionName()))
592 return createStringError(
593 EC: errc::function_not_supported,
594 S: "BOLT-ERROR: input file was processed by BOLT. Cannot re-optimize");
595 }
596
597 if (!NextAvailableAddress || !NextAvailableOffset)
598 return createStringError(EC: errc::executable_format_error,
599 S: "no PT_LOAD pheader seen");
600
601 BC->outs() << "BOLT-INFO: first alloc address is 0x"
602 << Twine::utohexstr(Val: BC->FirstAllocAddress) << '\n';
603
604 FirstNonAllocatableOffset = NextAvailableOffset;
605
606 if (opts::CustomAllocationVMA) {
607 // If user specified a custom address where we should start writing new
608 // data, honor that.
609 NextAvailableAddress = opts::CustomAllocationVMA;
610 // Sanity check the user-supplied address and emit warnings if something
611 // seems off.
612 for (const ELF64LE::Phdr &Phdr : PHs) {
613 switch (Phdr.p_type) {
614 case ELF::PT_LOAD:
615 if (NextAvailableAddress >= Phdr.p_vaddr &&
616 NextAvailableAddress < Phdr.p_vaddr + Phdr.p_memsz) {
617 BC->errs() << "BOLT-WARNING: user-supplied allocation vma 0x"
618 << Twine::utohexstr(Val: NextAvailableAddress)
619 << " conflicts with ELF segment at 0x"
620 << Twine::utohexstr(Val: Phdr.p_vaddr) << "\n";
621 }
622 }
623 }
624 }
625 NextAvailableAddress = alignTo(Value: NextAvailableAddress, Align: BC->PageAlign);
626 NextAvailableOffset = alignTo(Value: NextAvailableOffset, Align: BC->PageAlign);
627
628 // Hugify: Additional huge page from left side due to
629 // weird ASLR mapping addresses (4KB aligned)
630 if (opts::Hugify && !BC->HasFixedLoadAddress) {
631 NextAvailableAddress += BC->PageAlign;
632 }
633
634 NewTextSegmentAddress = NextAvailableAddress;
635 NewTextSegmentOffset = NextAvailableOffset;
636
637 if (!opts::UseGnuStack && !BC->IsLinuxKernel) {
638 // This is where the black magic happens. Creating PHDR table in a segment
639 // other than that containing ELF header is tricky. Some loaders and/or
640 // parts of loaders will apply e_phoff from ELF header assuming both are in
641 // the same segment, while others will do the proper calculation.
642 // We create the new PHDR table in such a way that both of the methods
643 // of loading and locating the table work. There's a slight file size
644 // overhead because of that.
645 //
646 // NB: bfd's strip command cannot do the above and will corrupt the
647 // binary during the process of stripping non-allocatable sections.
648 if (NextAvailableOffset <= NextAvailableAddress - BC->FirstAllocAddress)
649 NextAvailableOffset = NextAvailableAddress - BC->FirstAllocAddress;
650 else
651 NextAvailableAddress = NextAvailableOffset + BC->FirstAllocAddress;
652
653 assert(NextAvailableOffset ==
654 NextAvailableAddress - BC->FirstAllocAddress &&
655 "PHDR table address calculation error");
656
657 BC->outs() << "BOLT-INFO: creating new program header table at address 0x"
658 << Twine::utohexstr(Val: NextAvailableAddress) << ", offset 0x"
659 << Twine::utohexstr(Val: NextAvailableOffset) << '\n';
660
661 PHDRTableAddress = NextAvailableAddress;
662 PHDRTableOffset = NextAvailableOffset;
663 NewTextSegmentAddress = NextAvailableAddress;
664 NewTextSegmentOffset = NextAvailableOffset;
665
666 // Reserve space for 3 extra pheaders.
667 unsigned Phnum = Obj.getHeader().e_phnum;
668 Phnum += 3;
669
670 // Reserve two more pheaders to avoid having writeable and executable
671 // segment in instrumented binary.
672 if (opts::Instrument)
673 Phnum += 2;
674
675 NextAvailableAddress += Phnum * sizeof(ELF64LEPhdrTy);
676 NextAvailableOffset += Phnum * sizeof(ELF64LEPhdrTy);
677
678 // Align at cache line.
679 NextAvailableAddress = alignTo(Value: NextAvailableAddress, Align: 64);
680 NextAvailableOffset = alignTo(Value: NextAvailableOffset, Align: 64);
681 }
682
683 BC->LayoutStartAddress = NextAvailableAddress;
684
685 // Tools such as objcopy can strip section contents but leave header
686 // entries. Check that at least .text is mapped in the file.
687 if (!getFileOffsetForAddress(Address: BC->OldTextSectionAddress))
688 return createStringError(EC: errc::executable_format_error,
689 S: "BOLT-ERROR: input binary is not a valid ELF "
690 "executable as its text section is not "
691 "mapped to a valid segment");
692 return Error::success();
693}
694
695Error RewriteInstance::run() {
696 assert(BC && "failed to create a binary context");
697
698 BC->outs() << "BOLT-INFO: Target architecture: "
699 << Triple::getArchTypeName(
700 Kind: (llvm::Triple::ArchType)InputFile->getArch())
701 << "\n";
702 BC->outs() << "BOLT-INFO: BOLT version: " << BoltRevision << "\n";
703
704 if (Error E = discoverStorage())
705 return E;
706 if (Error E = readSpecialSections())
707 return E;
708 adjustCommandLineOptions();
709 discoverFileObjects();
710
711 if (opts::Instrument && !BC->IsStaticExecutable)
712 if (Error E = discoverRtFiniAddress())
713 return E;
714
715 preprocessProfileData();
716
717 // Skip disassembling if we have a translation table and we are running an
718 // aggregation job.
719 if (opts::AggregateOnly && BAT->enabledFor(InputFile)) {
720 // YAML profile in BAT mode requires CFG for .bolt.org.text functions
721 if (!opts::SaveProfile.empty() ||
722 opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML) {
723 selectFunctionsToProcess();
724 disassembleFunctions();
725 processMetadataPreCFG();
726 buildFunctionsCFG();
727 }
728 processProfileData();
729 return Error::success();
730 }
731
732 selectFunctionsToProcess();
733
734 readDebugInfo();
735
736 disassembleFunctions();
737
738 processMetadataPreCFG();
739
740 buildFunctionsCFG();
741
742 processProfileData();
743
744 // Save input binary metadata if BAT section needs to be emitted
745 if (opts::EnableBAT)
746 BAT->saveMetadata(BC&: *BC);
747
748 postProcessFunctions();
749
750 processMetadataPostCFG();
751
752 if (opts::DiffOnly)
753 return Error::success();
754
755 if (opts::BinaryAnalysisMode) {
756 runBinaryAnalyses();
757 return Error::success();
758 }
759
760 preregisterSections();
761
762 runOptimizationPasses();
763
764 finalizeMetadataPreEmit();
765
766 emitAndLink();
767
768 updateMetadata();
769
770 if (opts::Instrument && !BC->IsStaticExecutable)
771 updateRtFiniReloc();
772
773 if (opts::OutputFilename == "/dev/null") {
774 BC->outs() << "BOLT-INFO: skipping writing final binary to disk\n";
775 return Error::success();
776 } else if (BC->IsLinuxKernel) {
777 BC->errs() << "BOLT-WARNING: Linux kernel support is experimental\n";
778 }
779
780 // Rewrite allocatable contents and copy non-allocatable parts with mods.
781 rewriteFile();
782 return Error::success();
783}
784
785void RewriteInstance::discoverFileObjects() {
786 NamedRegionTimer T("discoverFileObjects", "discover file objects",
787 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
788
789 // For local symbols we want to keep track of associated FILE symbol name for
790 // disambiguation by combined name.
791 for (const ELFSymbolRef &Symbol : InputFile->symbols()) {
792 Expected<StringRef> NameOrError = Symbol.getName();
793 if (NameOrError && NameOrError->starts_with(Prefix: "__asan_init")) {
794 BC->errs()
795 << "BOLT-ERROR: input file was compiled or linked with sanitizer "
796 "support. Cannot optimize.\n";
797 exit(status: 1);
798 }
799 if (NameOrError && NameOrError->starts_with(Prefix: "__llvm_coverage_mapping")) {
800 BC->errs()
801 << "BOLT-ERROR: input file was compiled or linked with coverage "
802 "support. Cannot optimize.\n";
803 exit(status: 1);
804 }
805
806 if (cantFail(ValOrErr: Symbol.getFlags()) & SymbolRef::SF_Undefined)
807 continue;
808
809 if (cantFail(ValOrErr: Symbol.getType()) == SymbolRef::ST_File)
810 FileSymbols.emplace_back(args: Symbol);
811 }
812
813 // Sort symbols in the file by value. Ignore symbols from non-allocatable
814 // sections. We memoize getAddress(), as it has rather high overhead.
815 struct SymbolInfo {
816 uint64_t Address;
817 SymbolRef Symbol;
818 };
819 std::vector<SymbolInfo> SortedSymbols;
820 auto isSymbolInMemory = [this](const SymbolRef &Sym) {
821 if (cantFail(ValOrErr: Sym.getType()) == SymbolRef::ST_File)
822 return false;
823 if (cantFail(ValOrErr: Sym.getFlags()) & SymbolRef::SF_Absolute)
824 return true;
825 if (cantFail(ValOrErr: Sym.getFlags()) & SymbolRef::SF_Undefined)
826 return false;
827 BinarySection Section(*BC, *cantFail(ValOrErr: Sym.getSection()));
828 return Section.isAllocatable();
829 };
830 auto checkSymbolInSection = [this](const SymbolInfo &S) {
831 // Sometimes, we encounter symbols with addresses outside their section. If
832 // such symbols happen to fall into another section, they can interfere with
833 // disassembly. Notably, this occurs with AArch64 marker symbols ($d and $t)
834 // that belong to .eh_frame, but end up pointing into .text.
835 // As a workaround, we ignore all symbols that lie outside their sections.
836 auto Section = cantFail(ValOrErr: S.Symbol.getSection());
837
838 // Accept all absolute symbols.
839 if (Section == InputFile->section_end())
840 return true;
841
842 uint64_t SecStart = Section->getAddress();
843 uint64_t SecEnd = SecStart + Section->getSize();
844 uint64_t SymEnd = S.Address + ELFSymbolRef(S.Symbol).getSize();
845 if (S.Address >= SecStart && SymEnd <= SecEnd)
846 return true;
847
848 auto SymType = cantFail(ValOrErr: S.Symbol.getType());
849 // Skip warnings for common benign cases.
850 if (opts::Verbosity < 1 && SymType == SymbolRef::ST_Other)
851 return false; // E.g. ELF::STT_TLS.
852
853 auto SymName = S.Symbol.getName();
854 auto SecName = cantFail(ValOrErr: S.Symbol.getSection())->getName();
855 BC->errs() << "BOLT-WARNING: ignoring symbol "
856 << (SymName ? *SymName : "[unnamed]") << " at 0x"
857 << Twine::utohexstr(Val: S.Address) << ", which lies outside "
858 << (SecName ? *SecName : "[unnamed]") << "\n";
859
860 return false;
861 };
862 for (const SymbolRef &Symbol : InputFile->symbols())
863 if (isSymbolInMemory(Symbol)) {
864 SymbolInfo SymInfo{.Address: cantFail(ValOrErr: Symbol.getAddress()), .Symbol: Symbol};
865 if (checkSymbolInSection(SymInfo))
866 SortedSymbols.push_back(x: SymInfo);
867 }
868
869 auto CompareSymbols = [this](const SymbolInfo &A, const SymbolInfo &B) {
870 if (A.Address != B.Address)
871 return A.Address < B.Address;
872
873 const bool AMarker = BC->isMarker(Symbol: A.Symbol);
874 const bool BMarker = BC->isMarker(Symbol: B.Symbol);
875 if (AMarker || BMarker) {
876 return AMarker && !BMarker;
877 }
878
879 const auto AType = cantFail(ValOrErr: A.Symbol.getType());
880 const auto BType = cantFail(ValOrErr: B.Symbol.getType());
881 if (AType == SymbolRef::ST_Function && BType != SymbolRef::ST_Function)
882 return true;
883 if (BType == SymbolRef::ST_Debug && AType != SymbolRef::ST_Debug)
884 return true;
885
886 return false;
887 };
888 llvm::stable_sort(Range&: SortedSymbols, C: CompareSymbols);
889
890 auto LastSymbol = SortedSymbols.end();
891 if (!SortedSymbols.empty())
892 --LastSymbol;
893
894 // For aarch64, the ABI defines mapping symbols so we identify data in the
895 // code section (see IHI0056B). $d identifies data contents.
896 // Compilers usually merge multiple data objects in a single $d-$x interval,
897 // but we need every data object to be marked with $d. Because of that we
898 // create a vector of MarkerSyms with all locations of data objects.
899
900 struct MarkerSym {
901 uint64_t Address;
902 MarkerSymType Type;
903 };
904
905 std::vector<MarkerSym> SortedMarkerSymbols;
906 auto addExtraDataMarkerPerSymbol = [&]() {
907 bool IsData = false;
908 uint64_t LastAddr = 0;
909 for (const auto &SymInfo : SortedSymbols) {
910 if (LastAddr == SymInfo.Address) // don't repeat markers
911 continue;
912
913 MarkerSymType MarkerType = BC->getMarkerType(Symbol: SymInfo.Symbol);
914 if (MarkerType != MarkerSymType::NONE) {
915 SortedMarkerSymbols.push_back(x: MarkerSym{.Address: SymInfo.Address, .Type: MarkerType});
916 LastAddr = SymInfo.Address;
917 IsData = MarkerType == MarkerSymType::DATA;
918 continue;
919 }
920
921 if (IsData) {
922 SortedMarkerSymbols.push_back(x: {.Address: SymInfo.Address, .Type: MarkerSymType::DATA});
923 LastAddr = SymInfo.Address;
924 }
925 }
926 };
927
928 if (BC->isAArch64() || BC->isRISCV()) {
929 addExtraDataMarkerPerSymbol();
930 LastSymbol = std::stable_partition(
931 first: SortedSymbols.begin(), last: SortedSymbols.end(),
932 pred: [this](const SymbolInfo &S) { return !BC->isMarker(Symbol: S.Symbol); });
933 if (!SortedSymbols.empty())
934 --LastSymbol;
935 }
936
937 BinaryFunction *PreviousFunction = nullptr;
938 unsigned AnonymousId = 0;
939
940 const auto SortedSymbolsEnd =
941 LastSymbol == SortedSymbols.end() ? LastSymbol : std::next(x: LastSymbol);
942 for (auto Iter = SortedSymbols.begin(); Iter != SortedSymbolsEnd; ++Iter) {
943 const SymbolRef &Symbol = Iter->Symbol;
944 const uint64_t SymbolAddress = Iter->Address;
945 const auto SymbolFlags = cantFail(ValOrErr: Symbol.getFlags());
946 const SymbolRef::Type SymbolType = cantFail(ValOrErr: Symbol.getType());
947
948 if (SymbolType == SymbolRef::ST_File)
949 continue;
950
951 StringRef SymName = cantFail(ValOrErr: Symbol.getName(), Msg: "cannot get symbol name");
952 if (SymbolAddress == 0) {
953 if (opts::Verbosity >= 1 && SymbolType == SymbolRef::ST_Function)
954 BC->errs() << "BOLT-WARNING: function with 0 address seen\n";
955 continue;
956 }
957
958 // Ignore input hot markers unless in heatmap mode
959 if ((SymName == "__hot_start" || SymName == "__hot_end") &&
960 !opts::HeatmapMode)
961 continue;
962
963 FileSymRefs.emplace(args: SymbolAddress, args: Symbol);
964
965 // Skip section symbols that will be registered by disassemblePLT().
966 if (SymbolType == SymbolRef::ST_Debug) {
967 ErrorOr<BinarySection &> BSection =
968 BC->getSectionForAddress(Address: SymbolAddress);
969 if (BSection && getPLTSectionInfo(SectionName: BSection->getName()))
970 continue;
971 }
972
973 /// It is possible we are seeing a globalized local. LLVM might treat it as
974 /// a local if it has a "private global" prefix, e.g. ".L". Thus we have to
975 /// change the prefix to enforce global scope of the symbol.
976 std::string Name =
977 SymName.starts_with(Prefix: BC->AsmInfo->getPrivateGlobalPrefix())
978 ? "PG" + std::string(SymName)
979 : std::string(SymName);
980
981 // Disambiguate all local symbols before adding to symbol table.
982 // Since we don't know if we will see a global with the same name,
983 // always modify the local name.
984 //
985 // NOTE: the naming convention for local symbols should match
986 // the one we use for profile data.
987 std::string UniqueName;
988 std::string AlternativeName;
989 if (Name.empty()) {
990 UniqueName = "ANONYMOUS." + std::to_string(val: AnonymousId++);
991 } else if (SymbolFlags & SymbolRef::SF_Global) {
992 if (const BinaryData *BD = BC->getBinaryDataByName(Name)) {
993 if (BD->getSize() == ELFSymbolRef(Symbol).getSize() &&
994 BD->getAddress() == SymbolAddress) {
995 if (opts::Verbosity > 1)
996 BC->errs() << "BOLT-WARNING: ignoring duplicate global symbol "
997 << Name << "\n";
998 // Ignore duplicate entry - possibly a bug in the linker
999 continue;
1000 }
1001 BC->errs() << "BOLT-ERROR: bad input binary, global symbol \"" << Name
1002 << "\" is not unique\n";
1003 exit(status: 1);
1004 }
1005 UniqueName = Name;
1006 } else {
1007 // If we have a local file name, we should create 2 variants for the
1008 // function name. The reason is that perf profile might have been
1009 // collected on a binary that did not have the local file name (e.g. as
1010 // a side effect of stripping debug info from the binary):
1011 //
1012 // primary: <function>/<id>
1013 // alternative: <function>/<file>/<id2>
1014 //
1015 // The <id> field is used for disambiguation of local symbols since there
1016 // could be identical function names coming from identical file names
1017 // (e.g. from different directories).
1018 auto SFI = llvm::upper_bound(Range&: FileSymbols, Value: ELFSymbolRef(Symbol));
1019 if (SymbolType == SymbolRef::ST_Function && SFI != FileSymbols.begin()) {
1020 StringRef FileSymbolName = cantFail(ValOrErr: SFI[-1].getName());
1021 if (!FileSymbolName.empty())
1022 AlternativeName = NR.uniquify(Name: Name + "/" + FileSymbolName.str());
1023 }
1024
1025 UniqueName = NR.uniquify(Name);
1026 }
1027
1028 uint64_t SymbolSize = ELFSymbolRef(Symbol).getSize();
1029 uint64_t SymbolAlignment = Symbol.getAlignment();
1030
1031 auto registerName = [&](uint64_t FinalSize) {
1032 // Register names even if it's not a function, e.g. for an entry point.
1033 BC->registerNameAtAddress(Name: UniqueName, Address: SymbolAddress, Size: FinalSize,
1034 Alignment: SymbolAlignment, Flags: SymbolFlags);
1035 if (!AlternativeName.empty())
1036 BC->registerNameAtAddress(Name: AlternativeName, Address: SymbolAddress, Size: FinalSize,
1037 Alignment: SymbolAlignment, Flags: SymbolFlags);
1038 };
1039
1040 section_iterator Section =
1041 cantFail(ValOrErr: Symbol.getSection(), Msg: "cannot get symbol section");
1042 if (Section == InputFile->section_end()) {
1043 // Could be an absolute symbol. Used on RISC-V for __global_pointer$ so we
1044 // need to record it to handle relocations against it. For other instances
1045 // of absolute symbols, we record for pretty printing.
1046 LLVM_DEBUG(if (opts::Verbosity > 1) {
1047 dbgs() << "BOLT-INFO: absolute sym " << UniqueName << "\n";
1048 });
1049 registerName(SymbolSize);
1050 continue;
1051 }
1052
1053 if (SymName == getBOLTReservedStart() || SymName == getBOLTReservedEnd()) {
1054 registerName(SymbolSize);
1055 continue;
1056 }
1057
1058 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: considering symbol " << UniqueName
1059 << " for function\n");
1060
1061 if (SymbolAddress == Section->getAddress() + Section->getSize()) {
1062 assert(SymbolSize == 0 &&
1063 "unexpect non-zero sized symbol at end of section");
1064 LLVM_DEBUG(
1065 dbgs()
1066 << "BOLT-DEBUG: rejecting as symbol points to end of its section\n");
1067 registerName(SymbolSize);
1068 continue;
1069 }
1070
1071 if (!Section->isText() || Section->isVirtual()) {
1072 assert(SymbolType != SymbolRef::ST_Function &&
1073 "unexpected function inside non-code section");
1074 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: rejecting as symbol is not in code or "
1075 "is in nobits section\n");
1076 registerName(SymbolSize);
1077 continue;
1078 }
1079
1080 // Assembly functions could be ST_NONE with 0 size. Check that the
1081 // corresponding section is a code section and they are not inside any
1082 // other known function to consider them.
1083 //
1084 // Sometimes assembly functions are not marked as functions and neither are
1085 // their local labels. The only way to tell them apart is to look at
1086 // symbol scope - global vs local.
1087 if (PreviousFunction && SymbolType != SymbolRef::ST_Function) {
1088 if (PreviousFunction->containsAddress(PC: SymbolAddress)) {
1089 if (PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) {
1090 LLVM_DEBUG(dbgs()
1091 << "BOLT-DEBUG: symbol is a function local symbol\n");
1092 } else if (SymbolAddress == PreviousFunction->getAddress() &&
1093 !SymbolSize) {
1094 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring symbol as a marker\n");
1095 } else if (opts::Verbosity > 1) {
1096 BC->errs() << "BOLT-WARNING: symbol " << UniqueName
1097 << " seen in the middle of function " << *PreviousFunction
1098 << ". Could be a new entry.\n";
1099 }
1100 registerName(SymbolSize);
1101 continue;
1102 } else if (PreviousFunction->getSize() == 0 &&
1103 PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) {
1104 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: symbol is a function local symbol\n");
1105 registerName(SymbolSize);
1106 continue;
1107 }
1108 }
1109
1110 if (PreviousFunction && PreviousFunction->containsAddress(PC: SymbolAddress) &&
1111 PreviousFunction->getAddress() != SymbolAddress) {
1112 if (PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) {
1113 if (opts::Verbosity >= 1)
1114 BC->outs()
1115 << "BOLT-INFO: skipping possibly another entry for function "
1116 << *PreviousFunction << " : " << UniqueName << '\n';
1117 registerName(SymbolSize);
1118 } else {
1119 BC->outs() << "BOLT-INFO: using " << UniqueName
1120 << " as another entry to "
1121 << "function " << *PreviousFunction << '\n';
1122
1123 registerName(0);
1124
1125 PreviousFunction->addEntryPointAtOffset(Offset: SymbolAddress -
1126 PreviousFunction->getAddress());
1127
1128 // Remove the symbol from FileSymRefs so that we can skip it from
1129 // in the future.
1130 auto SI = llvm::find_if(
1131 Range: llvm::make_range(p: FileSymRefs.equal_range(x: SymbolAddress)),
1132 P: [&](auto SymIt) { return SymIt.second == Symbol; });
1133 assert(SI != FileSymRefs.end() && "symbol expected to be present");
1134 assert(SI->second == Symbol && "wrong symbol found");
1135 FileSymRefs.erase(position: SI);
1136 }
1137 continue;
1138 }
1139
1140 // Checkout for conflicts with function data from FDEs.
1141 bool IsSimple = true;
1142 auto FDEI = CFIRdWrt->getFDEs().lower_bound(x: SymbolAddress);
1143 if (FDEI != CFIRdWrt->getFDEs().end()) {
1144 const dwarf::FDE &FDE = *FDEI->second;
1145 if (FDEI->first != SymbolAddress) {
1146 // There's no matching starting address in FDE. Make sure the previous
1147 // FDE does not contain this address.
1148 if (FDEI != CFIRdWrt->getFDEs().begin()) {
1149 --FDEI;
1150 const dwarf::FDE &PrevFDE = *FDEI->second;
1151 uint64_t PrevStart = PrevFDE.getInitialLocation();
1152 uint64_t PrevLength = PrevFDE.getAddressRange();
1153 if (SymbolAddress > PrevStart &&
1154 SymbolAddress < PrevStart + PrevLength) {
1155 BC->errs() << "BOLT-ERROR: function " << UniqueName
1156 << " is in conflict with FDE ["
1157 << Twine::utohexstr(Val: PrevStart) << ", "
1158 << Twine::utohexstr(Val: PrevStart + PrevLength)
1159 << "). Skipping.\n";
1160 IsSimple = false;
1161 }
1162 }
1163 } else if (FDE.getAddressRange() != SymbolSize) {
1164 if (SymbolSize) {
1165 // Function addresses match but sizes differ.
1166 BC->errs() << "BOLT-WARNING: sizes differ for function " << UniqueName
1167 << ". FDE : " << FDE.getAddressRange()
1168 << "; symbol table : " << SymbolSize
1169 << ". Using max size.\n";
1170 }
1171 SymbolSize = std::max(a: SymbolSize, b: FDE.getAddressRange());
1172 if (BC->getBinaryDataAtAddress(Address: SymbolAddress)) {
1173 BC->setBinaryDataSize(Address: SymbolAddress, Size: SymbolSize);
1174 } else {
1175 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: No BD @ 0x"
1176 << Twine::utohexstr(SymbolAddress) << "\n");
1177 }
1178 }
1179 }
1180
1181 BinaryFunction *BF = nullptr;
1182 // Since function may not have yet obtained its real size, do a search
1183 // using the list of registered functions instead of calling
1184 // getBinaryFunctionAtAddress().
1185 auto BFI = BC->getBinaryFunctions().find(x: SymbolAddress);
1186 if (BFI != BC->getBinaryFunctions().end()) {
1187 BF = &BFI->second;
1188 // Duplicate the function name. Make sure everything matches before we add
1189 // an alternative name.
1190 if (SymbolSize != BF->getSize()) {
1191 if (opts::Verbosity >= 1) {
1192 if (SymbolSize && BF->getSize())
1193 BC->errs() << "BOLT-WARNING: size mismatch for duplicate entries "
1194 << *BF << " and " << UniqueName << '\n';
1195 BC->outs() << "BOLT-INFO: adjusting size of function " << *BF
1196 << " old " << BF->getSize() << " new " << SymbolSize
1197 << "\n";
1198 }
1199 BF->setSize(std::max(a: SymbolSize, b: BF->getSize()));
1200 BC->setBinaryDataSize(Address: SymbolAddress, Size: BF->getSize());
1201 }
1202 BF->addAlternativeName(NewName: UniqueName);
1203 } else {
1204 ErrorOr<BinarySection &> Section =
1205 BC->getSectionForAddress(Address: SymbolAddress);
1206 // Skip symbols from invalid sections
1207 if (!Section) {
1208 BC->errs() << "BOLT-WARNING: " << UniqueName << " (0x"
1209 << Twine::utohexstr(Val: SymbolAddress)
1210 << ") does not have any section\n";
1211 continue;
1212 }
1213
1214 // Skip symbols from zero-sized sections.
1215 if (!Section->getSize())
1216 continue;
1217
1218 BF = BC->createBinaryFunction(Name: UniqueName, Section&: *Section, Address: SymbolAddress,
1219 Size: SymbolSize);
1220 if (!IsSimple)
1221 BF->setSimple(false);
1222 }
1223
1224 // Check if it's a cold function fragment.
1225 if (FunctionFragmentTemplate.match(String: SymName)) {
1226 static bool PrintedWarning = false;
1227 if (!PrintedWarning) {
1228 PrintedWarning = true;
1229 BC->errs() << "BOLT-WARNING: split function detected on input : "
1230 << SymName;
1231 if (BC->HasRelocations)
1232 BC->errs() << ". The support is limited in relocation mode\n";
1233 else
1234 BC->errs() << '\n';
1235 }
1236 BC->HasSplitFunctions = true;
1237 BF->IsFragment = true;
1238 }
1239
1240 if (!AlternativeName.empty())
1241 BF->addAlternativeName(NewName: AlternativeName);
1242
1243 registerName(SymbolSize);
1244 PreviousFunction = BF;
1245 }
1246
1247 // Read dynamic relocation first as their presence affects the way we process
1248 // static relocations. E.g. we will ignore a static relocation at an address
1249 // that is a subject to dynamic relocation processing.
1250 processDynamicRelocations();
1251
1252 // Process PLT section.
1253 disassemblePLT();
1254
1255 // See if we missed any functions marked by FDE.
1256 for (const auto &FDEI : CFIRdWrt->getFDEs()) {
1257 const uint64_t Address = FDEI.first;
1258 const dwarf::FDE *FDE = FDEI.second;
1259 const BinaryFunction *BF = BC->getBinaryFunctionAtAddress(Address);
1260 if (BF)
1261 continue;
1262
1263 BF = BC->getBinaryFunctionContainingAddress(Address);
1264 if (BF) {
1265 BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Val: Address)
1266 << ", 0x" << Twine::utohexstr(Val: Address + FDE->getAddressRange())
1267 << ") conflicts with function " << *BF << '\n';
1268 continue;
1269 }
1270
1271 if (opts::Verbosity >= 1)
1272 BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Val: Address)
1273 << ", 0x" << Twine::utohexstr(Val: Address + FDE->getAddressRange())
1274 << ") has no corresponding symbol table entry\n";
1275
1276 ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);
1277 assert(Section && "cannot get section for address from FDE");
1278 std::string FunctionName =
1279 "__BOLT_FDE_FUNCat" + Twine::utohexstr(Val: Address).str();
1280 BC->createBinaryFunction(Name: FunctionName, Section&: *Section, Address,
1281 Size: FDE->getAddressRange());
1282 }
1283
1284 BC->setHasSymbolsWithFileName(FileSymbols.size());
1285
1286 // Now that all the functions were created - adjust their boundaries.
1287 adjustFunctionBoundaries();
1288
1289 // Annotate functions with code/data markers in AArch64
1290 for (auto ISym = SortedMarkerSymbols.begin();
1291 ISym != SortedMarkerSymbols.end(); ++ISym) {
1292
1293 auto *BF =
1294 BC->getBinaryFunctionContainingAddress(Address: ISym->Address, CheckPastEnd: true, UseMaxSize: true);
1295
1296 if (!BF) {
1297 // Stray marker
1298 continue;
1299 }
1300 const auto EntryOffset = ISym->Address - BF->getAddress();
1301 if (ISym->Type == MarkerSymType::CODE) {
1302 BF->markCodeAtOffset(Offset: EntryOffset);
1303 continue;
1304 }
1305 if (ISym->Type == MarkerSymType::DATA) {
1306 BF->markDataAtOffset(Offset: EntryOffset);
1307 BC->AddressToConstantIslandMap[ISym->Address] = BF;
1308 continue;
1309 }
1310 llvm_unreachable("Unknown marker");
1311 }
1312
1313 if (BC->isAArch64()) {
1314 // Check for dynamic relocations that might be contained in
1315 // constant islands.
1316 for (const BinarySection &Section : BC->allocatableSections()) {
1317 const uint64_t SectionAddress = Section.getAddress();
1318 for (const Relocation &Rel : Section.dynamicRelocations()) {
1319 const uint64_t RelAddress = SectionAddress + Rel.Offset;
1320 BinaryFunction *BF =
1321 BC->getBinaryFunctionContainingAddress(Address: RelAddress,
1322 /*CheckPastEnd*/ false,
1323 /*UseMaxSize*/ true);
1324 if (BF) {
1325 assert(Rel.isRelative() && "Expected relative relocation for island");
1326 BC->logBOLTErrorsAndQuitOnFatal(
1327 E: BF->markIslandDynamicRelocationAtAddress(Address: RelAddress));
1328 }
1329 }
1330 }
1331
1332 // The linker may omit data markers for absolute long veneers. Introduce
1333 // those markers artificially to assist the disassembler.
1334 for (BinaryFunction &BF :
1335 llvm::make_second_range(c&: BC->getBinaryFunctions())) {
1336 if (BF.getOneName().starts_with(Prefix: "__AArch64AbsLongThunk_") &&
1337 BF.getSize() == 16 && !BF.getSizeOfDataInCodeAt(Offset: 8)) {
1338 BC->errs() << "BOLT-WARNING: missing data marker detected in veneer "
1339 << BF << '\n';
1340 BF.markDataAtOffset(Offset: 8);
1341 BC->AddressToConstantIslandMap[BF.getAddress() + 8] = &BF;
1342 }
1343 }
1344 }
1345
1346 if (!BC->IsLinuxKernel) {
1347 // Read all relocations now that we have binary functions mapped.
1348 processRelocations();
1349 }
1350
1351 registerFragments();
1352 FileSymbols.clear();
1353 FileSymRefs.clear();
1354
1355 discoverBOLTReserved();
1356}
1357
1358void RewriteInstance::discoverBOLTReserved() {
1359 BinaryData *StartBD = BC->getBinaryDataByName(Name: getBOLTReservedStart());
1360 BinaryData *EndBD = BC->getBinaryDataByName(Name: getBOLTReservedEnd());
1361 if (!StartBD != !EndBD) {
1362 BC->errs() << "BOLT-ERROR: one of the symbols is missing from the binary: "
1363 << getBOLTReservedStart() << ", " << getBOLTReservedEnd()
1364 << '\n';
1365 exit(status: 1);
1366 }
1367
1368 if (!StartBD)
1369 return;
1370
1371 if (StartBD->getAddress() >= EndBD->getAddress()) {
1372 BC->errs() << "BOLT-ERROR: invalid reserved space boundaries\n";
1373 exit(status: 1);
1374 }
1375 BC->BOLTReserved = AddressRange(StartBD->getAddress(), EndBD->getAddress());
1376 BC->outs() << "BOLT-INFO: using reserved space for allocating new sections\n";
1377
1378 PHDRTableOffset = 0;
1379 PHDRTableAddress = 0;
1380 NewTextSegmentAddress = 0;
1381 NewTextSegmentOffset = 0;
1382 NextAvailableAddress = BC->BOLTReserved.start();
1383}
1384
1385Error RewriteInstance::discoverRtFiniAddress() {
1386 // Use DT_FINI if it's available.
1387 if (BC->FiniAddress) {
1388 BC->FiniFunctionAddress = BC->FiniAddress;
1389 return Error::success();
1390 }
1391
1392 if (!BC->FiniArrayAddress || !BC->FiniArraySize) {
1393 return createStringError(
1394 EC: std::errc::not_supported,
1395 Fmt: "Instrumentation needs either DT_FINI or DT_FINI_ARRAY");
1396 }
1397
1398 if (*BC->FiniArraySize < BC->AsmInfo->getCodePointerSize()) {
1399 return createStringError(EC: std::errc::not_supported,
1400 Fmt: "Need at least 1 DT_FINI_ARRAY slot");
1401 }
1402
1403 ErrorOr<BinarySection &> FiniArraySection =
1404 BC->getSectionForAddress(Address: *BC->FiniArrayAddress);
1405 if (auto EC = FiniArraySection.getError())
1406 return errorCodeToError(EC);
1407
1408 if (const Relocation *Reloc = FiniArraySection->getDynamicRelocationAt(Offset: 0)) {
1409 BC->FiniFunctionAddress = Reloc->Addend;
1410 return Error::success();
1411 }
1412
1413 if (const Relocation *Reloc = FiniArraySection->getRelocationAt(Offset: 0)) {
1414 BC->FiniFunctionAddress = Reloc->Value;
1415 return Error::success();
1416 }
1417
1418 return createStringError(EC: std::errc::not_supported,
1419 Fmt: "No relocation for first DT_FINI_ARRAY slot");
1420}
1421
1422void RewriteInstance::updateRtFiniReloc() {
1423 // Updating DT_FINI is handled by patchELFDynamic.
1424 if (BC->FiniAddress)
1425 return;
1426
1427 const RuntimeLibrary *RT = BC->getRuntimeLibrary();
1428 if (!RT || !RT->getRuntimeFiniAddress())
1429 return;
1430
1431 assert(BC->FiniArrayAddress && BC->FiniArraySize &&
1432 "inconsistent .fini_array state");
1433
1434 ErrorOr<BinarySection &> FiniArraySection =
1435 BC->getSectionForAddress(Address: *BC->FiniArrayAddress);
1436 assert(FiniArraySection && ".fini_array removed");
1437
1438 if (std::optional<Relocation> Reloc =
1439 FiniArraySection->takeDynamicRelocationAt(Offset: 0)) {
1440 assert(Reloc->Addend == BC->FiniFunctionAddress &&
1441 "inconsistent .fini_array dynamic relocation");
1442 Reloc->Addend = RT->getRuntimeFiniAddress();
1443 FiniArraySection->addDynamicRelocation(Reloc: *Reloc);
1444 }
1445
1446 // Update the static relocation by adding a pending relocation which will get
1447 // patched when flushPendingRelocations is called in rewriteFile. Note that
1448 // flushPendingRelocations will calculate the value to patch as
1449 // "Symbol + Addend". Since we don't have a symbol, just set the addend to the
1450 // desired value.
1451 FiniArraySection->addPendingRelocation(Rel: Relocation{
1452 /*Offset*/ 0, /*Symbol*/ nullptr, /*Type*/ Relocation::getAbs64(),
1453 /*Addend*/ RT->getRuntimeFiniAddress(), /*Value*/ 0});
1454}
1455
1456void RewriteInstance::registerFragments() {
1457 if (!BC->HasSplitFunctions ||
1458 opts::HeatmapMode == opts::HeatmapModeKind::HM_Exclusive)
1459 return;
1460
1461 // Process fragments with ambiguous parents separately as they are typically a
1462 // vanishing minority of cases and require expensive symbol table lookups.
1463 std::vector<std::pair<StringRef, BinaryFunction *>> AmbiguousFragments;
1464 for (auto &BFI : BC->getBinaryFunctions()) {
1465 BinaryFunction &Function = BFI.second;
1466 if (!Function.isFragment())
1467 continue;
1468 for (StringRef Name : Function.getNames()) {
1469 StringRef BaseName = NR.restore(Name);
1470 const bool IsGlobal = BaseName == Name;
1471 SmallVector<StringRef> Matches;
1472 if (!FunctionFragmentTemplate.match(String: BaseName, Matches: &Matches))
1473 continue;
1474 StringRef ParentName = Matches[1];
1475 const BinaryData *BD = BC->getBinaryDataByName(Name: ParentName);
1476 const uint64_t NumPossibleLocalParents =
1477 NR.getUniquifiedNameCount(Name: ParentName);
1478 // The most common case: single local parent fragment.
1479 if (!BD && NumPossibleLocalParents == 1) {
1480 BD = BC->getBinaryDataByName(Name: NR.getUniqueName(Name: ParentName, ID: 1));
1481 } else if (BD && (!NumPossibleLocalParents || IsGlobal)) {
1482 // Global parent and either no local candidates (second most common), or
1483 // the fragment is global as well (uncommon).
1484 } else {
1485 // Any other case: need to disambiguate using FILE symbols.
1486 AmbiguousFragments.emplace_back(args&: ParentName, args: &Function);
1487 continue;
1488 }
1489 if (BD) {
1490 BinaryFunction *BF = BC->getFunctionForSymbol(Symbol: BD->getSymbol());
1491 if (BF) {
1492 BC->registerFragment(TargetFunction&: Function, Function&: *BF);
1493 continue;
1494 }
1495 }
1496 BC->errs() << "BOLT-ERROR: parent function not found for " << Function
1497 << '\n';
1498 exit(status: 1);
1499 }
1500 }
1501
1502 if (AmbiguousFragments.empty())
1503 return;
1504
1505 if (!BC->hasSymbolsWithFileName()) {
1506 BC->errs() << "BOLT-ERROR: input file has split functions but does not "
1507 "have FILE symbols. If the binary was stripped, preserve "
1508 "FILE symbols with --keep-file-symbols strip option\n";
1509 exit(status: 1);
1510 }
1511
1512 // The first global symbol is identified by the symbol table sh_info value.
1513 // Used as local symbol search stopping point.
1514 auto *ELF64LEFile = cast<ELF64LEObjectFile>(Val: InputFile);
1515 const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();
1516 auto *SymTab = llvm::find_if(Range: cantFail(ValOrErr: Obj.sections()), P: [](const auto &Sec) {
1517 return Sec.sh_type == ELF::SHT_SYMTAB;
1518 });
1519 assert(SymTab);
1520 // Symtab sh_info contains the value one greater than the symbol table index
1521 // of the last local symbol.
1522 ELFSymbolRef LocalSymEnd = ELF64LEFile->toSymbolRef(SymTable: SymTab, SymbolNum: SymTab->sh_info);
1523
1524 for (auto &Fragment : AmbiguousFragments) {
1525 const StringRef &ParentName = Fragment.first;
1526 BinaryFunction *BF = Fragment.second;
1527 const uint64_t Address = BF->getAddress();
1528
1529 // Get fragment's own symbol
1530 const auto SymIt = llvm::find_if(
1531 Range: llvm::make_range(p: FileSymRefs.equal_range(x: Address)), P: [&](auto SI) {
1532 StringRef Name = cantFail(SI.second.getName());
1533 return Name.contains(Other: ParentName);
1534 });
1535 if (SymIt == FileSymRefs.end()) {
1536 BC->errs()
1537 << "BOLT-ERROR: symbol lookup failed for function at address 0x"
1538 << Twine::utohexstr(Val: Address) << '\n';
1539 exit(status: 1);
1540 }
1541
1542 // Find containing FILE symbol
1543 ELFSymbolRef Symbol = SymIt->second;
1544 auto FSI = llvm::upper_bound(Range&: FileSymbols, Value&: Symbol);
1545 if (FSI == FileSymbols.begin()) {
1546 BC->errs() << "BOLT-ERROR: owning FILE symbol not found for symbol "
1547 << cantFail(ValOrErr: Symbol.getName()) << '\n';
1548 exit(status: 1);
1549 }
1550
1551 ELFSymbolRef StopSymbol = LocalSymEnd;
1552 if (FSI != FileSymbols.end())
1553 StopSymbol = *FSI;
1554
1555 uint64_t ParentAddress{0};
1556
1557 // Check if containing FILE symbol is BOLT emitted synthetic symbol marking
1558 // local fragments of global parents.
1559 if (cantFail(ValOrErr: FSI[-1].getName()) == getBOLTFileSymbolName())
1560 goto registerParent;
1561
1562 // BOLT split fragment symbols are emitted just before the main function
1563 // symbol.
1564 for (ELFSymbolRef NextSymbol = Symbol; NextSymbol < StopSymbol;
1565 NextSymbol.moveNext()) {
1566 StringRef Name = cantFail(ValOrErr: NextSymbol.getName());
1567 if (Name == ParentName) {
1568 ParentAddress = cantFail(ValOrErr: NextSymbol.getValue());
1569 goto registerParent;
1570 }
1571 if (Name.starts_with(Prefix: ParentName))
1572 // With multi-way splitting, there are multiple fragments with different
1573 // suffixes. Parent follows the last fragment.
1574 continue;
1575 break;
1576 }
1577
1578 // Iterate over local file symbols and check symbol names to match parent.
1579 for (ELFSymbolRef Symbol(FSI[-1]); Symbol < StopSymbol; Symbol.moveNext()) {
1580 if (cantFail(ValOrErr: Symbol.getName()) == ParentName) {
1581 ParentAddress = cantFail(ValOrErr: Symbol.getAddress());
1582 break;
1583 }
1584 }
1585
1586registerParent:
1587 // No local parent is found, use global parent function.
1588 if (!ParentAddress)
1589 if (BinaryData *ParentBD = BC->getBinaryDataByName(Name: ParentName))
1590 ParentAddress = ParentBD->getAddress();
1591
1592 if (BinaryFunction *ParentBF =
1593 BC->getBinaryFunctionAtAddress(Address: ParentAddress)) {
1594 BC->registerFragment(TargetFunction&: *BF, Function&: *ParentBF);
1595 continue;
1596 }
1597 BC->errs() << "BOLT-ERROR: parent function not found for " << *BF << '\n';
1598 exit(status: 1);
1599 }
1600}
1601
1602void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
1603 uint64_t EntryAddress,
1604 uint64_t EntrySize) {
1605 if (!TargetAddress)
1606 return;
1607
1608 auto setPLTSymbol = [&](BinaryFunction *BF, StringRef Name) {
1609 const unsigned PtrSize = BC->AsmInfo->getCodePointerSize();
1610 MCSymbol *TargetSymbol = BC->registerNameAtAddress(
1611 Name: Name.str() + "@GOT", Address: TargetAddress, Size: PtrSize, Alignment: PtrSize);
1612 BF->setPLTSymbol(TargetSymbol);
1613 };
1614
1615 BinaryFunction *BF = BC->getBinaryFunctionAtAddress(Address: EntryAddress);
1616 if (BF && BC->isAArch64()) {
1617 // Handle IFUNC trampoline with symbol
1618 setPLTSymbol(BF, BF->getOneName());
1619 return;
1620 }
1621
1622 const Relocation *Rel = BC->getDynamicRelocationAt(Address: TargetAddress);
1623 if (!Rel)
1624 return;
1625
1626 MCSymbol *Symbol = Rel->Symbol;
1627 if (!Symbol) {
1628 if (BC->isRISCV() || !Rel->Addend || !Rel->isIRelative())
1629 return;
1630
1631 // IFUNC trampoline without symbol
1632 BinaryFunction *TargetBF = BC->getBinaryFunctionAtAddress(Address: Rel->Addend);
1633 if (!TargetBF) {
1634 BC->errs()
1635 << "BOLT-WARNING: Expected BF to be presented as IFUNC resolver at "
1636 << Twine::utohexstr(Val: Rel->Addend) << ", skipping\n";
1637 return;
1638 }
1639
1640 Symbol = TargetBF->getSymbol();
1641 }
1642
1643 ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address: EntryAddress);
1644 assert(Section && "cannot get section for address");
1645 if (!BF)
1646 BF = BC->createBinaryFunction(Name: Symbol->getName().str() + "@PLT", Section&: *Section,
1647 Address: EntryAddress, Size: 0, SymbolSize: EntrySize,
1648 Alignment: Section->getAlignment());
1649 else
1650 BF->addAlternativeName(NewName: Symbol->getName().str() + "@PLT");
1651 setPLTSymbol(BF, Symbol->getName());
1652}
1653
1654void RewriteInstance::disassemblePLTInstruction(const BinarySection &Section,
1655 uint64_t InstrOffset,
1656 MCInst &Instruction,
1657 uint64_t &InstrSize) {
1658 const uint64_t SectionAddress = Section.getAddress();
1659 const uint64_t SectionSize = Section.getSize();
1660 StringRef PLTContents = Section.getContents();
1661 ArrayRef<uint8_t> PLTData(
1662 reinterpret_cast<const uint8_t *>(PLTContents.data()), SectionSize);
1663
1664 const uint64_t InstrAddr = SectionAddress + InstrOffset;
1665 if (!BC->DisAsm->getInstruction(Instr&: Instruction, Size&: InstrSize,
1666 Bytes: PLTData.slice(N: InstrOffset), Address: InstrAddr,
1667 CStream&: nulls())) {
1668 BC->errs()
1669 << "BOLT-ERROR: unable to disassemble instruction in PLT section "
1670 << Section.getName() << formatv(Fmt: " at offset {0:x}\n", Vals&: InstrOffset);
1671 exit(status: 1);
1672 }
1673}
1674
1675void RewriteInstance::disassemblePLTSectionAArch64(BinarySection &Section) {
1676 const uint64_t SectionAddress = Section.getAddress();
1677 const uint64_t SectionSize = Section.getSize();
1678
1679 uint64_t InstrOffset = 0;
1680 // Locate new plt entry
1681 while (InstrOffset < SectionSize) {
1682 InstructionListType Instructions;
1683 MCInst Instruction;
1684 uint64_t EntryOffset = InstrOffset;
1685 uint64_t EntrySize = 0;
1686 uint64_t InstrSize;
1687 // Loop through entry instructions
1688 while (InstrOffset < SectionSize) {
1689 disassemblePLTInstruction(Section, InstrOffset, Instruction, InstrSize);
1690 EntrySize += InstrSize;
1691 if (!BC->MIB->isIndirectBranch(Inst: Instruction)) {
1692 Instructions.emplace_back(args&: Instruction);
1693 InstrOffset += InstrSize;
1694 continue;
1695 }
1696
1697 const uint64_t EntryAddress = SectionAddress + EntryOffset;
1698 const uint64_t TargetAddress = BC->MIB->analyzePLTEntry(
1699 Instruction, Begin: Instructions.begin(), End: Instructions.end(), BeginPC: EntryAddress);
1700
1701 createPLTBinaryFunction(TargetAddress, EntryAddress, EntrySize);
1702 break;
1703 }
1704
1705 // Branch instruction
1706 InstrOffset += InstrSize;
1707
1708 // Skip nops if any
1709 while (InstrOffset < SectionSize) {
1710 disassemblePLTInstruction(Section, InstrOffset, Instruction, InstrSize);
1711 if (!BC->MIB->isNoop(Inst: Instruction))
1712 break;
1713
1714 InstrOffset += InstrSize;
1715 }
1716 }
1717}
1718
1719void RewriteInstance::disassemblePLTSectionRISCV(BinarySection &Section) {
1720 const uint64_t SectionAddress = Section.getAddress();
1721 const uint64_t SectionSize = Section.getSize();
1722 StringRef PLTContents = Section.getContents();
1723 ArrayRef<uint8_t> PLTData(
1724 reinterpret_cast<const uint8_t *>(PLTContents.data()), SectionSize);
1725
1726 auto disassembleInstruction = [&](uint64_t InstrOffset, MCInst &Instruction,
1727 uint64_t &InstrSize) {
1728 const uint64_t InstrAddr = SectionAddress + InstrOffset;
1729 if (!BC->DisAsm->getInstruction(Instr&: Instruction, Size&: InstrSize,
1730 Bytes: PLTData.slice(N: InstrOffset), Address: InstrAddr,
1731 CStream&: nulls())) {
1732 BC->errs()
1733 << "BOLT-ERROR: unable to disassemble instruction in PLT section "
1734 << Section.getName() << " at offset 0x"
1735 << Twine::utohexstr(Val: InstrOffset) << '\n';
1736 exit(status: 1);
1737 }
1738 };
1739
1740 // Skip the first special entry since no relocation points to it.
1741 uint64_t InstrOffset = 32;
1742
1743 while (InstrOffset < SectionSize) {
1744 InstructionListType Instructions;
1745 MCInst Instruction;
1746 const uint64_t EntryOffset = InstrOffset;
1747 const uint64_t EntrySize = 16;
1748 uint64_t InstrSize;
1749
1750 while (InstrOffset < EntryOffset + EntrySize) {
1751 disassembleInstruction(InstrOffset, Instruction, InstrSize);
1752 Instructions.emplace_back(args&: Instruction);
1753 InstrOffset += InstrSize;
1754 }
1755
1756 const uint64_t EntryAddress = SectionAddress + EntryOffset;
1757 const uint64_t TargetAddress = BC->MIB->analyzePLTEntry(
1758 Instruction, Begin: Instructions.begin(), End: Instructions.end(), BeginPC: EntryAddress);
1759
1760 createPLTBinaryFunction(TargetAddress, EntryAddress, EntrySize);
1761 }
1762}
1763
1764void RewriteInstance::disassemblePLTSectionX86(BinarySection &Section,
1765 uint64_t EntrySize) {
1766 const uint64_t SectionAddress = Section.getAddress();
1767 const uint64_t SectionSize = Section.getSize();
1768
1769 for (uint64_t EntryOffset = 0; EntryOffset + EntrySize <= SectionSize;
1770 EntryOffset += EntrySize) {
1771 MCInst Instruction;
1772 uint64_t InstrSize, InstrOffset = EntryOffset;
1773 while (InstrOffset < EntryOffset + EntrySize) {
1774 disassemblePLTInstruction(Section, InstrOffset, Instruction, InstrSize);
1775 // Check if the entry size needs adjustment.
1776 if (EntryOffset == 0 && BC->MIB->isTerminateBranch(Inst: Instruction) &&
1777 EntrySize == 8)
1778 EntrySize = 16;
1779
1780 if (BC->MIB->isIndirectBranch(Inst: Instruction))
1781 break;
1782
1783 InstrOffset += InstrSize;
1784 }
1785
1786 if (InstrOffset + InstrSize > EntryOffset + EntrySize)
1787 continue;
1788
1789 uint64_t TargetAddress;
1790 if (!BC->MIB->evaluateMemOperandTarget(Inst: Instruction, Target&: TargetAddress,
1791 Address: SectionAddress + InstrOffset,
1792 Size: InstrSize)) {
1793 BC->errs() << "BOLT-ERROR: error evaluating PLT instruction at offset 0x"
1794 << Twine::utohexstr(Val: SectionAddress + InstrOffset) << '\n';
1795 exit(status: 1);
1796 }
1797
1798 createPLTBinaryFunction(TargetAddress, EntryAddress: SectionAddress + EntryOffset,
1799 EntrySize);
1800 }
1801}
1802
1803void RewriteInstance::disassemblePLT() {
1804 auto analyzeOnePLTSection = [&](BinarySection &Section, uint64_t EntrySize) {
1805 if (BC->isAArch64())
1806 return disassemblePLTSectionAArch64(Section);
1807 if (BC->isRISCV())
1808 return disassemblePLTSectionRISCV(Section);
1809 if (BC->isX86())
1810 return disassemblePLTSectionX86(Section, EntrySize);
1811 llvm_unreachable("Unmplemented PLT");
1812 };
1813
1814 for (BinarySection &Section : BC->allocatableSections()) {
1815 const PLTSectionInfo *PLTSI = getPLTSectionInfo(SectionName: Section.getName());
1816 if (!PLTSI)
1817 continue;
1818
1819 analyzeOnePLTSection(Section, PLTSI->EntrySize);
1820
1821 BinaryFunction *PltBF;
1822 auto BFIter = BC->getBinaryFunctions().find(x: Section.getAddress());
1823 if (BFIter != BC->getBinaryFunctions().end()) {
1824 PltBF = &BFIter->second;
1825 } else {
1826 // If we did not register any function at the start of the section,
1827 // then it must be a general PLT entry. Add a function at the location.
1828 PltBF = BC->createBinaryFunction(
1829 Name: "__BOLT_PSEUDO_" + Section.getName().str(), Section,
1830 Address: Section.getAddress(), Size: 0, SymbolSize: PLTSI->EntrySize, Alignment: Section.getAlignment());
1831 }
1832 PltBF->setPseudo(true);
1833 }
1834}
1835
1836void RewriteInstance::adjustFunctionBoundaries() {
1837 for (auto BFI = BC->getBinaryFunctions().begin(),
1838 BFE = BC->getBinaryFunctions().end();
1839 BFI != BFE; ++BFI) {
1840 BinaryFunction &Function = BFI->second;
1841 const BinaryFunction *NextFunction = nullptr;
1842 if (std::next(x: BFI) != BFE)
1843 NextFunction = &std::next(x: BFI)->second;
1844
1845 // Check if there's a symbol or a function with a larger address in the
1846 // same section. If there is - it determines the maximum size for the
1847 // current function. Otherwise, it is the size of a containing section
1848 // the defines it.
1849 //
1850 // NOTE: ignore some symbols that could be tolerated inside the body
1851 // of a function.
1852 auto NextSymRefI = FileSymRefs.upper_bound(x: Function.getAddress());
1853 while (NextSymRefI != FileSymRefs.end()) {
1854 SymbolRef &Symbol = NextSymRefI->second;
1855 const uint64_t SymbolAddress = NextSymRefI->first;
1856 const uint64_t SymbolSize = ELFSymbolRef(Symbol).getSize();
1857
1858 if (NextFunction && SymbolAddress >= NextFunction->getAddress())
1859 break;
1860
1861 if (!Function.isSymbolValidInScope(Symbol, SymbolSize))
1862 break;
1863
1864 // Skip basic block labels. This happens on RISC-V with linker relaxation
1865 // enabled because every branch needs a relocation and corresponding
1866 // symbol. We don't want to add such symbols as entry points.
1867 const auto PrivateLabelPrefix = BC->AsmInfo->getPrivateLabelPrefix();
1868 if (!PrivateLabelPrefix.empty() &&
1869 cantFail(ValOrErr: Symbol.getName()).starts_with(Prefix: PrivateLabelPrefix)) {
1870 ++NextSymRefI;
1871 continue;
1872 }
1873
1874 // This is potentially another entry point into the function.
1875 uint64_t EntryOffset = NextSymRefI->first - Function.getAddress();
1876 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: adding entry point to function "
1877 << Function << " at offset 0x"
1878 << Twine::utohexstr(EntryOffset) << '\n');
1879 Function.addEntryPointAtOffset(Offset: EntryOffset);
1880
1881 ++NextSymRefI;
1882 }
1883
1884 // Function runs at most till the end of the containing section.
1885 uint64_t NextObjectAddress = Function.getOriginSection()->getEndAddress();
1886 // Or till the next object marked by a symbol.
1887 if (NextSymRefI != FileSymRefs.end())
1888 NextObjectAddress = std::min(a: NextSymRefI->first, b: NextObjectAddress);
1889
1890 // Or till the next function not marked by a symbol.
1891 if (NextFunction)
1892 NextObjectAddress =
1893 std::min(a: NextFunction->getAddress(), b: NextObjectAddress);
1894
1895 const uint64_t MaxSize = NextObjectAddress - Function.getAddress();
1896 if (MaxSize < Function.getSize()) {
1897 BC->errs() << "BOLT-ERROR: symbol seen in the middle of the function "
1898 << Function << ". Skipping.\n";
1899 Function.setSimple(false);
1900 Function.setMaxSize(Function.getSize());
1901 continue;
1902 }
1903 Function.setMaxSize(MaxSize);
1904 if (!Function.getSize() && Function.isSimple()) {
1905 // Some assembly functions have their size set to 0, use the max
1906 // size as their real size.
1907 if (opts::Verbosity >= 1)
1908 BC->outs() << "BOLT-INFO: setting size of function " << Function
1909 << " to " << Function.getMaxSize() << " (was 0)\n";
1910 Function.setSize(Function.getMaxSize());
1911 }
1912 }
1913}
1914
1915void RewriteInstance::relocateEHFrameSection() {
1916 assert(EHFrameSection && "Non-empty .eh_frame section expected.");
1917
1918 BinarySection *RelocatedEHFrameSection =
1919 getSection(Name: ".relocated" + getEHFrameSectionName());
1920 assert(RelocatedEHFrameSection &&
1921 "Relocated eh_frame section should be preregistered.");
1922 DWARFDataExtractor DE(EHFrameSection->getContents(),
1923 BC->AsmInfo->isLittleEndian(),
1924 BC->AsmInfo->getCodePointerSize());
1925 auto createReloc = [&](uint64_t Value, uint64_t Offset, uint64_t DwarfType) {
1926 if (DwarfType == dwarf::DW_EH_PE_omit)
1927 return;
1928
1929 // Only fix references that are relative to other locations.
1930 if (!(DwarfType & dwarf::DW_EH_PE_pcrel) &&
1931 !(DwarfType & dwarf::DW_EH_PE_textrel) &&
1932 !(DwarfType & dwarf::DW_EH_PE_funcrel) &&
1933 !(DwarfType & dwarf::DW_EH_PE_datarel))
1934 return;
1935
1936 if (!(DwarfType & dwarf::DW_EH_PE_sdata4))
1937 return;
1938
1939 uint32_t RelType;
1940 switch (DwarfType & 0x0f) {
1941 default:
1942 llvm_unreachable("unsupported DWARF encoding type");
1943 case dwarf::DW_EH_PE_sdata4:
1944 case dwarf::DW_EH_PE_udata4:
1945 RelType = Relocation::getPC32();
1946 Offset -= 4;
1947 break;
1948 case dwarf::DW_EH_PE_sdata8:
1949 case dwarf::DW_EH_PE_udata8:
1950 RelType = Relocation::getPC64();
1951 Offset -= 8;
1952 break;
1953 }
1954
1955 // Create a relocation against an absolute value since the goal is to
1956 // preserve the contents of the section independent of the new values
1957 // of referenced symbols.
1958 RelocatedEHFrameSection->addRelocation(Offset, Symbol: nullptr, Type: RelType, Addend: Value);
1959 };
1960
1961 Error E = EHFrameParser::parse(Data: DE, EHFrameAddress: EHFrameSection->getAddress(), PatcherCallback: createReloc);
1962 check_error(E: std::move(E), Message: "failed to patch EH frame");
1963}
1964
1965Error RewriteInstance::readSpecialSections() {
1966 NamedRegionTimer T("readSpecialSections", "read special sections",
1967 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
1968
1969 bool HasTextRelocations = false;
1970 bool HasSymbolTable = false;
1971 bool HasDebugInfo = false;
1972
1973 // Process special sections.
1974 for (const SectionRef &Section : InputFile->sections()) {
1975 Expected<StringRef> SectionNameOrErr = Section.getName();
1976 check_error(E: SectionNameOrErr.takeError(), Message: "cannot get section name");
1977 StringRef SectionName = *SectionNameOrErr;
1978
1979 if (Error E = Section.getContents().takeError())
1980 return E;
1981 BC->registerSection(Section);
1982 LLVM_DEBUG(
1983 dbgs() << "BOLT-DEBUG: registering section " << SectionName << " @ 0x"
1984 << Twine::utohexstr(Section.getAddress()) << ":0x"
1985 << Twine::utohexstr(Section.getAddress() + Section.getSize())
1986 << "\n");
1987 if (isDebugSection(SectionName))
1988 HasDebugInfo = true;
1989 }
1990
1991 // Set IsRelro section attribute based on PT_GNU_RELRO segment.
1992 markGnuRelroSections();
1993
1994 if (HasDebugInfo && !opts::UpdateDebugSections && !opts::AggregateOnly) {
1995 BC->errs() << "BOLT-WARNING: debug info will be stripped from the binary. "
1996 "Use -update-debug-sections to keep it.\n";
1997 }
1998
1999 HasTextRelocations = (bool)BC->getUniqueSectionByName(
2000 SectionName: ".rela" + std::string(BC->getMainCodeSectionName()));
2001 HasSymbolTable = (bool)BC->getUniqueSectionByName(SectionName: ".symtab");
2002 EHFrameSection = BC->getUniqueSectionByName(SectionName: ".eh_frame");
2003
2004 if (ErrorOr<BinarySection &> BATSec =
2005 BC->getUniqueSectionByName(SectionName: BoltAddressTranslation::SECTION_NAME)) {
2006 BC->HasBATSection = true;
2007 // Do not read BAT when plotting a heatmap
2008 if (opts::HeatmapMode != opts::HeatmapModeKind::HM_Exclusive) {
2009 if (std::error_code EC = BAT->parse(OS&: BC->outs(), Buf: BATSec->getContents())) {
2010 BC->errs() << "BOLT-ERROR: failed to parse BOLT address translation "
2011 "table.\n";
2012 exit(status: 1);
2013 }
2014 }
2015 }
2016
2017 if (opts::PrintSections) {
2018 BC->outs() << "BOLT-INFO: Sections from original binary:\n";
2019 BC->printSections(OS&: BC->outs());
2020 }
2021
2022 if (opts::RelocationMode == cl::BOU_TRUE && !HasTextRelocations) {
2023 BC->errs()
2024 << "BOLT-ERROR: relocations against code are missing from the input "
2025 "file. Cannot proceed in relocations mode (-relocs).\n";
2026 exit(status: 1);
2027 }
2028
2029 BC->HasRelocations =
2030 HasTextRelocations && (opts::RelocationMode != cl::BOU_FALSE);
2031
2032 if (BC->IsLinuxKernel && BC->HasRelocations) {
2033 BC->outs() << "BOLT-INFO: disabling relocation mode for Linux kernel\n";
2034 BC->HasRelocations = false;
2035 }
2036
2037 BC->IsStripped = !HasSymbolTable;
2038
2039 if (BC->IsStripped && !opts::AllowStripped) {
2040 BC->errs()
2041 << "BOLT-ERROR: stripped binaries are not supported. If you know "
2042 "what you're doing, use --allow-stripped to proceed";
2043 exit(status: 1);
2044 }
2045
2046 // Force non-relocation mode for heatmap generation
2047 if (opts::HeatmapMode == opts::HeatmapModeKind::HM_Exclusive)
2048 BC->HasRelocations = false;
2049
2050 if (BC->HasRelocations)
2051 BC->outs() << "BOLT-INFO: enabling " << (opts::StrictMode ? "strict " : "")
2052 << "relocation mode\n";
2053
2054 // Read EH frame for function boundaries info.
2055 Expected<const DWARFDebugFrame *> EHFrameOrError = BC->DwCtx->getEHFrame();
2056 if (!EHFrameOrError)
2057 report_error(Message: "expected valid eh_frame section", E: EHFrameOrError.takeError());
2058 CFIRdWrt.reset(p: new CFIReaderWriter(*BC, *EHFrameOrError.get()));
2059
2060 processSectionMetadata();
2061
2062 // Read .dynamic/PT_DYNAMIC.
2063 return readELFDynamic();
2064}
2065
2066void RewriteInstance::adjustCommandLineOptions() {
2067 if (BC->isAArch64() && !BC->HasRelocations)
2068 BC->errs() << "BOLT-WARNING: non-relocation mode for AArch64 is not fully "
2069 "supported\n";
2070
2071 if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary())
2072 RtLibrary->adjustCommandLineOptions(BC: *BC);
2073
2074 if (BC->isX86() && BC->MAB->allowAutoPadding()) {
2075 if (!BC->HasRelocations) {
2076 BC->errs()
2077 << "BOLT-ERROR: cannot apply mitigations for Intel JCC erratum in "
2078 "non-relocation mode\n";
2079 exit(status: 1);
2080 }
2081 BC->outs()
2082 << "BOLT-WARNING: using mitigation for Intel JCC erratum, layout "
2083 "may take several minutes\n";
2084 }
2085
2086 if (opts::SplitEH && !BC->HasRelocations) {
2087 BC->errs() << "BOLT-WARNING: disabling -split-eh in non-relocation mode\n";
2088 opts::SplitEH = false;
2089 }
2090
2091 if (opts::StrictMode && !BC->HasRelocations) {
2092 BC->errs()
2093 << "BOLT-WARNING: disabling strict mode (-strict) in non-relocation "
2094 "mode\n";
2095 opts::StrictMode = false;
2096 }
2097
2098 if (BC->HasRelocations && opts::AggregateOnly &&
2099 !opts::StrictMode.getNumOccurrences()) {
2100 BC->outs() << "BOLT-INFO: enabling strict relocation mode for aggregation "
2101 "purposes\n";
2102 opts::StrictMode = true;
2103 }
2104
2105 if (!BC->HasRelocations &&
2106 opts::ReorderFunctions != ReorderFunctions::RT_NONE) {
2107 BC->errs() << "BOLT-ERROR: function reordering only works when "
2108 << "relocations are enabled\n";
2109 exit(status: 1);
2110 }
2111
2112 if (!BC->HasRelocations &&
2113 opts::ICF == IdenticalCodeFolding::ICFLevel::Safe) {
2114 BC->errs() << "BOLT-ERROR: binary built without relocations. Safe ICF is "
2115 "not supported\n";
2116 exit(status: 1);
2117 }
2118
2119 if (opts::Instrument ||
2120 (opts::ReorderFunctions != ReorderFunctions::RT_NONE &&
2121 !opts::HotText.getNumOccurrences())) {
2122 opts::HotText = true;
2123 } else if (opts::HotText && !BC->HasRelocations) {
2124 BC->errs() << "BOLT-WARNING: hot text is disabled in non-relocation mode\n";
2125 opts::HotText = false;
2126 }
2127
2128 if (opts::Instrument && opts::UseGnuStack) {
2129 BC->errs() << "BOLT-ERROR: cannot avoid having writeable and executable "
2130 "segment in instrumented binary if program headers will be "
2131 "updated in place\n";
2132 exit(status: 1);
2133 }
2134
2135 if (opts::HotText && opts::HotTextMoveSections.getNumOccurrences() == 0) {
2136 opts::HotTextMoveSections.addValue(V: ".stub");
2137 opts::HotTextMoveSections.addValue(V: ".mover");
2138 opts::HotTextMoveSections.addValue(V: ".never_hugify");
2139 }
2140
2141 if (opts::UseOldText && !BC->OldTextSectionAddress) {
2142 BC->errs()
2143 << "BOLT-WARNING: cannot use old .text as the section was not found"
2144 "\n";
2145 opts::UseOldText = false;
2146 }
2147 if (opts::UseOldText && !BC->HasRelocations) {
2148 BC->errs() << "BOLT-WARNING: cannot use old .text in non-relocation mode\n";
2149 opts::UseOldText = false;
2150 }
2151
2152 if (!opts::AlignText.getNumOccurrences())
2153 opts::AlignText = BC->PageAlign;
2154
2155 if (opts::AlignText < opts::AlignFunctions)
2156 opts::AlignText = (unsigned)opts::AlignFunctions;
2157
2158 if (BC->isX86() && opts::Lite.getNumOccurrences() == 0 && !opts::StrictMode &&
2159 !opts::UseOldText)
2160 opts::Lite = true;
2161
2162 if (opts::Lite && opts::UseOldText) {
2163 BC->errs() << "BOLT-WARNING: cannot combine -lite with -use-old-text. "
2164 "Disabling -use-old-text.\n";
2165 opts::UseOldText = false;
2166 }
2167
2168 if (opts::Lite && opts::StrictMode) {
2169 BC->errs()
2170 << "BOLT-ERROR: -strict and -lite cannot be used at the same time\n";
2171 exit(status: 1);
2172 }
2173
2174 if (opts::Lite)
2175 BC->outs() << "BOLT-INFO: enabling lite mode\n";
2176
2177 if (BC->IsLinuxKernel) {
2178 if (!opts::KeepNops.getNumOccurrences())
2179 opts::KeepNops = true;
2180
2181 // Linux kernel may resume execution after a trap instruction in some cases.
2182 if (!opts::TerminalTrap.getNumOccurrences())
2183 opts::TerminalTrap = false;
2184 }
2185}
2186
2187namespace {
2188template <typename ELFT>
2189int64_t getRelocationAddend(const ELFObjectFile<ELFT> *Obj,
2190 const RelocationRef &RelRef) {
2191 using ELFShdrTy = typename ELFT::Shdr;
2192 using Elf_Rela = typename ELFT::Rela;
2193 int64_t Addend = 0;
2194 const ELFFile<ELFT> &EF = Obj->getELFFile();
2195 DataRefImpl Rel = RelRef.getRawDataRefImpl();
2196 const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));
2197 switch (RelocationSection->sh_type) {
2198 default:
2199 llvm_unreachable("unexpected relocation section type");
2200 case ELF::SHT_REL:
2201 break;
2202 case ELF::SHT_RELA: {
2203 const Elf_Rela *RelA = Obj->getRela(Rel);
2204 Addend = RelA->r_addend;
2205 break;
2206 }
2207 }
2208
2209 return Addend;
2210}
2211
2212int64_t getRelocationAddend(const ELFObjectFileBase *Obj,
2213 const RelocationRef &Rel) {
2214 return getRelocationAddend(Obj: cast<ELF64LEObjectFile>(Val: Obj), RelRef: Rel);
2215}
2216
2217template <typename ELFT>
2218uint32_t getRelocationSymbol(const ELFObjectFile<ELFT> *Obj,
2219 const RelocationRef &RelRef) {
2220 using ELFShdrTy = typename ELFT::Shdr;
2221 uint32_t Symbol = 0;
2222 const ELFFile<ELFT> &EF = Obj->getELFFile();
2223 DataRefImpl Rel = RelRef.getRawDataRefImpl();
2224 const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));
2225 switch (RelocationSection->sh_type) {
2226 default:
2227 llvm_unreachable("unexpected relocation section type");
2228 case ELF::SHT_REL:
2229 Symbol = Obj->getRel(Rel)->getSymbol(EF.isMips64EL());
2230 break;
2231 case ELF::SHT_RELA:
2232 Symbol = Obj->getRela(Rel)->getSymbol(EF.isMips64EL());
2233 break;
2234 }
2235
2236 return Symbol;
2237}
2238
2239uint32_t getRelocationSymbol(const ELFObjectFileBase *Obj,
2240 const RelocationRef &Rel) {
2241 return getRelocationSymbol(Obj: cast<ELF64LEObjectFile>(Val: Obj), RelRef: Rel);
2242}
2243} // anonymous namespace
2244
2245bool RewriteInstance::analyzeRelocation(
2246 const RelocationRef &Rel, uint32_t &RType, std::string &SymbolName,
2247 bool &IsSectionRelocation, uint64_t &SymbolAddress, int64_t &Addend,
2248 uint64_t &ExtractedValue, bool &Skip) const {
2249 Skip = false;
2250 if (!Relocation::isSupported(Type: RType))
2251 return false;
2252
2253 auto IsWeakReference = [](const SymbolRef &Symbol) {
2254 Expected<uint32_t> SymFlagsOrErr = Symbol.getFlags();
2255 if (!SymFlagsOrErr)
2256 return false;
2257 return (*SymFlagsOrErr & SymbolRef::SF_Undefined) &&
2258 (*SymFlagsOrErr & SymbolRef::SF_Weak);
2259 };
2260
2261 const bool IsAArch64 = BC->isAArch64();
2262
2263 const size_t RelSize = Relocation::getSizeForType(Type: RType);
2264
2265 ErrorOr<uint64_t> Value =
2266 BC->getUnsignedValueAtAddress(Address: Rel.getOffset(), Size: RelSize);
2267 assert(Value && "failed to extract relocated value");
2268
2269 ExtractedValue = Relocation::extractValue(Type: RType, Contents: *Value, PC: Rel.getOffset());
2270 Addend = getRelocationAddend(Obj: InputFile, Rel);
2271
2272 const bool IsPCRelative = Relocation::isPCRelative(Type: RType);
2273 const uint64_t PCRelOffset = IsPCRelative && !IsAArch64 ? Rel.getOffset() : 0;
2274 bool SkipVerification = false;
2275 auto SymbolIter = Rel.getSymbol();
2276 if (SymbolIter == InputFile->symbol_end()) {
2277 SymbolAddress = ExtractedValue - Addend + PCRelOffset;
2278 MCSymbol *RelSymbol =
2279 BC->getOrCreateGlobalSymbol(Address: SymbolAddress, Prefix: "RELSYMat");
2280 SymbolName = std::string(RelSymbol->getName());
2281 IsSectionRelocation = false;
2282 } else {
2283 const SymbolRef &Symbol = *SymbolIter;
2284 SymbolName = std::string(cantFail(ValOrErr: Symbol.getName()));
2285 SymbolAddress = cantFail(ValOrErr: Symbol.getAddress());
2286 SkipVerification = (cantFail(ValOrErr: Symbol.getType()) == SymbolRef::ST_Other);
2287 // Section symbols are marked as ST_Debug.
2288 IsSectionRelocation = (cantFail(ValOrErr: Symbol.getType()) == SymbolRef::ST_Debug);
2289 // Check for PLT entry registered with symbol name
2290 if (!SymbolAddress && !IsWeakReference(Symbol) &&
2291 (IsAArch64 || BC->isRISCV())) {
2292 const BinaryData *BD = BC->getPLTBinaryDataByName(Name: SymbolName);
2293 SymbolAddress = BD ? BD->getAddress() : 0;
2294 }
2295 }
2296 // For PIE or dynamic libs, the linker may choose not to put the relocation
2297 // result at the address if it is a X86_64_64 one because it will emit a
2298 // dynamic relocation (X86_RELATIVE) for the dynamic linker and loader to
2299 // resolve it at run time. The static relocation result goes as the addend
2300 // of the dynamic relocation in this case. We can't verify these cases.
2301 // FIXME: perhaps we can try to find if it really emitted a corresponding
2302 // RELATIVE relocation at this offset with the correct value as the addend.
2303 if (!BC->HasFixedLoadAddress && RelSize == 8)
2304 SkipVerification = true;
2305
2306 if (IsSectionRelocation && !IsAArch64) {
2307 ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address: SymbolAddress);
2308 assert(Section && "section expected for section relocation");
2309 SymbolName = "section " + std::string(Section->getName());
2310 // Convert section symbol relocations to regular relocations inside
2311 // non-section symbols.
2312 if (Section->containsAddress(Address: ExtractedValue) && !IsPCRelative) {
2313 SymbolAddress = ExtractedValue;
2314 Addend = 0;
2315 } else {
2316 Addend = ExtractedValue - (SymbolAddress - PCRelOffset);
2317 }
2318 }
2319
2320 // GOT relocation can cause the underlying instruction to be modified by the
2321 // linker, resulting in the extracted value being different from the actual
2322 // symbol. It's also possible to have a GOT entry for a symbol defined in the
2323 // binary. In the latter case, the instruction can be using the GOT version
2324 // causing the extracted value mismatch. Similar cases can happen for TLS.
2325 // Pass the relocation information as is to the disassembler and let it decide
2326 // how to use it for the operand symbolization.
2327 if (Relocation::isGOT(Type: RType) || Relocation::isTLS(Type: RType)) {
2328 SkipVerification = true;
2329 } else if (!SymbolAddress) {
2330 assert(!IsSectionRelocation);
2331 if (ExtractedValue || Addend == 0 || IsPCRelative) {
2332 SymbolAddress =
2333 truncateToSize(Value: ExtractedValue - Addend + PCRelOffset, Bytes: RelSize);
2334 } else {
2335 // This is weird case. The extracted value is zero but the addend is
2336 // non-zero and the relocation is not pc-rel. Using the previous logic,
2337 // the SymbolAddress would end up as a huge number. Seen in
2338 // exceptions_pic.test.
2339 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: relocation @ 0x"
2340 << Twine::utohexstr(Rel.getOffset())
2341 << " value does not match addend for "
2342 << "relocation to undefined symbol.\n");
2343 return true;
2344 }
2345 }
2346
2347 auto verifyExtractedValue = [&]() {
2348 if (SkipVerification)
2349 return true;
2350
2351 if (IsAArch64 || BC->isRISCV())
2352 return true;
2353
2354 if (SymbolName == "__hot_start" || SymbolName == "__hot_end")
2355 return true;
2356
2357 if (RType == ELF::R_X86_64_PLT32)
2358 return true;
2359
2360 return truncateToSize(Value: ExtractedValue, Bytes: RelSize) ==
2361 truncateToSize(Value: SymbolAddress + Addend - PCRelOffset, Bytes: RelSize);
2362 };
2363
2364 (void)verifyExtractedValue;
2365 assert(verifyExtractedValue() && "mismatched extracted relocation value");
2366
2367 return true;
2368}
2369
2370void RewriteInstance::processDynamicRelocations() {
2371 // Read .relr.dyn section containing compressed R_*_RELATIVE relocations.
2372 if (DynamicRelrSize > 0) {
2373 ErrorOr<BinarySection &> DynamicRelrSectionOrErr =
2374 BC->getSectionForAddress(Address: *DynamicRelrAddress);
2375 if (!DynamicRelrSectionOrErr)
2376 report_error(Message: "unable to find section corresponding to DT_RELR",
2377 EC: DynamicRelrSectionOrErr.getError());
2378 if (DynamicRelrSectionOrErr->getSize() != DynamicRelrSize)
2379 report_error(Message: "section size mismatch for DT_RELRSZ",
2380 EC: errc::executable_format_error);
2381 readDynamicRelrRelocations(Section&: *DynamicRelrSectionOrErr);
2382 }
2383
2384 // Read relocations for PLT - DT_JMPREL.
2385 if (PLTRelocationsSize > 0) {
2386 ErrorOr<BinarySection &> PLTRelSectionOrErr =
2387 BC->getSectionForAddress(Address: *PLTRelocationsAddress);
2388 if (!PLTRelSectionOrErr)
2389 report_error(Message: "unable to find section corresponding to DT_JMPREL",
2390 EC: PLTRelSectionOrErr.getError());
2391 if (PLTRelSectionOrErr->getSize() != PLTRelocationsSize)
2392 report_error(Message: "section size mismatch for DT_PLTRELSZ",
2393 EC: errc::executable_format_error);
2394 readDynamicRelocations(Section: PLTRelSectionOrErr->getSectionRef(),
2395 /*IsJmpRel*/ true);
2396 }
2397
2398 // The rest of dynamic relocations - DT_RELA.
2399 // The static executable might have .rela.dyn secion and not have PT_DYNAMIC
2400 if (!DynamicRelocationsSize && BC->IsStaticExecutable) {
2401 ErrorOr<BinarySection &> DynamicRelSectionOrErr =
2402 BC->getUniqueSectionByName(SectionName: getRelaDynSectionName());
2403 if (DynamicRelSectionOrErr) {
2404 DynamicRelocationsAddress = DynamicRelSectionOrErr->getAddress();
2405 DynamicRelocationsSize = DynamicRelSectionOrErr->getSize();
2406 const SectionRef &SectionRef = DynamicRelSectionOrErr->getSectionRef();
2407 DynamicRelativeRelocationsCount = std::distance(
2408 first: SectionRef.relocation_begin(), last: SectionRef.relocation_end());
2409 }
2410 }
2411
2412 if (DynamicRelocationsSize > 0) {
2413 ErrorOr<BinarySection &> DynamicRelSectionOrErr =
2414 BC->getSectionForAddress(Address: *DynamicRelocationsAddress);
2415 if (!DynamicRelSectionOrErr)
2416 report_error(Message: "unable to find section corresponding to DT_RELA",
2417 EC: DynamicRelSectionOrErr.getError());
2418 auto DynamicRelSectionSize = DynamicRelSectionOrErr->getSize();
2419 // On RISC-V DT_RELASZ seems to include both .rela.dyn and .rela.plt
2420 if (DynamicRelocationsSize == DynamicRelSectionSize + PLTRelocationsSize)
2421 DynamicRelocationsSize = DynamicRelSectionSize;
2422 if (DynamicRelSectionSize != DynamicRelocationsSize)
2423 report_error(Message: "section size mismatch for DT_RELASZ",
2424 EC: errc::executable_format_error);
2425 readDynamicRelocations(Section: DynamicRelSectionOrErr->getSectionRef(),
2426 /*IsJmpRel*/ false);
2427 }
2428}
2429
2430void RewriteInstance::processRelocations() {
2431 if (!BC->HasRelocations)
2432 return;
2433
2434 for (const SectionRef &Section : InputFile->sections()) {
2435 section_iterator SecIter = cantFail(ValOrErr: Section.getRelocatedSection());
2436 if (SecIter == InputFile->section_end())
2437 continue;
2438 if (BinarySection(*BC, Section).isAllocatable())
2439 continue;
2440
2441 readRelocations(Section);
2442 }
2443
2444 if (NumFailedRelocations)
2445 BC->errs() << "BOLT-WARNING: Failed to analyze " << NumFailedRelocations
2446 << " relocations\n";
2447}
2448
2449void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
2450 bool IsJmpRel) {
2451 assert(BinarySection(*BC, Section).isAllocatable() && "allocatable expected");
2452
2453 LLVM_DEBUG({
2454 StringRef SectionName = cantFail(Section.getName());
2455 dbgs() << "BOLT-DEBUG: reading relocations for section " << SectionName
2456 << ":\n";
2457 });
2458
2459 for (const RelocationRef &Rel : Section.relocations()) {
2460 const uint32_t RType = Relocation::getType(Rel);
2461 if (Relocation::isNone(Type: RType))
2462 continue;
2463
2464 StringRef SymbolName = "<none>";
2465 MCSymbol *Symbol = nullptr;
2466 uint64_t SymbolAddress = 0;
2467 const uint64_t Addend = getRelocationAddend(Obj: InputFile, Rel);
2468
2469 symbol_iterator SymbolIter = Rel.getSymbol();
2470 if (SymbolIter != InputFile->symbol_end()) {
2471 SymbolName = cantFail(ValOrErr: SymbolIter->getName());
2472 BinaryData *BD = BC->getBinaryDataByName(Name: SymbolName);
2473 Symbol = BD ? BD->getSymbol()
2474 : BC->getOrCreateUndefinedGlobalSymbol(Name: SymbolName);
2475 SymbolAddress = cantFail(ValOrErr: SymbolIter->getAddress());
2476 (void)SymbolAddress;
2477 }
2478
2479 LLVM_DEBUG(
2480 SmallString<16> TypeName;
2481 Rel.getTypeName(TypeName);
2482 dbgs() << "BOLT-DEBUG: dynamic relocation at 0x"
2483 << Twine::utohexstr(Rel.getOffset()) << " : " << TypeName
2484 << " : " << SymbolName << " : " << Twine::utohexstr(SymbolAddress)
2485 << " : + 0x" << Twine::utohexstr(Addend) << '\n'
2486 );
2487
2488 if (IsJmpRel)
2489 IsJmpRelocation[RType] = true;
2490
2491 if (Symbol)
2492 SymbolIndex[Symbol] = getRelocationSymbol(Obj: InputFile, Rel);
2493
2494 const uint64_t ReferencedAddress = SymbolAddress + Addend;
2495 BinaryFunction *Func =
2496 BC->getBinaryFunctionContainingAddress(Address: ReferencedAddress);
2497
2498 if (Relocation::isRelative(Type: RType) && SymbolAddress == 0) {
2499 if (Func) {
2500 if (!Func->isInConstantIsland(Address: ReferencedAddress)) {
2501 if (const uint64_t ReferenceOffset =
2502 ReferencedAddress - Func->getAddress()) {
2503 Func->addEntryPointAtOffset(Offset: ReferenceOffset);
2504 }
2505 } else {
2506 BC->errs() << "BOLT-ERROR: referenced address at 0x"
2507 << Twine::utohexstr(Val: ReferencedAddress)
2508 << " is in constant island of function " << *Func << "\n";
2509 exit(status: 1);
2510 }
2511 }
2512 } else if (Relocation::isRelative(Type: RType) && SymbolAddress != 0) {
2513 BC->errs() << "BOLT-ERROR: symbol address non zero for RELATIVE "
2514 "relocation type\n";
2515 exit(status: 1);
2516 }
2517
2518 BC->addDynamicRelocation(Address: Rel.getOffset(), Symbol, Type: RType, Addend);
2519 }
2520}
2521
2522void RewriteInstance::readDynamicRelrRelocations(BinarySection &Section) {
2523 assert(Section.isAllocatable() && "allocatable expected");
2524
2525 LLVM_DEBUG({
2526 StringRef SectionName = Section.getName();
2527 dbgs() << "BOLT-DEBUG: reading relocations in section " << SectionName
2528 << ":\n";
2529 });
2530
2531 const uint32_t RType = Relocation::getRelative();
2532 const uint8_t PSize = BC->AsmInfo->getCodePointerSize();
2533 const uint64_t MaxDelta = ((CHAR_BIT * DynamicRelrEntrySize) - 1) * PSize;
2534
2535 auto ExtractAddendValue = [&](uint64_t Address) -> uint64_t {
2536 ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);
2537 assert(Section && "cannot get section for data address from RELR");
2538 DataExtractor DE = DataExtractor(Section->getContents(),
2539 BC->AsmInfo->isLittleEndian(), PSize);
2540 uint64_t Offset = Address - Section->getAddress();
2541 return DE.getUnsigned(offset_ptr: &Offset, byte_size: PSize);
2542 };
2543
2544 auto AddRelocation = [&](uint64_t Address) {
2545 uint64_t Addend = ExtractAddendValue(Address);
2546 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: R_*_RELATIVE relocation at 0x"
2547 << Twine::utohexstr(Address) << " to 0x"
2548 << Twine::utohexstr(Addend) << '\n';);
2549 BC->addDynamicRelocation(Address, Symbol: nullptr, Type: RType, Addend);
2550 };
2551
2552 DataExtractor DE = DataExtractor(Section.getContents(),
2553 BC->AsmInfo->isLittleEndian(), PSize);
2554 uint64_t Offset = 0, Address = 0;
2555 uint64_t RelrCount = DynamicRelrSize / DynamicRelrEntrySize;
2556 while (RelrCount--) {
2557 assert(DE.isValidOffset(Offset));
2558 uint64_t Entry = DE.getUnsigned(offset_ptr: &Offset, byte_size: DynamicRelrEntrySize);
2559 if ((Entry & 1) == 0) {
2560 AddRelocation(Entry);
2561 Address = Entry + PSize;
2562 } else {
2563 const uint64_t StartAddress = Address;
2564 while (Entry >>= 1) {
2565 if (Entry & 1)
2566 AddRelocation(Address);
2567
2568 Address += PSize;
2569 }
2570
2571 Address = StartAddress + MaxDelta;
2572 }
2573 }
2574}
2575
2576void RewriteInstance::printRelocationInfo(const RelocationRef &Rel,
2577 StringRef SymbolName,
2578 uint64_t SymbolAddress,
2579 uint64_t Addend,
2580 uint64_t ExtractedValue) const {
2581 SmallString<16> TypeName;
2582 Rel.getTypeName(Result&: TypeName);
2583 const uint64_t Address = SymbolAddress + Addend;
2584 const uint64_t Offset = Rel.getOffset();
2585 ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address: SymbolAddress);
2586 BinaryFunction *Func =
2587 BC->getBinaryFunctionContainingAddress(Address: Offset, CheckPastEnd: false, UseMaxSize: BC->isAArch64());
2588 dbgs() << formatv(Fmt: "Relocation: offset = {0:x}; type = {1}; value = {2:x}; ",
2589 Vals: Offset, Vals&: TypeName, Vals&: ExtractedValue)
2590 << formatv(Fmt: "symbol = {0} ({1}); symbol address = {2:x}; ", Vals&: SymbolName,
2591 Vals: Section ? Section->getName() : "", Vals&: SymbolAddress)
2592 << formatv(Fmt: "addend = {0:x}; address = {1:x}; in = ", Vals&: Addend, Vals: Address);
2593 if (Func)
2594 dbgs() << Func->getPrintName();
2595 else
2596 dbgs() << BC->getSectionForAddress(Address: Rel.getOffset())->getName();
2597 dbgs() << '\n';
2598}
2599
2600void RewriteInstance::readRelocations(const SectionRef &Section) {
2601 LLVM_DEBUG({
2602 StringRef SectionName = cantFail(Section.getName());
2603 dbgs() << "BOLT-DEBUG: reading relocations for section " << SectionName
2604 << ":\n";
2605 });
2606 if (BinarySection(*BC, Section).isAllocatable()) {
2607 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring runtime relocations\n");
2608 return;
2609 }
2610 section_iterator SecIter = cantFail(ValOrErr: Section.getRelocatedSection());
2611 assert(SecIter != InputFile->section_end() && "relocated section expected");
2612 SectionRef RelocatedSection = *SecIter;
2613
2614 StringRef RelocatedSectionName = cantFail(ValOrErr: RelocatedSection.getName());
2615 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: relocated section is "
2616 << RelocatedSectionName << '\n');
2617
2618 if (!BinarySection(*BC, RelocatedSection).isAllocatable()) {
2619 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring relocations against "
2620 << "non-allocatable section\n");
2621 return;
2622 }
2623 const bool SkipRelocs = StringSwitch<bool>(RelocatedSectionName)
2624 .Cases(S0: ".plt", S1: ".rela.plt", S2: ".got.plt",
2625 S3: ".eh_frame", S4: ".gcc_except_table", Value: true)
2626 .Default(Value: false);
2627 if (SkipRelocs) {
2628 LLVM_DEBUG(
2629 dbgs() << "BOLT-DEBUG: ignoring relocations against known section\n");
2630 return;
2631 }
2632
2633 for (const RelocationRef &Rel : Section.relocations())
2634 handleRelocation(RelocatedSection, Rel);
2635}
2636
2637void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
2638 const RelocationRef &Rel) {
2639 const bool IsAArch64 = BC->isAArch64();
2640 const bool IsX86 = BC->isX86();
2641 const bool IsFromCode = RelocatedSection.isText();
2642 const bool IsWritable = BinarySection(*BC, RelocatedSection).isWritable();
2643
2644 SmallString<16> TypeName;
2645 Rel.getTypeName(Result&: TypeName);
2646 uint32_t RType = Relocation::getType(Rel);
2647 if (Relocation::skipRelocationType(Type: RType))
2648 return;
2649
2650 // Adjust the relocation type as the linker might have skewed it.
2651 if (IsX86 && (RType & ELF::R_X86_64_converted_reloc_bit)) {
2652 if (opts::Verbosity >= 1)
2653 dbgs() << "BOLT-WARNING: ignoring R_X86_64_converted_reloc_bit\n";
2654 RType &= ~ELF::R_X86_64_converted_reloc_bit;
2655 }
2656
2657 if (Relocation::isTLS(Type: RType)) {
2658 // No special handling required for TLS relocations on X86.
2659 if (IsX86)
2660 return;
2661
2662 // The non-got related TLS relocations on AArch64 and RISC-V also could be
2663 // skipped.
2664 if (!Relocation::isGOT(Type: RType))
2665 return;
2666 }
2667
2668 if (!IsAArch64 && BC->getDynamicRelocationAt(Address: Rel.getOffset())) {
2669 LLVM_DEBUG({
2670 dbgs() << formatv("BOLT-DEBUG: address {0:x} has a ", Rel.getOffset())
2671 << "dynamic relocation against it. Ignoring static relocation.\n";
2672 });
2673 return;
2674 }
2675
2676 std::string SymbolName;
2677 uint64_t SymbolAddress;
2678 int64_t Addend;
2679 uint64_t ExtractedValue;
2680 bool IsSectionRelocation;
2681 bool Skip;
2682 if (!analyzeRelocation(Rel, RType, SymbolName, IsSectionRelocation,
2683 SymbolAddress, Addend, ExtractedValue, Skip)) {
2684 LLVM_DEBUG({
2685 dbgs() << "BOLT-WARNING: failed to analyze relocation @ offset = "
2686 << formatv("{0:x}; type name = {1}\n", Rel.getOffset(), TypeName);
2687 });
2688 ++NumFailedRelocations;
2689 return;
2690 }
2691
2692 if (Skip) {
2693 LLVM_DEBUG({
2694 dbgs() << "BOLT-DEBUG: skipping relocation @ offset = "
2695 << formatv("{0:x}; type name = {1}\n", Rel.getOffset(), TypeName);
2696 });
2697 return;
2698 }
2699
2700 if (!IsFromCode && !IsWritable && (IsX86 || IsAArch64) &&
2701 Relocation::isPCRelative(Type: RType)) {
2702 BinaryData *BD = BC->getBinaryDataContainingAddress(Address: Rel.getOffset());
2703 if (BD && (BD->nameStartsWith(Prefix: "_ZTV") || // vtable
2704 BD->nameStartsWith(Prefix: "_ZTCN"))) { // construction vtable
2705 BinaryFunction *BF = BC->getBinaryFunctionContainingAddress(
2706 Address: SymbolAddress, /*CheckPastEnd*/ false, /*UseMaxSize*/ true);
2707 if (BF) {
2708 if (BF->getAddress() != SymbolAddress) {
2709 BC->errs()
2710 << "BOLT-ERROR: the virtual function table entry at offset 0x"
2711 << Twine::utohexstr(Val: Rel.getOffset())
2712 << " points to the middle of a function @ 0x"
2713 << Twine::utohexstr(Val: BF->getAddress()) << "\n";
2714 exit(status: 1);
2715 }
2716 BC->addRelocation(Address: Rel.getOffset(), Symbol: BF->getSymbol(), Type: RType, Addend,
2717 Value: ExtractedValue);
2718 return;
2719 }
2720 }
2721 }
2722
2723 const uint64_t Address = SymbolAddress + Addend;
2724
2725 LLVM_DEBUG({
2726 dbgs() << "BOLT-DEBUG: ";
2727 printRelocationInfo(Rel, SymbolName, SymbolAddress, Addend, ExtractedValue);
2728 });
2729
2730 BinaryFunction *ContainingBF = nullptr;
2731 if (IsFromCode) {
2732 ContainingBF =
2733 BC->getBinaryFunctionContainingAddress(Address: Rel.getOffset(),
2734 /*CheckPastEnd*/ false,
2735 /*UseMaxSize*/ true);
2736 assert(ContainingBF && "cannot find function for address in code");
2737 if (!IsAArch64 && !ContainingBF->containsAddress(PC: Rel.getOffset())) {
2738 if (opts::Verbosity >= 1)
2739 BC->outs() << formatv(
2740 Fmt: "BOLT-INFO: {0} has relocations in padding area\n", Vals&: *ContainingBF);
2741 ContainingBF->setSize(ContainingBF->getMaxSize());
2742 ContainingBF->setSimple(false);
2743 return;
2744 }
2745 }
2746
2747 MCSymbol *ReferencedSymbol = nullptr;
2748 if (!IsSectionRelocation) {
2749 if (BinaryData *BD = BC->getBinaryDataByName(Name: SymbolName)) {
2750 ReferencedSymbol = BD->getSymbol();
2751 } else if (BC->isGOTSymbol(SymName: SymbolName)) {
2752 if (BinaryData *BD = BC->getGOTSymbol())
2753 ReferencedSymbol = BD->getSymbol();
2754 } else if (BinaryData *BD = BC->getBinaryDataAtAddress(Address: SymbolAddress)) {
2755 ReferencedSymbol = BD->getSymbol();
2756 }
2757 }
2758
2759 ErrorOr<BinarySection &> ReferencedSection{std::errc::bad_address};
2760 symbol_iterator SymbolIter = Rel.getSymbol();
2761 if (SymbolIter != InputFile->symbol_end()) {
2762 SymbolRef Symbol = *SymbolIter;
2763 section_iterator Section =
2764 cantFail(ValOrErr: Symbol.getSection(), Msg: "cannot get symbol section");
2765 if (Section != InputFile->section_end()) {
2766 Expected<StringRef> SectionName = Section->getName();
2767 if (SectionName && !SectionName->empty())
2768 ReferencedSection = BC->getUniqueSectionByName(SectionName: *SectionName);
2769 } else if (BC->isRISCV() && ReferencedSymbol && ContainingBF &&
2770 (cantFail(ValOrErr: Symbol.getFlags()) & SymbolRef::SF_Absolute)) {
2771 // This might be a relocation for an ABS symbols like __global_pointer$ on
2772 // RISC-V
2773 ContainingBF->addRelocation(Address: Rel.getOffset(), Symbol: ReferencedSymbol,
2774 RelType: Relocation::getType(Rel), Addend: 0,
2775 Value: cantFail(ValOrErr: Symbol.getValue()));
2776 return;
2777 }
2778 }
2779
2780 if (!ReferencedSection)
2781 ReferencedSection = BC->getSectionForAddress(Address: SymbolAddress);
2782
2783 const bool IsToCode = ReferencedSection && ReferencedSection->isText();
2784
2785 // Special handling of PC-relative relocations.
2786 if (IsX86 && Relocation::isPCRelative(Type: RType)) {
2787 if (!IsFromCode && IsToCode) {
2788 // PC-relative relocations from data to code are tricky since the
2789 // original information is typically lost after linking, even with
2790 // '--emit-relocs'. Such relocations are normally used by PIC-style
2791 // jump tables and they reference both the jump table and jump
2792 // targets by computing the difference between the two. If we blindly
2793 // apply the relocation, it will appear that it references an arbitrary
2794 // location in the code, possibly in a different function from the one
2795 // containing the jump table.
2796 //
2797 // For that reason, we only register the fact that there is a
2798 // PC-relative relocation at a given address against the code.
2799 // The actual referenced label/address will be determined during jump
2800 // table analysis.
2801 BC->addPCRelativeDataRelocation(Address: Rel.getOffset());
2802 } else if (ContainingBF && !IsSectionRelocation && ReferencedSymbol) {
2803 // If we know the referenced symbol, register the relocation from
2804 // the code. It's required to properly handle cases where
2805 // "symbol + addend" references an object different from "symbol".
2806 ContainingBF->addRelocation(Address: Rel.getOffset(), Symbol: ReferencedSymbol, RelType: RType,
2807 Addend, Value: ExtractedValue);
2808 } else {
2809 LLVM_DEBUG({
2810 dbgs() << "BOLT-DEBUG: not creating PC-relative relocation at"
2811 << formatv("{0:x} for {1}\n", Rel.getOffset(), SymbolName);
2812 });
2813 }
2814
2815 return;
2816 }
2817
2818 bool ForceRelocation = BC->forceSymbolRelocations(SymbolName);
2819 if ((BC->isAArch64() || BC->isRISCV()) && Relocation::isGOT(Type: RType))
2820 ForceRelocation = true;
2821
2822 if (!ReferencedSection && !ForceRelocation) {
2823 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: cannot determine referenced section.\n");
2824 return;
2825 }
2826
2827 // Occasionally we may see a reference past the last byte of the function
2828 // typically as a result of __builtin_unreachable(). Check it here.
2829 BinaryFunction *ReferencedBF = BC->getBinaryFunctionContainingAddress(
2830 Address, /*CheckPastEnd*/ true, /*UseMaxSize*/ IsAArch64);
2831
2832 if (!IsSectionRelocation) {
2833 if (BinaryFunction *BF =
2834 BC->getBinaryFunctionContainingAddress(Address: SymbolAddress)) {
2835 if (BF != ReferencedBF) {
2836 // It's possible we are referencing a function without referencing any
2837 // code, e.g. when taking a bitmask action on a function address.
2838 BC->errs()
2839 << "BOLT-WARNING: non-standard function reference (e.g. bitmask)"
2840 << formatv(Fmt: " detected against function {0} from ", Vals&: *BF);
2841 if (IsFromCode)
2842 BC->errs() << formatv(Fmt: "function {0}\n", Vals&: *ContainingBF);
2843 else
2844 BC->errs() << formatv(Fmt: "data section at {0:x}\n", Vals: Rel.getOffset());
2845 LLVM_DEBUG(printRelocationInfo(Rel, SymbolName, SymbolAddress, Addend,
2846 ExtractedValue));
2847 ReferencedBF = BF;
2848 }
2849 }
2850 } else if (ReferencedBF) {
2851 assert(ReferencedSection && "section expected for section relocation");
2852 if (*ReferencedBF->getOriginSection() != *ReferencedSection) {
2853 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring false function reference\n");
2854 ReferencedBF = nullptr;
2855 }
2856 }
2857
2858 // Workaround for a member function pointer de-virtualization bug. We check
2859 // if a non-pc-relative relocation in the code is pointing to (fptr - 1).
2860 if (IsToCode && ContainingBF && !Relocation::isPCRelative(Type: RType) &&
2861 (!ReferencedBF || (ReferencedBF->getAddress() != Address))) {
2862 if (const BinaryFunction *RogueBF =
2863 BC->getBinaryFunctionAtAddress(Address: Address + 1)) {
2864 // Do an extra check that the function was referenced previously.
2865 // It's a linear search, but it should rarely happen.
2866 auto CheckReloc = [&](const Relocation &Rel) {
2867 return Rel.Symbol == RogueBF->getSymbol() &&
2868 !Relocation::isPCRelative(Type: Rel.Type);
2869 };
2870 bool Found = llvm::any_of(
2871 Range: llvm::make_second_range(c&: ContainingBF->Relocations), P: CheckReloc);
2872
2873 if (Found) {
2874 BC->errs()
2875 << "BOLT-WARNING: detected possible compiler de-virtualization "
2876 "bug: -1 addend used with non-pc-relative relocation against "
2877 << formatv(Fmt: "function {0} in function {1}\n", Vals: *RogueBF,
2878 Vals&: *ContainingBF);
2879 return;
2880 }
2881 }
2882 }
2883
2884 if (ForceRelocation && !ReferencedBF) {
2885 // Create the relocation symbol if it's not defined in the binary.
2886 if (SymbolAddress == 0)
2887 ReferencedSymbol = BC->registerNameAtAddress(Name: SymbolName, Address: 0, Size: 0, Alignment: 0);
2888
2889 LLVM_DEBUG(
2890 dbgs() << "BOLT-DEBUG: forcing relocation against symbol "
2891 << (ReferencedSymbol ? ReferencedSymbol->getName() : "<none>")
2892 << " with addend " << Addend << '\n');
2893 } else if (ReferencedBF) {
2894 ReferencedSymbol = ReferencedBF->getSymbol();
2895 uint64_t RefFunctionOffset = 0;
2896
2897 // Adjust the point of reference to a code location inside a function.
2898 if (ReferencedBF->containsAddress(PC: Address, /*UseMaxSize = */ true)) {
2899 RefFunctionOffset = Address - ReferencedBF->getAddress();
2900 if (Relocation::isInstructionReference(Type: RType)) {
2901 // Instruction labels are created while disassembling so we just leave
2902 // the symbol empty for now. Since the extracted value is typically
2903 // unrelated to the referenced symbol (e.g., %pcrel_lo in RISC-V
2904 // references an instruction but the patched value references the low
2905 // bits of a data address), we set the extracted value to the symbol
2906 // address in order to be able to correctly reconstruct the reference
2907 // later.
2908 ReferencedSymbol = nullptr;
2909 ExtractedValue = Address;
2910 } else if (RefFunctionOffset) {
2911 if (ContainingBF && ContainingBF != ReferencedBF) {
2912 ReferencedSymbol =
2913 ReferencedBF->addEntryPointAtOffset(Offset: RefFunctionOffset);
2914 } else {
2915 ReferencedSymbol =
2916 ReferencedBF->getOrCreateLocalLabel(Address,
2917 /*CreatePastEnd =*/true);
2918
2919 // If ContainingBF != nullptr, it equals ReferencedBF (see
2920 // if-condition above) so we're handling a relocation from a function
2921 // to itself. RISC-V uses such relocations for branches, for example.
2922 // These should not be registered as externally references offsets.
2923 if (!ContainingBF)
2924 ReferencedBF->registerReferencedOffset(Offset: RefFunctionOffset);
2925 }
2926 if (opts::Verbosity > 1 &&
2927 BinarySection(*BC, RelocatedSection).isWritable())
2928 BC->errs()
2929 << "BOLT-WARNING: writable reference into the middle of the "
2930 << formatv(Fmt: "function {0} detected at address {1:x}\n",
2931 Vals&: *ReferencedBF, Vals: Rel.getOffset());
2932 }
2933 SymbolAddress = Address;
2934 Addend = 0;
2935 }
2936 LLVM_DEBUG({
2937 dbgs() << " referenced function " << *ReferencedBF;
2938 if (Address != ReferencedBF->getAddress())
2939 dbgs() << formatv(" at offset {0:x}", RefFunctionOffset);
2940 dbgs() << '\n';
2941 });
2942 } else {
2943 if (IsToCode && SymbolAddress) {
2944 // This can happen e.g. with PIC-style jump tables.
2945 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: no corresponding function for "
2946 "relocation against code\n");
2947 }
2948
2949 // In AArch64 there are zero reasons to keep a reference to the
2950 // "original" symbol plus addend. The original symbol is probably just a
2951 // section symbol. If we are here, this means we are probably accessing
2952 // data, so it is imperative to keep the original address.
2953 if (IsAArch64) {
2954 SymbolName = formatv(Fmt: "SYMBOLat{0:x}", Vals: Address);
2955 SymbolAddress = Address;
2956 Addend = 0;
2957 }
2958
2959 if (BinaryData *BD = BC->getBinaryDataContainingAddress(Address: SymbolAddress)) {
2960 // Note: this assertion is trying to check sanity of BinaryData objects
2961 // but AArch64 and RISCV has inferred and incomplete object locations
2962 // coming from GOT/TLS or any other non-trivial relocation (that requires
2963 // creation of sections and whose symbol address is not really what should
2964 // be encoded in the instruction). So we essentially disabled this check
2965 // for AArch64 and live with bogus names for objects.
2966 assert((IsAArch64 || BC->isRISCV() || IsSectionRelocation ||
2967 BD->nameStartsWith(SymbolName) ||
2968 BD->nameStartsWith("PG" + SymbolName) ||
2969 (BD->nameStartsWith("ANONYMOUS") &&
2970 (BD->getSectionName().starts_with(".plt") ||
2971 BD->getSectionName().ends_with(".plt")))) &&
2972 "BOLT symbol names of all non-section relocations must match up "
2973 "with symbol names referenced in the relocation");
2974
2975 if (IsSectionRelocation)
2976 BC->markAmbiguousRelocations(BD&: *BD, Address);
2977
2978 ReferencedSymbol = BD->getSymbol();
2979 Addend += (SymbolAddress - BD->getAddress());
2980 SymbolAddress = BD->getAddress();
2981 assert(Address == SymbolAddress + Addend);
2982 } else {
2983 // These are mostly local data symbols but undefined symbols
2984 // in relocation sections can get through here too, from .plt.
2985 assert(
2986 (IsAArch64 || BC->isRISCV() || IsSectionRelocation ||
2987 BC->getSectionNameForAddress(SymbolAddress)->starts_with(".plt")) &&
2988 "known symbols should not resolve to anonymous locals");
2989
2990 if (IsSectionRelocation) {
2991 ReferencedSymbol =
2992 BC->getOrCreateGlobalSymbol(Address: SymbolAddress, Prefix: "SYMBOLat");
2993 } else {
2994 SymbolRef Symbol = *Rel.getSymbol();
2995 const uint64_t SymbolSize =
2996 IsAArch64 ? 0 : ELFSymbolRef(Symbol).getSize();
2997 const uint64_t SymbolAlignment = IsAArch64 ? 1 : Symbol.getAlignment();
2998 const uint32_t SymbolFlags = cantFail(ValOrErr: Symbol.getFlags());
2999 std::string Name;
3000 if (SymbolFlags & SymbolRef::SF_Global) {
3001 Name = SymbolName;
3002 } else {
3003 if (StringRef(SymbolName)
3004 .starts_with(Prefix: BC->AsmInfo->getPrivateGlobalPrefix()))
3005 Name = NR.uniquify(Name: "PG" + SymbolName);
3006 else
3007 Name = NR.uniquify(Name: SymbolName);
3008 }
3009 ReferencedSymbol = BC->registerNameAtAddress(
3010 Name, Address: SymbolAddress, Size: SymbolSize, Alignment: SymbolAlignment, Flags: SymbolFlags);
3011 }
3012
3013 if (IsSectionRelocation) {
3014 BinaryData *BD = BC->getBinaryDataByName(Name: ReferencedSymbol->getName());
3015 BC->markAmbiguousRelocations(BD&: *BD, Address);
3016 }
3017 }
3018 }
3019
3020 auto checkMaxDataRelocations = [&]() {
3021 ++NumDataRelocations;
3022 LLVM_DEBUG(if (opts::MaxDataRelocations &&
3023 NumDataRelocations + 1 == opts::MaxDataRelocations) {
3024 dbgs() << "BOLT-DEBUG: processing ending on data relocation "
3025 << NumDataRelocations << ": ";
3026 printRelocationInfo(Rel, ReferencedSymbol->getName(), SymbolAddress,
3027 Addend, ExtractedValue);
3028 });
3029
3030 return (!opts::MaxDataRelocations ||
3031 NumDataRelocations < opts::MaxDataRelocations);
3032 };
3033
3034 if ((ReferencedSection && refersToReorderedSection(Section: ReferencedSection)) ||
3035 (opts::ForceToDataRelocations && checkMaxDataRelocations()) ||
3036 // RISC-V has ADD/SUB data-to-data relocations
3037 BC->isRISCV())
3038 ForceRelocation = true;
3039
3040 if (IsFromCode)
3041 ContainingBF->addRelocation(Address: Rel.getOffset(), Symbol: ReferencedSymbol, RelType: RType,
3042 Addend, Value: ExtractedValue);
3043 else if (IsToCode || ForceRelocation)
3044 BC->addRelocation(Address: Rel.getOffset(), Symbol: ReferencedSymbol, Type: RType, Addend,
3045 Value: ExtractedValue);
3046 else
3047 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring relocation from data to data\n");
3048}
3049
3050static BinaryFunction *getInitFunctionIfStaticBinary(BinaryContext &BC) {
3051 // Workaround for https://github.com/llvm/llvm-project/issues/100096
3052 // ("[BOLT] GOT array pointer incorrectly rewritten"). In aarch64
3053 // static glibc binaries, the .init section's _init function pointer can
3054 // alias with a data pointer for the end of an array. GOT rewriting
3055 // currently can't detect this and updates the data pointer to the
3056 // moved _init, causing a runtime crash. Skipping _init on the other
3057 // hand should be harmless.
3058 if (!BC.IsStaticExecutable)
3059 return nullptr;
3060 const BinaryData *BD = BC.getBinaryDataByName(Name: "_init");
3061 if (!BD || BD->getSectionName() != ".init")
3062 return nullptr;
3063 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: skip _init in for GOT workaround.\n");
3064 return BC.getBinaryFunctionAtAddress(Address: BD->getAddress());
3065}
3066
3067void RewriteInstance::selectFunctionsToProcess() {
3068 // Extend the list of functions to process or skip from a file.
3069 auto populateFunctionNames = [](cl::opt<std::string> &FunctionNamesFile,
3070 cl::list<std::string> &FunctionNames) {
3071 if (FunctionNamesFile.empty())
3072 return;
3073 std::ifstream FuncsFile(FunctionNamesFile, std::ios::in);
3074 std::string FuncName;
3075 while (std::getline(is&: FuncsFile, str&: FuncName))
3076 FunctionNames.push_back(value: FuncName);
3077 };
3078 populateFunctionNames(opts::FunctionNamesFile, opts::ForceFunctionNames);
3079 populateFunctionNames(opts::SkipFunctionNamesFile, opts::SkipFunctionNames);
3080 populateFunctionNames(opts::FunctionNamesFileNR, opts::ForceFunctionNamesNR);
3081
3082 // Make a set of functions to process to speed up lookups.
3083 std::unordered_set<std::string> ForceFunctionsNR(
3084 opts::ForceFunctionNamesNR.begin(), opts::ForceFunctionNamesNR.end());
3085
3086 if ((!opts::ForceFunctionNames.empty() ||
3087 !opts::ForceFunctionNamesNR.empty()) &&
3088 !opts::SkipFunctionNames.empty()) {
3089 BC->errs()
3090 << "BOLT-ERROR: cannot select functions to process and skip at the "
3091 "same time. Please use only one type of selection.\n";
3092 exit(status: 1);
3093 }
3094
3095 uint64_t LiteThresholdExecCount = 0;
3096 if (opts::LiteThresholdPct) {
3097 if (opts::LiteThresholdPct > 100)
3098 opts::LiteThresholdPct = 100;
3099
3100 std::vector<const BinaryFunction *> TopFunctions;
3101 for (auto &BFI : BC->getBinaryFunctions()) {
3102 const BinaryFunction &Function = BFI.second;
3103 if (ProfileReader->mayHaveProfileData(BF: Function))
3104 TopFunctions.push_back(x: &Function);
3105 }
3106 llvm::sort(
3107 C&: TopFunctions, Comp: [](const BinaryFunction *A, const BinaryFunction *B) {
3108 return A->getKnownExecutionCount() < B->getKnownExecutionCount();
3109 });
3110
3111 size_t Index = TopFunctions.size() * opts::LiteThresholdPct / 100;
3112 if (Index)
3113 --Index;
3114 LiteThresholdExecCount = TopFunctions[Index]->getKnownExecutionCount();
3115 BC->outs() << "BOLT-INFO: limiting processing to functions with at least "
3116 << LiteThresholdExecCount << " invocations\n";
3117 }
3118 LiteThresholdExecCount = std::max(
3119 a: LiteThresholdExecCount, b: static_cast<uint64_t>(opts::LiteThresholdCount));
3120
3121 StringSet<> ReorderFunctionsUserSet;
3122 StringSet<> ReorderFunctionsLTOCommonSet;
3123 if (opts::ReorderFunctions == ReorderFunctions::RT_USER) {
3124 std::vector<std::string> FunctionNames;
3125 BC->logBOLTErrorsAndQuitOnFatal(
3126 E: ReorderFunctions::readFunctionOrderFile(FunctionNames));
3127 for (const std::string &Function : FunctionNames) {
3128 ReorderFunctionsUserSet.insert(key: Function);
3129 if (std::optional<StringRef> LTOCommonName = getLTOCommonName(Name: Function))
3130 ReorderFunctionsLTOCommonSet.insert(key: *LTOCommonName);
3131 }
3132 }
3133
3134 uint64_t NumFunctionsToProcess = 0;
3135 auto mustSkip = [&](const BinaryFunction &Function) {
3136 if (opts::MaxFunctions.getNumOccurrences() &&
3137 NumFunctionsToProcess >= opts::MaxFunctions)
3138 return true;
3139 for (std::string &Name : opts::SkipFunctionNames)
3140 if (Function.hasNameRegex(NameRegex: Name))
3141 return true;
3142
3143 return false;
3144 };
3145
3146 auto shouldProcess = [&](const BinaryFunction &Function) {
3147 if (mustSkip(Function))
3148 return false;
3149
3150 // If the list is not empty, only process functions from the list.
3151 if (!opts::ForceFunctionNames.empty() || !ForceFunctionsNR.empty()) {
3152 // Regex check (-funcs and -funcs-file options).
3153 for (std::string &Name : opts::ForceFunctionNames)
3154 if (Function.hasNameRegex(NameRegex: Name))
3155 return true;
3156
3157 // Non-regex check (-funcs-no-regex and -funcs-file-no-regex).
3158 for (const StringRef Name : Function.getNames())
3159 if (ForceFunctionsNR.count(x: Name.str()))
3160 return true;
3161
3162 return false;
3163 }
3164
3165 if (opts::Lite) {
3166 // Forcibly include functions specified in the -function-order file.
3167 if (opts::ReorderFunctions == ReorderFunctions::RT_USER) {
3168 for (const StringRef Name : Function.getNames())
3169 if (ReorderFunctionsUserSet.contains(key: Name))
3170 return true;
3171 for (const StringRef Name : Function.getNames())
3172 if (std::optional<StringRef> LTOCommonName = getLTOCommonName(Name))
3173 if (ReorderFunctionsLTOCommonSet.contains(key: *LTOCommonName))
3174 return true;
3175 }
3176
3177 if (ProfileReader && !ProfileReader->mayHaveProfileData(BF: Function))
3178 return false;
3179
3180 if (Function.getKnownExecutionCount() < LiteThresholdExecCount)
3181 return false;
3182 }
3183
3184 return true;
3185 };
3186
3187 if (BinaryFunction *Init = getInitFunctionIfStaticBinary(BC&: *BC))
3188 Init->setIgnored();
3189
3190 for (auto &BFI : BC->getBinaryFunctions()) {
3191 BinaryFunction &Function = BFI.second;
3192
3193 // Pseudo functions are explicitly marked by us not to be processed.
3194 if (Function.isPseudo()) {
3195 Function.IsIgnored = true;
3196 Function.HasExternalRefRelocations = true;
3197 continue;
3198 }
3199
3200 // Decide what to do with fragments after parent functions are processed.
3201 if (Function.isFragment())
3202 continue;
3203
3204 if (!shouldProcess(Function)) {
3205 if (opts::Verbosity >= 1) {
3206 BC->outs() << "BOLT-INFO: skipping processing " << Function
3207 << " per user request\n";
3208 }
3209 Function.setIgnored();
3210 } else {
3211 ++NumFunctionsToProcess;
3212 if (opts::MaxFunctions.getNumOccurrences() &&
3213 NumFunctionsToProcess == opts::MaxFunctions)
3214 BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n';
3215 }
3216 }
3217
3218 if (!BC->HasSplitFunctions)
3219 return;
3220
3221 // Fragment overrides:
3222 // - If the fragment must be skipped, then the parent must be skipped as well.
3223 // Otherwise, fragment should follow the parent function:
3224 // - if the parent is skipped, skip fragment,
3225 // - if the parent is processed, process the fragment(s) as well.
3226 for (auto &BFI : BC->getBinaryFunctions()) {
3227 BinaryFunction &Function = BFI.second;
3228 if (!Function.isFragment())
3229 continue;
3230 if (mustSkip(Function)) {
3231 for (BinaryFunction *Parent : Function.ParentFragments) {
3232 if (opts::Verbosity >= 1) {
3233 BC->outs() << "BOLT-INFO: skipping processing " << *Parent
3234 << " together with fragment function\n";
3235 }
3236 Parent->setIgnored();
3237 --NumFunctionsToProcess;
3238 }
3239 Function.setIgnored();
3240 continue;
3241 }
3242
3243 bool IgnoredParent =
3244 llvm::any_of(Range&: Function.ParentFragments, P: [&](BinaryFunction *Parent) {
3245 return Parent->isIgnored();
3246 });
3247 if (IgnoredParent) {
3248 if (opts::Verbosity >= 1) {
3249 BC->outs() << "BOLT-INFO: skipping processing " << Function
3250 << " together with parent function\n";
3251 }
3252 Function.setIgnored();
3253 } else {
3254 ++NumFunctionsToProcess;
3255 if (opts::Verbosity >= 1) {
3256 BC->outs() << "BOLT-INFO: processing " << Function
3257 << " as a sibling of non-ignored function\n";
3258 }
3259 if (opts::MaxFunctions && NumFunctionsToProcess == opts::MaxFunctions)
3260 BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n';
3261 }
3262 }
3263}
3264
3265void RewriteInstance::readDebugInfo() {
3266 NamedRegionTimer T("readDebugInfo", "read debug info", TimerGroupName,
3267 TimerGroupDesc, opts::TimeRewrite);
3268 if (!opts::UpdateDebugSections)
3269 return;
3270
3271 BC->preprocessDebugInfo();
3272}
3273
3274void RewriteInstance::preprocessProfileData() {
3275 if (!ProfileReader)
3276 return;
3277
3278 NamedRegionTimer T("preprocessprofile", "pre-process profile data",
3279 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3280
3281 BC->outs() << "BOLT-INFO: pre-processing profile using "
3282 << ProfileReader->getReaderName() << '\n';
3283
3284 if (BAT->enabledFor(InputFile)) {
3285 BC->outs() << "BOLT-INFO: profile collection done on a binary already "
3286 "processed by BOLT\n";
3287 ProfileReader->setBAT(&*BAT);
3288 }
3289
3290 if (Error E = ProfileReader->preprocessProfile(BC&: *BC))
3291 report_error(Message: "cannot pre-process profile", E: std::move(E));
3292
3293 if (!BC->hasSymbolsWithFileName() && ProfileReader->hasLocalsWithFileName() &&
3294 !opts::AllowStripped) {
3295 BC->errs()
3296 << "BOLT-ERROR: input binary does not have local file symbols "
3297 "but profile data includes function names with embedded file "
3298 "names. It appears that the input binary was stripped while a "
3299 "profiled binary was not. If you know what you are doing and "
3300 "wish to proceed, use -allow-stripped option.\n";
3301 exit(status: 1);
3302 }
3303}
3304
3305void RewriteInstance::initializeMetadataManager() {
3306 if (BC->IsLinuxKernel)
3307 MetadataManager.registerRewriter(Rewriter: createLinuxKernelRewriter(*BC));
3308
3309 MetadataManager.registerRewriter(Rewriter: createBuildIDRewriter(*BC));
3310
3311 MetadataManager.registerRewriter(Rewriter: createPseudoProbeRewriter(*BC));
3312
3313 MetadataManager.registerRewriter(Rewriter: createSDTRewriter(*BC));
3314}
3315
3316void RewriteInstance::processSectionMetadata() {
3317 NamedRegionTimer T("processmetadata-section", "process section metadata",
3318 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3319 initializeMetadataManager();
3320
3321 MetadataManager.runSectionInitializers();
3322}
3323
3324void RewriteInstance::processMetadataPreCFG() {
3325 NamedRegionTimer T("processmetadata-precfg", "process metadata pre-CFG",
3326 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3327 MetadataManager.runInitializersPreCFG();
3328
3329 processProfileDataPreCFG();
3330}
3331
3332void RewriteInstance::processMetadataPostCFG() {
3333 NamedRegionTimer T("processmetadata-postcfg", "process metadata post-CFG",
3334 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3335 MetadataManager.runInitializersPostCFG();
3336}
3337
3338void RewriteInstance::processProfileDataPreCFG() {
3339 if (!ProfileReader)
3340 return;
3341
3342 NamedRegionTimer T("processprofile-precfg", "process profile data pre-CFG",
3343 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3344
3345 if (Error E = ProfileReader->readProfilePreCFG(BC&: *BC))
3346 report_error(Message: "cannot read profile pre-CFG", E: std::move(E));
3347}
3348
3349void RewriteInstance::processProfileData() {
3350 if (!ProfileReader)
3351 return;
3352
3353 NamedRegionTimer T("processprofile", "process profile data", TimerGroupName,
3354 TimerGroupDesc, opts::TimeRewrite);
3355
3356 if (Error E = ProfileReader->readProfile(BC&: *BC))
3357 report_error(Message: "cannot read profile", E: std::move(E));
3358
3359 if (opts::PrintProfile || opts::PrintAll) {
3360 for (auto &BFI : BC->getBinaryFunctions()) {
3361 BinaryFunction &Function = BFI.second;
3362 if (Function.empty())
3363 continue;
3364
3365 Function.print(OS&: BC->outs(), Annotation: "after attaching profile");
3366 }
3367 }
3368
3369 if (!opts::SaveProfile.empty() && !BAT->enabledFor(InputFile)) {
3370 YAMLProfileWriter PW(opts::SaveProfile);
3371 PW.writeProfile(RI: *this);
3372 }
3373 if (opts::AggregateOnly &&
3374 opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML &&
3375 !BAT->enabledFor(InputFile)) {
3376 YAMLProfileWriter PW(opts::OutputFilename);
3377 PW.writeProfile(RI: *this);
3378 }
3379
3380 // Release memory used by profile reader.
3381 ProfileReader.reset();
3382
3383 if (opts::AggregateOnly) {
3384 PrintProgramStats PPS(&*BAT);
3385 BC->logBOLTErrorsAndQuitOnFatal(E: PPS.runOnFunctions(BC&: *BC));
3386 TimerGroup::printAll(OS&: outs());
3387 exit(status: 0);
3388 }
3389}
3390
3391void RewriteInstance::disassembleFunctions() {
3392 NamedRegionTimer T("disassembleFunctions", "disassemble functions",
3393 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3394 for (auto &BFI : BC->getBinaryFunctions()) {
3395 BinaryFunction &Function = BFI.second;
3396
3397 ErrorOr<ArrayRef<uint8_t>> FunctionData = Function.getData();
3398 if (!FunctionData) {
3399 BC->errs() << "BOLT-ERROR: corresponding section is non-executable or "
3400 << "empty for function " << Function << '\n';
3401 exit(status: 1);
3402 }
3403
3404 // Treat zero-sized functions as non-simple ones.
3405 if (Function.getSize() == 0) {
3406 Function.setSimple(false);
3407 continue;
3408 }
3409
3410 // Offset of the function in the file.
3411 const auto *FileBegin =
3412 reinterpret_cast<const uint8_t *>(InputFile->getData().data());
3413 Function.setFileOffset(FunctionData->begin() - FileBegin);
3414
3415 if (!shouldDisassemble(BF: Function)) {
3416 NamedRegionTimer T("scan", "scan functions", "buildfuncs",
3417 "Scan Binary Functions", opts::TimeBuild);
3418 Function.scanExternalRefs();
3419 Function.setSimple(false);
3420 continue;
3421 }
3422
3423 bool DisasmFailed{false};
3424 handleAllErrors(E: Function.disassemble(), Handlers: [&](const BOLTError &E) {
3425 DisasmFailed = true;
3426 if (E.isFatal()) {
3427 E.log(OS&: BC->errs());
3428 exit(status: 1);
3429 }
3430 if (opts::processAllFunctions()) {
3431 BC->errs() << BC->generateBugReportMessage(
3432 Message: "function cannot be properly disassembled. "
3433 "Unable to continue in relocation mode.",
3434 Function);
3435 exit(status: 1);
3436 }
3437 if (opts::Verbosity >= 1)
3438 BC->outs() << "BOLT-INFO: could not disassemble function " << Function
3439 << ". Will ignore.\n";
3440 // Forcefully ignore the function.
3441 Function.scanExternalRefs();
3442 Function.setIgnored();
3443 });
3444
3445 if (DisasmFailed)
3446 continue;
3447
3448 if (opts::PrintAll || opts::PrintDisasm)
3449 Function.print(OS&: BC->outs(), Annotation: "after disassembly");
3450 }
3451
3452 BC->processInterproceduralReferences();
3453 BC->populateJumpTables();
3454
3455 for (auto &BFI : BC->getBinaryFunctions()) {
3456 BinaryFunction &Function = BFI.second;
3457
3458 if (!shouldDisassemble(BF: Function))
3459 continue;
3460
3461 Function.postProcessEntryPoints();
3462 Function.postProcessJumpTables();
3463 }
3464
3465 BC->clearJumpTableTempData();
3466 BC->adjustCodePadding();
3467
3468 for (auto &BFI : BC->getBinaryFunctions()) {
3469 BinaryFunction &Function = BFI.second;
3470
3471 if (!shouldDisassemble(BF: Function))
3472 continue;
3473
3474 if (!Function.isSimple()) {
3475 assert((!BC->HasRelocations || Function.getSize() == 0 ||
3476 Function.hasIndirectTargetToSplitFragment()) &&
3477 "unexpected non-simple function in relocation mode");
3478 continue;
3479 }
3480
3481 // Fill in CFI information for this function
3482 if (!Function.trapsOnEntry() && !CFIRdWrt->fillCFIInfoFor(Function)) {
3483 if (BC->HasRelocations) {
3484 BC->errs() << BC->generateBugReportMessage(Message: "unable to fill CFI.",
3485 Function);
3486 exit(status: 1);
3487 } else {
3488 BC->errs() << "BOLT-WARNING: unable to fill CFI for function "
3489 << Function << ". Skipping.\n";
3490 Function.setSimple(false);
3491 continue;
3492 }
3493 }
3494
3495 // Parse LSDA.
3496 if (Function.getLSDAAddress() != 0 &&
3497 !BC->getFragmentsToSkip().count(x: &Function)) {
3498 ErrorOr<BinarySection &> LSDASection =
3499 BC->getSectionForAddress(Address: Function.getLSDAAddress());
3500 check_error(EC: LSDASection.getError(), Message: "failed to get LSDA section");
3501 ArrayRef<uint8_t> LSDAData = ArrayRef<uint8_t>(
3502 LSDASection->getData(), LSDASection->getContents().size());
3503 BC->logBOLTErrorsAndQuitOnFatal(
3504 E: Function.parseLSDA(LSDAData, LSDAAddress: LSDASection->getAddress()));
3505 }
3506 }
3507}
3508
3509void RewriteInstance::buildFunctionsCFG() {
3510 NamedRegionTimer T("buildCFG", "buildCFG", "buildfuncs",
3511 "Build Binary Functions", opts::TimeBuild);
3512
3513 // Create annotation indices to allow lock-free execution
3514 BC->MIB->getOrCreateAnnotationIndex(Name: "JTIndexReg");
3515 BC->MIB->getOrCreateAnnotationIndex(Name: "NOP");
3516
3517 ParallelUtilities::WorkFuncWithAllocTy WorkFun =
3518 [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId) {
3519 bool HadErrors{false};
3520 handleAllErrors(E: BF.buildCFG(AllocId), Handlers: [&](const BOLTError &E) {
3521 if (!E.getMessage().empty())
3522 E.log(OS&: BC->errs());
3523 if (E.isFatal())
3524 exit(status: 1);
3525 HadErrors = true;
3526 });
3527
3528 if (HadErrors)
3529 return;
3530
3531 if (opts::PrintAll) {
3532 auto L = BC->scopeLock();
3533 BF.print(OS&: BC->outs(), Annotation: "while building cfg");
3534 }
3535 };
3536
3537 ParallelUtilities::PredicateTy SkipPredicate = [&](const BinaryFunction &BF) {
3538 return !shouldDisassemble(BF) || !BF.isSimple();
3539 };
3540
3541 ParallelUtilities::runOnEachFunctionWithUniqueAllocId(
3542 BC&: *BC, SchedPolicy: ParallelUtilities::SchedulingPolicy::SP_INST_LINEAR, WorkFunction: WorkFun,
3543 SkipPredicate, LogName: "disassembleFunctions-buildCFG",
3544 /*ForceSequential*/ opts::SequentialDisassembly || opts::PrintAll);
3545
3546 BC->postProcessSymbolTable();
3547}
3548
3549void RewriteInstance::postProcessFunctions() {
3550 // We mark fragments as non-simple here, not during disassembly,
3551 // So we can build their CFGs.
3552 BC->skipMarkedFragments();
3553 BC->clearFragmentsToSkip();
3554
3555 BC->TotalScore = 0;
3556 BC->SumExecutionCount = 0;
3557 for (auto &BFI : BC->getBinaryFunctions()) {
3558 BinaryFunction &Function = BFI.second;
3559
3560 // Set function as non-simple if it has dynamic relocations
3561 // in constant island, we don't want this function to be optimized
3562 // e.g. function splitting is unsupported.
3563 if (Function.hasDynamicRelocationAtIsland())
3564 Function.setSimple(false);
3565
3566 if (Function.empty())
3567 continue;
3568
3569 Function.postProcessCFG();
3570
3571 if (opts::PrintAll || opts::PrintCFG)
3572 Function.print(OS&: BC->outs(), Annotation: "after building cfg");
3573
3574 if (opts::DumpDotAll)
3575 Function.dumpGraphForPass(Annotation: "00_build-cfg");
3576
3577 if (opts::PrintLoopInfo) {
3578 Function.calculateLoopInfo();
3579 Function.printLoopInfo(OS&: BC->outs());
3580 }
3581
3582 BC->TotalScore += Function.getFunctionScore();
3583 BC->SumExecutionCount += Function.getKnownExecutionCount();
3584 }
3585
3586 if (opts::PrintGlobals) {
3587 BC->outs() << "BOLT-INFO: Global symbols:\n";
3588 BC->printGlobalSymbols(OS&: BC->outs());
3589 }
3590}
3591
3592void RewriteInstance::runOptimizationPasses() {
3593 NamedRegionTimer T("runOptimizationPasses", "run optimization passes",
3594 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3595 BC->logBOLTErrorsAndQuitOnFatal(E: BinaryFunctionPassManager::runAllPasses(BC&: *BC));
3596}
3597
3598void RewriteInstance::runBinaryAnalyses() {
3599 NamedRegionTimer T("runBinaryAnalyses", "run binary analysis passes",
3600 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3601 BinaryFunctionPassManager Manager(*BC);
3602 // FIXME: add a pass that warns about which functions do not have CFG,
3603 // and therefore, analysis is most likely to be less accurate.
3604 using GSK = opts::GadgetScannerKind;
3605 using PAuthScanner = PAuthGadgetScanner::Analysis;
3606
3607 // If no command line option was given, act as if "all" was specified.
3608 bool RunAll = !opts::GadgetScannersToRun.getBits() ||
3609 opts::GadgetScannersToRun.isSet(V: GSK::GS_ALL);
3610
3611 if (RunAll || opts::GadgetScannersToRun.isSet(V: GSK::GS_PAUTH)) {
3612 Manager.registerPass(
3613 Pass: std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/args: false));
3614 } else if (RunAll || opts::GadgetScannersToRun.isSet(V: GSK::GS_PACRET)) {
3615 Manager.registerPass(
3616 Pass: std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/args: true));
3617 }
3618
3619 BC->logBOLTErrorsAndQuitOnFatal(E: Manager.runPasses());
3620}
3621
3622void RewriteInstance::preregisterSections() {
3623 // Preregister sections before emission to set their order in the output.
3624 const unsigned ROFlags = BinarySection::getFlags(/*IsReadOnly*/ true,
3625 /*IsText*/ false,
3626 /*IsAllocatable*/ true);
3627 if (BinarySection *EHFrameSection = getSection(Name: getEHFrameSectionName())) {
3628 // New .eh_frame.
3629 BC->registerOrUpdateSection(Name: getNewSecPrefix() + getEHFrameSectionName(),
3630 ELFType: ELF::SHT_PROGBITS, ELFFlags: ROFlags);
3631 // Fully register a relocatable copy of the original .eh_frame.
3632 BC->registerSection(SectionName: ".relocated.eh_frame", OriginalSection: *EHFrameSection);
3633 }
3634 BC->registerOrUpdateSection(Name: getNewSecPrefix() + ".gcc_except_table",
3635 ELFType: ELF::SHT_PROGBITS, ELFFlags: ROFlags);
3636 BC->registerOrUpdateSection(Name: getNewSecPrefix() + ".rodata", ELFType: ELF::SHT_PROGBITS,
3637 ELFFlags: ROFlags);
3638 BC->registerOrUpdateSection(Name: getNewSecPrefix() + ".rodata.cold",
3639 ELFType: ELF::SHT_PROGBITS, ELFFlags: ROFlags);
3640}
3641
3642void RewriteInstance::emitAndLink() {
3643 NamedRegionTimer T("emitAndLink", "emit and link", TimerGroupName,
3644 TimerGroupDesc, opts::TimeRewrite);
3645
3646 SmallString<0> ObjectBuffer;
3647 raw_svector_ostream OS(ObjectBuffer);
3648
3649 // Implicitly MCObjectStreamer takes ownership of MCAsmBackend (MAB)
3650 // and MCCodeEmitter (MCE). ~MCObjectStreamer() will delete these
3651 // two instances.
3652 std::unique_ptr<MCStreamer> Streamer = BC->createStreamer(OS);
3653
3654 if (EHFrameSection) {
3655 if (opts::UseOldText || opts::StrictMode) {
3656 // The section is going to be regenerated from scratch.
3657 // Empty the contents, but keep the section reference.
3658 EHFrameSection->clearContents();
3659 } else {
3660 // Make .eh_frame relocatable.
3661 relocateEHFrameSection();
3662 }
3663 }
3664
3665 emitBinaryContext(Streamer&: *Streamer, BC&: *BC, OrgSecPrefix: getOrgSecPrefix());
3666
3667 Streamer->finish();
3668 if (Streamer->getContext().hadError()) {
3669 BC->errs() << "BOLT-ERROR: Emission failed.\n";
3670 exit(status: 1);
3671 }
3672
3673 if (opts::KeepTmp) {
3674 SmallString<128> OutObjectPath;
3675 sys::fs::getPotentiallyUniqueTempFileName(Prefix: "output", Suffix: "o", ResultPath&: OutObjectPath);
3676 std::error_code EC;
3677 raw_fd_ostream FOS(OutObjectPath, EC);
3678 check_error(EC, Message: "cannot create output object file");
3679 FOS << ObjectBuffer;
3680 BC->outs()
3681 << "BOLT-INFO: intermediary output object file saved for debugging "
3682 "purposes: "
3683 << OutObjectPath << "\n";
3684 }
3685
3686 ErrorOr<BinarySection &> TextSection =
3687 BC->getUniqueSectionByName(SectionName: BC->getMainCodeSectionName());
3688 if (BC->HasRelocations && TextSection)
3689 BC->renameSection(Section&: *TextSection,
3690 NewName: getOrgSecPrefix() + BC->getMainCodeSectionName());
3691
3692 //////////////////////////////////////////////////////////////////////////////
3693 // Assign addresses to new sections.
3694 //////////////////////////////////////////////////////////////////////////////
3695
3696 // Get output object as ObjectFile.
3697 std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
3698 MemoryBuffer::getMemBuffer(InputData: ObjectBuffer, BufferName: "in-memory object file", RequiresNullTerminator: false);
3699
3700 auto EFMM = std::make_unique<ExecutableFileMemoryManager>(args&: *BC);
3701 EFMM->setNewSecPrefix(getNewSecPrefix());
3702 EFMM->setOrgSecPrefix(getOrgSecPrefix());
3703
3704 Linker = std::make_unique<JITLinkLinker>(args&: *BC, args: std::move(EFMM));
3705 Linker->loadObject(Obj: ObjectMemBuffer->getMemBufferRef(),
3706 MapSections: [this](auto MapSection) { mapFileSections(MapSection); });
3707
3708 // Update output addresses based on the new section map and
3709 // layout. Only do this for the object created by ourselves.
3710 updateOutputValues(Linker: *Linker);
3711
3712 if (opts::UpdateDebugSections) {
3713 DebugInfoRewriter->updateLineTableOffsets(
3714 Asm: static_cast<MCObjectStreamer &>(*Streamer).getAssembler());
3715 }
3716
3717 if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary()) {
3718 StartLinkingRuntimeLib = true;
3719 RtLibrary->link(BC&: *BC, ToolPath, Linker&: *Linker, MapSections: [this](auto MapSection) {
3720 // Map newly registered sections.
3721 this->mapAllocatableSections(MapSection);
3722 });
3723 }
3724
3725 // Once the code is emitted, we can rename function sections to actual
3726 // output sections and de-register sections used for emission.
3727 for (BinaryFunction *Function : BC->getAllBinaryFunctions()) {
3728 ErrorOr<BinarySection &> Section = Function->getCodeSection();
3729 if (Section &&
3730 (Function->getImageAddress() == 0 || Function->getImageSize() == 0))
3731 continue;
3732
3733 // Restore origin section for functions that were emitted or supposed to
3734 // be emitted to patch sections.
3735 if (Section)
3736 BC->deregisterSection(Section&: *Section);
3737 assert(Function->getOriginSectionName() && "expected origin section");
3738 Function->CodeSectionName = Function->getOriginSectionName()->str();
3739 for (const FunctionFragment &FF :
3740 Function->getLayout().getSplitFragments()) {
3741 if (ErrorOr<BinarySection &> ColdSection =
3742 Function->getCodeSection(Fragment: FF.getFragmentNum()))
3743 BC->deregisterSection(Section&: *ColdSection);
3744 }
3745 if (Function->getLayout().isSplit())
3746 Function->setColdCodeSectionName(getBOLTTextSectionName());
3747 }
3748
3749 if (opts::PrintCacheMetrics) {
3750 BC->outs() << "BOLT-INFO: cache metrics after emitting functions:\n";
3751 CacheMetrics::printAll(OS&: BC->outs(), BinaryFunctions: BC->getSortedFunctions());
3752 }
3753}
3754
3755void RewriteInstance::finalizeMetadataPreEmit() {
3756 NamedRegionTimer T("finalizemetadata-preemit", "finalize metadata pre-emit",
3757 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3758 MetadataManager.runFinalizersPreEmit();
3759}
3760
3761void RewriteInstance::updateMetadata() {
3762 NamedRegionTimer T("updatemetadata-postemit", "update metadata post-emit",
3763 TimerGroupName, TimerGroupDesc, opts::TimeRewrite);
3764 MetadataManager.runFinalizersAfterEmit();
3765
3766 if (opts::UpdateDebugSections) {
3767 NamedRegionTimer T("updateDebugInfo", "update debug info", TimerGroupName,
3768 TimerGroupDesc, opts::TimeRewrite);
3769 DebugInfoRewriter->updateDebugInfo();
3770 }
3771
3772 if (opts::WriteBoltInfoSection)
3773 addBoltInfoSection();
3774}
3775
3776void RewriteInstance::mapFileSections(BOLTLinker::SectionMapper MapSection) {
3777 BC->deregisterUnusedSections();
3778
3779 // If no new .eh_frame was written, remove relocated original .eh_frame.
3780 BinarySection *RelocatedEHFrameSection =
3781 getSection(Name: ".relocated" + getEHFrameSectionName());
3782 if (RelocatedEHFrameSection && RelocatedEHFrameSection->hasValidSectionID()) {
3783 BinarySection *NewEHFrameSection =
3784 getSection(Name: getNewSecPrefix() + getEHFrameSectionName());
3785 if (!NewEHFrameSection || !NewEHFrameSection->isFinalized()) {
3786 // JITLink will still have to process relocations for the section, hence
3787 // we need to assign it the address that wouldn't result in relocation
3788 // processing failure.
3789 MapSection(*RelocatedEHFrameSection, NextAvailableAddress);
3790 BC->deregisterSection(Section&: *RelocatedEHFrameSection);
3791 }
3792 }
3793
3794 mapCodeSections(MapSection);
3795
3796 // Map the rest of the sections.
3797 mapAllocatableSections(MapSection);
3798
3799 if (!BC->BOLTReserved.empty()) {
3800 const uint64_t AllocatedSize =
3801 NextAvailableAddress - BC->BOLTReserved.start();
3802 if (BC->BOLTReserved.size() < AllocatedSize) {
3803 BC->errs() << "BOLT-ERROR: reserved space (" << BC->BOLTReserved.size()
3804 << " byte" << (BC->BOLTReserved.size() == 1 ? "" : "s")
3805 << ") is smaller than required for new allocations ("
3806 << AllocatedSize << " bytes)\n";
3807 exit(status: 1);
3808 }
3809 }
3810}
3811
3812std::vector<BinarySection *> RewriteInstance::getCodeSections() {
3813 std::vector<BinarySection *> CodeSections;
3814 for (BinarySection &Section : BC->textSections())
3815 if (Section.hasValidSectionID())
3816 CodeSections.emplace_back(args: &Section);
3817
3818 auto compareSections = [&](const BinarySection *A, const BinarySection *B) {
3819 // If both A and B have names starting with ".text.cold", then
3820 // - if opts::HotFunctionsAtEnd is true, we want order
3821 // ".text.cold.T", ".text.cold.T-1", ... ".text.cold.1", ".text.cold"
3822 // - if opts::HotFunctionsAtEnd is false, we want order
3823 // ".text.cold", ".text.cold.1", ... ".text.cold.T-1", ".text.cold.T"
3824 if (A->getName().starts_with(Prefix: BC->getColdCodeSectionName()) &&
3825 B->getName().starts_with(Prefix: BC->getColdCodeSectionName())) {
3826 if (A->getName().size() != B->getName().size())
3827 return (opts::HotFunctionsAtEnd)
3828 ? (A->getName().size() > B->getName().size())
3829 : (A->getName().size() < B->getName().size());
3830 return (opts::HotFunctionsAtEnd) ? (A->getName() > B->getName())
3831 : (A->getName() < B->getName());
3832 }
3833
3834 // Place movers before anything else.
3835 if (A->getName() == BC->getHotTextMoverSectionName())
3836 return true;
3837 if (B->getName() == BC->getHotTextMoverSectionName())
3838 return false;
3839
3840 // Depending on opts::HotFunctionsAtEnd, place main and warm sections in
3841 // order.
3842 if (opts::HotFunctionsAtEnd) {
3843 if (B->getName() == BC->getMainCodeSectionName())
3844 return true;
3845 if (A->getName() == BC->getMainCodeSectionName())
3846 return false;
3847 return (B->getName() == BC->getWarmCodeSectionName());
3848 } else {
3849 if (A->getName() == BC->getMainCodeSectionName())
3850 return true;
3851 if (B->getName() == BC->getMainCodeSectionName())
3852 return false;
3853 return (A->getName() == BC->getWarmCodeSectionName());
3854 }
3855 };
3856
3857 // Determine the order of sections.
3858 llvm::stable_sort(Range&: CodeSections, C: compareSections);
3859
3860 return CodeSections;
3861}
3862
3863void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
3864 if (!BC->HasRelocations) {
3865 mapCodeSectionsInPlace(MapSection);
3866 return;
3867 }
3868
3869 // Map sections for functions with pre-assigned addresses.
3870 for (BinaryFunction *InjectedFunction : BC->getInjectedBinaryFunctions()) {
3871 const uint64_t OutputAddress = InjectedFunction->getOutputAddress();
3872 if (!OutputAddress)
3873 continue;
3874
3875 ErrorOr<BinarySection &> FunctionSection =
3876 InjectedFunction->getCodeSection();
3877 assert(FunctionSection && "function should have section");
3878 FunctionSection->setOutputAddress(OutputAddress);
3879 MapSection(*FunctionSection, OutputAddress);
3880 InjectedFunction->setImageAddress(FunctionSection->getAllocAddress());
3881 InjectedFunction->setImageSize(FunctionSection->getOutputSize());
3882 }
3883
3884 // Populate the list of sections to be allocated.
3885 std::vector<BinarySection *> CodeSections = getCodeSections();
3886
3887 // Remove sections that were pre-allocated (patch sections).
3888 llvm::erase_if(C&: CodeSections, P: [](BinarySection *Section) {
3889 return Section->getOutputAddress();
3890 });
3891 LLVM_DEBUG(dbgs() << "Code sections in the order of output:\n";
3892 for (const BinarySection *Section : CodeSections) dbgs()
3893 << Section->getName() << '\n';);
3894
3895 uint64_t PaddingSize = 0; // size of padding required at the end
3896
3897 // Allocate sections starting at a given Address.
3898 auto allocateAt = [&](uint64_t Address) {
3899 const char *LastNonColdSectionName = BC->HasWarmSection
3900 ? BC->getWarmCodeSectionName()
3901 : BC->getMainCodeSectionName();
3902 for (BinarySection *Section : CodeSections) {
3903 Address = alignTo(Value: Address, Align: Section->getAlignment());
3904 Section->setOutputAddress(Address);
3905 Address += Section->getOutputSize();
3906
3907 // Hugify: Additional huge page from right side due to
3908 // weird ASLR mapping addresses (4KB aligned)
3909 if (opts::Hugify && !BC->HasFixedLoadAddress &&
3910 Section->getName() == LastNonColdSectionName)
3911 Address = alignTo(Value: Address, Align: Section->getAlignment());
3912 }
3913
3914 // Make sure we allocate enough space for huge pages.
3915 ErrorOr<BinarySection &> TextSection =
3916 BC->getUniqueSectionByName(SectionName: LastNonColdSectionName);
3917 if (opts::HotText && TextSection && TextSection->hasValidSectionID()) {
3918 uint64_t HotTextEnd =
3919 TextSection->getOutputAddress() + TextSection->getOutputSize();
3920 HotTextEnd = alignTo(Value: HotTextEnd, Align: BC->PageAlign);
3921 if (HotTextEnd > Address) {
3922 PaddingSize = HotTextEnd - Address;
3923 Address = HotTextEnd;
3924 }
3925 }
3926 return Address;
3927 };
3928
3929 // Try to allocate sections before the \p Address and return an address for
3930 // the allocation of the first section, or 0 if [0, Address) range is not
3931 // big enough to fit all sections.
3932 auto allocateBefore = [&](uint64_t Address) -> uint64_t {
3933 for (BinarySection *Section : llvm::reverse(C&: CodeSections)) {
3934 if (Section->getOutputSize() > Address)
3935 return 0;
3936 Address -= Section->getOutputSize();
3937 Address = alignDown(Value: Address, Align: Section->getAlignment());
3938 Section->setOutputAddress(Address);
3939 }
3940 return Address;
3941 };
3942
3943 // Check if we can fit code in the original .text
3944 bool AllocationDone = false;
3945 if (opts::UseOldText) {
3946 uint64_t StartAddress;
3947 uint64_t EndAddress;
3948 if (opts::HotFunctionsAtEnd) {
3949 EndAddress = BC->OldTextSectionAddress + BC->OldTextSectionSize;
3950 StartAddress = allocateBefore(EndAddress);
3951 } else {
3952 StartAddress = BC->OldTextSectionAddress;
3953 EndAddress = allocateAt(BC->OldTextSectionAddress);
3954 }
3955
3956 const uint64_t CodeSize = EndAddress - StartAddress;
3957 if (CodeSize <= BC->OldTextSectionSize) {
3958 BC->outs() << "BOLT-INFO: using original .text for new code with 0x"
3959 << Twine::utohexstr(Val: opts::AlignText) << " alignment";
3960 if (StartAddress != BC->OldTextSectionAddress)
3961 BC->outs() << " at 0x" << Twine::utohexstr(Val: StartAddress);
3962 BC->outs() << '\n';
3963 AllocationDone = true;
3964 } else {
3965 BC->errs() << "BOLT-WARNING: original .text too small to fit the new code"
3966 << " using 0x" << Twine::utohexstr(Val: opts::AlignText)
3967 << " alignment. " << CodeSize << " bytes needed, have "
3968 << BC->OldTextSectionSize << " bytes available.\n";
3969 opts::UseOldText = false;
3970 }
3971 }
3972
3973 if (!AllocationDone)
3974 NextAvailableAddress = allocateAt(NextAvailableAddress);
3975
3976 // Do the mapping for ORC layer based on the allocation.
3977 for (BinarySection *Section : CodeSections) {
3978 LLVM_DEBUG(dbgs() << "BOLT: mapping " << Section->getName() << " at 0x"
3979 << Twine::utohexstr(Section->getAllocAddress())
3980 << " to 0x"
3981 << Twine::utohexstr(Section->getOutputAddress()) << '\n');
3982 MapSection(*Section, Section->getOutputAddress());
3983 Section->setOutputFileOffset(
3984 getFileOffsetForAddress(Address: Section->getOutputAddress()));
3985 }
3986
3987 // Check if we need to insert a padding section for hot text.
3988 if (PaddingSize && !opts::UseOldText)
3989 BC->outs() << "BOLT-INFO: padding code to 0x"
3990 << Twine::utohexstr(Val: NextAvailableAddress)
3991 << " to accommodate hot text\n";
3992}
3993
3994void RewriteInstance::mapCodeSectionsInPlace(
3995 BOLTLinker::SectionMapper MapSection) {
3996 // Processing in non-relocation mode.
3997 uint64_t NewTextSectionStartAddress = NextAvailableAddress;
3998
3999 for (auto &BFI : BC->getBinaryFunctions()) {
4000 BinaryFunction &Function = BFI.second;
4001 if (!Function.isEmitted())
4002 continue;
4003
4004 ErrorOr<BinarySection &> FuncSection = Function.getCodeSection();
4005 assert(FuncSection && "cannot find section for function");
4006 FuncSection->setOutputAddress(Function.getAddress());
4007 LLVM_DEBUG(dbgs() << "BOLT: mapping 0x"
4008 << Twine::utohexstr(FuncSection->getAllocAddress())
4009 << " to 0x" << Twine::utohexstr(Function.getAddress())
4010 << '\n');
4011 MapSection(*FuncSection, Function.getAddress());
4012 Function.setImageAddress(FuncSection->getAllocAddress());
4013 Function.setImageSize(FuncSection->getOutputSize());
4014 assert(Function.getImageSize() <= Function.getMaxSize() &&
4015 "Unexpected large function");
4016
4017 if (!Function.isSplit())
4018 continue;
4019
4020 assert(Function.getLayout().isHotColdSplit() &&
4021 "Cannot allocate more than two fragments per function in "
4022 "non-relocation mode.");
4023
4024 FunctionFragment &FF =
4025 Function.getLayout().getFragment(Num: FragmentNum::cold());
4026 ErrorOr<BinarySection &> ColdSection =
4027 Function.getCodeSection(Fragment: FF.getFragmentNum());
4028 assert(ColdSection && "cannot find section for cold part");
4029 // Cold fragments are aligned at 16 bytes.
4030 NextAvailableAddress = alignTo(Value: NextAvailableAddress, Align: 16);
4031 FF.setAddress(NextAvailableAddress);
4032 FF.setImageAddress(ColdSection->getAllocAddress());
4033 FF.setImageSize(ColdSection->getOutputSize());
4034 FF.setFileOffset(getFileOffsetForAddress(Address: NextAvailableAddress));
4035 ColdSection->setOutputAddress(FF.getAddress());
4036
4037 LLVM_DEBUG(
4038 dbgs() << formatv(
4039 "BOLT: mapping cold fragment {0:x+} to {1:x+} with size {2:x+}\n",
4040 FF.getImageAddress(), FF.getAddress(), FF.getImageSize()));
4041 MapSection(*ColdSection, FF.getAddress());
4042
4043 NextAvailableAddress += FF.getImageSize();
4044 }
4045
4046 // Add the new text section aggregating all existing code sections.
4047 // This is pseudo-section that serves a purpose of creating a corresponding
4048 // entry in section header table.
4049 const uint64_t NewTextSectionSize =
4050 NextAvailableAddress - NewTextSectionStartAddress;
4051 if (NewTextSectionSize) {
4052 const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true,
4053 /*IsText=*/true,
4054 /*IsAllocatable=*/true);
4055 BinarySection &Section =
4056 BC->registerOrUpdateSection(Name: getBOLTTextSectionName(),
4057 ELFType: ELF::SHT_PROGBITS,
4058 ELFFlags: Flags,
4059 /*Data=*/nullptr,
4060 Size: NewTextSectionSize,
4061 Alignment: 16);
4062 Section.setOutputAddress(NewTextSectionStartAddress);
4063 Section.setOutputFileOffset(
4064 getFileOffsetForAddress(Address: NewTextSectionStartAddress));
4065 }
4066}
4067
4068void RewriteInstance::mapAllocatableSections(
4069 BOLTLinker::SectionMapper MapSection) {
4070
4071 if (opts::UseOldText || opts::StrictMode) {
4072 auto tryRewriteSection = [&](BinarySection &OldSection,
4073 BinarySection &NewSection) {
4074 if (OldSection.getSize() < NewSection.getOutputSize())
4075 return;
4076
4077 BC->outs() << "BOLT-INFO: rewriting " << OldSection.getName()
4078 << " in-place\n";
4079
4080 NewSection.setOutputAddress(OldSection.getAddress());
4081 NewSection.setOutputFileOffset(OldSection.getInputFileOffset());
4082 MapSection(NewSection, OldSection.getAddress());
4083
4084 // Pad contents with zeros.
4085 NewSection.addPadding(PaddingSize: OldSection.getSize() - NewSection.getOutputSize());
4086
4087 // Prevent the original section name from appearing in the section header
4088 // table.
4089 OldSection.setAnonymous(true);
4090 };
4091
4092 if (EHFrameSection) {
4093 BinarySection *NewEHFrameSection =
4094 getSection(Name: getNewSecPrefix() + getEHFrameSectionName());
4095 assert(NewEHFrameSection && "New contents expected for .eh_frame");
4096 tryRewriteSection(*EHFrameSection, *NewEHFrameSection);
4097 }
4098 BinarySection *EHSection = getSection(Name: ".gcc_except_table");
4099 BinarySection *NewEHSection =
4100 getSection(Name: getNewSecPrefix() + ".gcc_except_table");
4101 if (EHSection) {
4102 assert(NewEHSection && "New contents expected for .gcc_except_table");
4103 tryRewriteSection(*EHSection, *NewEHSection);
4104 }
4105 }
4106
4107 // Allocate read-only sections first, then writable sections.
4108 enum : uint8_t { ST_READONLY, ST_READWRITE };
4109 for (uint8_t SType = ST_READONLY; SType <= ST_READWRITE; ++SType) {
4110 const uint64_t LastNextAvailableAddress = NextAvailableAddress;
4111 if (SType == ST_READWRITE) {
4112 // Align R+W segment to regular page size
4113 NextAvailableAddress = alignTo(Value: NextAvailableAddress, Align: BC->RegularPageSize);
4114 NewWritableSegmentAddress = NextAvailableAddress;
4115 }
4116
4117 for (BinarySection &Section : BC->allocatableSections()) {
4118 if (Section.isLinkOnly())
4119 continue;
4120
4121 if (!Section.hasValidSectionID())
4122 continue;
4123
4124 if (Section.isWritable() == (SType == ST_READONLY))
4125 continue;
4126
4127 if (Section.getOutputAddress()) {
4128 LLVM_DEBUG({
4129 dbgs() << "BOLT-DEBUG: section " << Section.getName()
4130 << " is already mapped at 0x"
4131 << Twine::utohexstr(Section.getOutputAddress()) << '\n';
4132 });
4133 continue;
4134 }
4135
4136 if (Section.hasSectionRef()) {
4137 LLVM_DEBUG({
4138 dbgs() << "BOLT-DEBUG: mapping original section " << Section.getName()
4139 << " to 0x" << Twine::utohexstr(Section.getAddress()) << '\n';
4140 });
4141 Section.setOutputAddress(Section.getAddress());
4142 Section.setOutputFileOffset(Section.getInputFileOffset());
4143 MapSection(Section, Section.getAddress());
4144 } else {
4145 uint64_t Alignment = Section.getAlignment();
4146 if (opts::Instrument && StartLinkingRuntimeLib) {
4147 Alignment = BC->RegularPageSize;
4148 StartLinkingRuntimeLib = false;
4149 }
4150 NextAvailableAddress = alignTo(Value: NextAvailableAddress, Align: Alignment);
4151
4152 LLVM_DEBUG({
4153 dbgs() << "BOLT-DEBUG: mapping section " << Section.getName()
4154 << " (0x" << Twine::utohexstr(Section.getAllocAddress())
4155 << ") to 0x" << Twine::utohexstr(NextAvailableAddress) << ":0x"
4156 << Twine::utohexstr(NextAvailableAddress +
4157 Section.getOutputSize())
4158 << '\n';
4159 });
4160
4161 MapSection(Section, NextAvailableAddress);
4162 Section.setOutputAddress(NextAvailableAddress);
4163 Section.setOutputFileOffset(
4164 getFileOffsetForAddress(Address: NextAvailableAddress));
4165
4166 NextAvailableAddress += Section.getOutputSize();
4167 }
4168 }
4169
4170 if (SType == ST_READONLY) {
4171 if (NewTextSegmentAddress)
4172 NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;
4173 } else if (SType == ST_READWRITE) {
4174 NewWritableSegmentSize = NextAvailableAddress - NewWritableSegmentAddress;
4175 // Restore NextAvailableAddress if no new writable sections
4176 if (!NewWritableSegmentSize)
4177 NextAvailableAddress = LastNextAvailableAddress;
4178 }
4179 }
4180}
4181
4182void RewriteInstance::updateOutputValues(const BOLTLinker &Linker) {
4183 if (std::optional<AddressMap> Map = AddressMap::parse(BC&: *BC))
4184 BC->setIOAddressMap(std::move(*Map));
4185
4186 for (BinaryFunction *Function : BC->getAllBinaryFunctions())
4187 Function->updateOutputValues(Linker);
4188}
4189
4190void RewriteInstance::updateSegmentInfo() {
4191 // NOTE Currently .eh_frame_hdr appends to the last segment, recalculate
4192 // last segments size based on the NextAvailableAddress variable.
4193 if (!NewWritableSegmentSize) {
4194 if (NewTextSegmentAddress)
4195 NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;
4196 } else {
4197 NewWritableSegmentSize = NextAvailableAddress - NewWritableSegmentAddress;
4198 }
4199
4200 if (NewTextSegmentSize) {
4201 SegmentInfo TextSegment = {.Address: NewTextSegmentAddress,
4202 .Size: NewTextSegmentSize,
4203 .FileOffset: NewTextSegmentOffset,
4204 .FileSize: NewTextSegmentSize,
4205 .Alignment: BC->PageAlign,
4206 .IsExecutable: true,
4207 .IsWritable: false};
4208 if (!opts::Instrument) {
4209 BC->NewSegments.push_back(x: TextSegment);
4210 } else {
4211 ErrorOr<BinarySection &> Sec =
4212 BC->getUniqueSectionByName(SectionName: ".bolt.instr.counters");
4213 assert(Sec && "expected one and only one `.bolt.instr.counters` section");
4214 const uint64_t Addr = Sec->getOutputAddress();
4215 const uint64_t Offset = Sec->getOutputFileOffset();
4216 const uint64_t Size = Sec->getOutputSize();
4217 assert(Addr > TextSegment.Address &&
4218 Addr + Size < TextSegment.Address + TextSegment.Size &&
4219 "`.bolt.instr.counters` section is expected to be included in the "
4220 "new text segment");
4221
4222 // Set correct size for the previous header since we are breaking the
4223 // new text segment into three segments.
4224 uint64_t Delta = Addr - TextSegment.Address;
4225 TextSegment.Size = Delta;
4226 TextSegment.FileSize = Delta;
4227 BC->NewSegments.push_back(x: TextSegment);
4228
4229 // Create RW segment that includes the `.bolt.instr.counters` section.
4230 SegmentInfo RWSegment = {.Address: Addr, .Size: Size, .FileOffset: Offset, .FileSize: Size, .Alignment: BC->RegularPageSize,
4231 .IsExecutable: false, .IsWritable: true};
4232 BC->NewSegments.push_back(x: RWSegment);
4233
4234 // Create RX segment that includes all RX sections from runtime library.
4235 const uint64_t AddrRX = alignTo(Value: Addr + Size, Align: BC->RegularPageSize);
4236 const uint64_t OffsetRX = alignTo(Value: Offset + Size, Align: BC->RegularPageSize);
4237 const uint64_t SizeRX =
4238 NewTextSegmentSize - (AddrRX - TextSegment.Address);
4239 SegmentInfo RXSegment = {
4240 .Address: AddrRX, .Size: SizeRX, .FileOffset: OffsetRX, .FileSize: SizeRX, .Alignment: BC->RegularPageSize, .IsExecutable: true, .IsWritable: false};
4241 BC->NewSegments.push_back(x: RXSegment);
4242 }
4243 }
4244
4245 if (NewWritableSegmentSize) {
4246 SegmentInfo DataSegmentInfo = {
4247 .Address: NewWritableSegmentAddress,
4248 .Size: NewWritableSegmentSize,
4249 .FileOffset: getFileOffsetForAddress(Address: NewWritableSegmentAddress),
4250 .FileSize: NewWritableSegmentSize,
4251 .Alignment: BC->RegularPageSize,
4252 .IsExecutable: false,
4253 .IsWritable: true};
4254 BC->NewSegments.push_back(x: DataSegmentInfo);
4255 }
4256}
4257
4258void RewriteInstance::patchELFPHDRTable() {
4259 auto ELF64LEFile = cast<ELF64LEObjectFile>(Val: InputFile);
4260 const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();
4261 raw_fd_ostream &OS = Out->os();
4262
4263 // Write/re-write program headers.
4264 Phnum = Obj.getHeader().e_phnum;
4265 if (PHDRTableOffset) {
4266 // Writing new pheader table and adding one new entry for R+X segment.
4267 Phnum += 1;
4268 if (NewWritableSegmentSize) {
4269 // Adding one more entry for R+W segment.
4270 Phnum += 1;
4271 }
4272 } else {
4273 assert(!PHDRTableAddress && "unexpected address for program header table");
4274 PHDRTableOffset = Obj.getHeader().e_phoff;
4275 if (NewWritableSegmentSize) {
4276 BC->errs() << "BOLT-ERROR: unable to add writable segment\n";
4277 exit(status: 1);
4278 }
4279 }
4280
4281 if (opts::Instrument)
4282 Phnum += 2;
4283
4284 if (BC->NewSegments.empty()) {
4285 BC->outs() << "BOLT-INFO: not adding new segments\n";
4286 return;
4287 }
4288
4289 const uint64_t SavedPos = OS.tell();
4290 OS.seek(off: PHDRTableOffset);
4291
4292 auto createPhdr = [](const SegmentInfo &SI) {
4293 ELF64LEPhdrTy Phdr;
4294 Phdr.p_type = ELF::PT_LOAD;
4295 Phdr.p_offset = SI.FileOffset;
4296 Phdr.p_vaddr = SI.Address;
4297 Phdr.p_paddr = SI.Address;
4298 Phdr.p_filesz = SI.FileSize;
4299 Phdr.p_memsz = SI.Size;
4300 Phdr.p_flags = ELF::PF_R;
4301 if (SI.IsExecutable)
4302 Phdr.p_flags |= ELF::PF_X;
4303 if (SI.IsWritable)
4304 Phdr.p_flags |= ELF::PF_W;
4305 Phdr.p_align = SI.Alignment;
4306
4307 return Phdr;
4308 };
4309
4310 auto writeNewSegmentPhdrs = [&]() {
4311 for (const SegmentInfo &SI : BC->NewSegments) {
4312 ELF64LEPhdrTy Phdr = createPhdr(SI);
4313 OS.write(Ptr: reinterpret_cast<const char *>(&Phdr), Size: sizeof(Phdr));
4314 }
4315 };
4316
4317 bool ModdedGnuStack = false;
4318 bool AddedSegment = false;
4319
4320 // Copy existing program headers with modifications.
4321 for (const ELF64LE::Phdr &Phdr : cantFail(ValOrErr: Obj.program_headers())) {
4322 ELF64LE::Phdr NewPhdr = Phdr;
4323 switch (Phdr.p_type) {
4324 case ELF::PT_PHDR:
4325 if (PHDRTableAddress) {
4326 NewPhdr.p_offset = PHDRTableOffset;
4327 NewPhdr.p_vaddr = PHDRTableAddress;
4328 NewPhdr.p_paddr = PHDRTableAddress;
4329 NewPhdr.p_filesz = sizeof(NewPhdr) * Phnum;
4330 NewPhdr.p_memsz = sizeof(NewPhdr) * Phnum;
4331 }
4332 break;
4333 case ELF::PT_GNU_EH_FRAME: {
4334 ErrorOr<BinarySection &> EHFrameHdrSec = BC->getUniqueSectionByName(
4335 SectionName: getNewSecPrefix() + getEHFrameHdrSectionName());
4336 if (EHFrameHdrSec && EHFrameHdrSec->isAllocatable() &&
4337 EHFrameHdrSec->isFinalized()) {
4338 NewPhdr.p_offset = EHFrameHdrSec->getOutputFileOffset();
4339 NewPhdr.p_vaddr = EHFrameHdrSec->getOutputAddress();
4340 NewPhdr.p_paddr = EHFrameHdrSec->getOutputAddress();
4341 NewPhdr.p_filesz = EHFrameHdrSec->getOutputSize();
4342 NewPhdr.p_memsz = EHFrameHdrSec->getOutputSize();
4343 }
4344 break;
4345 }
4346 case ELF::PT_GNU_STACK:
4347 if (opts::UseGnuStack) {
4348 // Overwrite the header with the new segment header.
4349 assert(BC->NewSegments.size() == 1 &&
4350 "Expected exactly one new segment");
4351 NewPhdr = createPhdr(BC->NewSegments.front());
4352 ModdedGnuStack = true;
4353 }
4354 break;
4355 case ELF::PT_DYNAMIC:
4356 if (!opts::UseGnuStack) {
4357 // Insert new headers before DYNAMIC.
4358 writeNewSegmentPhdrs();
4359 AddedSegment = true;
4360 }
4361 break;
4362 }
4363 OS.write(Ptr: reinterpret_cast<const char *>(&NewPhdr), Size: sizeof(NewPhdr));
4364 }
4365
4366 if (!opts::UseGnuStack && !AddedSegment) {
4367 // Append new headers to the end of the table.
4368 writeNewSegmentPhdrs();
4369 }
4370
4371 if (opts::UseGnuStack && !ModdedGnuStack) {
4372 BC->errs()
4373 << "BOLT-ERROR: could not find PT_GNU_STACK program header to modify\n";
4374 exit(status: 1);
4375 }
4376
4377 OS.seek(off: SavedPos);
4378}
4379
4380namespace {
4381
4382/// Write padding to \p OS such that its current \p Offset becomes aligned
4383/// at \p Alignment. Return new (aligned) offset.
4384uint64_t appendPadding(raw_pwrite_stream &OS, uint64_t Offset,
4385 uint64_t Alignment) {
4386 if (!Alignment)
4387 return Offset;
4388
4389 const uint64_t PaddingSize =
4390 offsetToAlignment(Value: Offset, Alignment: llvm::Align(Alignment));
4391 for (unsigned I = 0; I < PaddingSize; ++I)
4392 OS.write(C: (unsigned char)0);
4393 return Offset + PaddingSize;
4394}
4395
4396}
4397
4398void RewriteInstance::rewriteNoteSections() {
4399 auto ELF64LEFile = cast<ELF64LEObjectFile>(Val: InputFile);
4400 const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();
4401 raw_fd_ostream &OS = Out->os();
4402
4403 uint64_t NextAvailableOffset = std::max(
4404 a: getFileOffsetForAddress(Address: NextAvailableAddress), b: FirstNonAllocatableOffset);
4405 OS.seek(off: NextAvailableOffset);
4406
4407 // Copy over non-allocatable section contents and update file offsets.
4408 for (const ELF64LE::Shdr &Section : cantFail(ValOrErr: Obj.sections())) {
4409 if (Section.sh_type == ELF::SHT_NULL)
4410 continue;
4411 if (Section.sh_flags & ELF::SHF_ALLOC)
4412 continue;
4413
4414 SectionRef SecRef = ELF64LEFile->toSectionRef(Sec: &Section);
4415 BinarySection *BSec = BC->getSectionForSectionRef(Section: SecRef);
4416 assert(BSec && !BSec->isAllocatable() &&
4417 "Matching non-allocatable BinarySection should exist.");
4418
4419 StringRef SectionName =
4420 cantFail(ValOrErr: Obj.getSectionName(Section), Msg: "cannot get section name");
4421 if (shouldStrip(Section, SectionName))
4422 continue;
4423
4424 // Insert padding as needed.
4425 NextAvailableOffset =
4426 appendPadding(OS, Offset: NextAvailableOffset, Alignment: Section.sh_addralign);
4427
4428 // New section size.
4429 uint64_t Size = 0;
4430 bool DataWritten = false;
4431 // Copy over section contents unless it's one of the sections we overwrite.
4432 if (!willOverwriteSection(SectionName)) {
4433 Size = Section.sh_size;
4434 StringRef Dataref = InputFile->getData().substr(Start: Section.sh_offset, N: Size);
4435 std::string Data;
4436 if (BSec->getPatcher()) {
4437 Data = BSec->getPatcher()->patchBinary(BinaryContents: Dataref);
4438 Dataref = StringRef(Data);
4439 }
4440
4441 // Section was expanded, so need to treat it as overwrite.
4442 if (Size != Dataref.size()) {
4443 BSec = &BC->registerOrUpdateNoteSection(
4444 Name: SectionName, Data: copyByteArray(Buffer: Dataref), Size: Dataref.size());
4445 Size = 0;
4446 } else {
4447 OS << Dataref;
4448 DataWritten = true;
4449
4450 // Add padding as the section extension might rely on the alignment.
4451 Size = appendPadding(OS, Offset: Size, Alignment: Section.sh_addralign);
4452 }
4453 }
4454
4455 // Perform section post-processing.
4456 assert(BSec->getAlignment() <= Section.sh_addralign &&
4457 "alignment exceeds value in file");
4458
4459 if (BSec->getAllocAddress()) {
4460 assert(!DataWritten && "Writing section twice.");
4461 (void)DataWritten;
4462 Size += BSec->write(OS);
4463 }
4464
4465 BSec->setOutputFileOffset(NextAvailableOffset);
4466 BSec->flushPendingRelocations(OS, Resolver: [this](const MCSymbol *S) {
4467 return getNewValueForSymbol(Name: S->getName());
4468 });
4469
4470 // Section contents are no longer needed, but we need to update the size so
4471 // that it will be reflected in the section header table.
4472 BSec->updateContents(NewData: nullptr, NewSize: Size);
4473
4474 NextAvailableOffset += Size;
4475 }
4476
4477 // Write new note sections.
4478 for (BinarySection &Section : BC->nonAllocatableSections()) {
4479 if (Section.getOutputFileOffset() || !Section.getAllocAddress())
4480 continue;
4481
4482 assert(!Section.hasPendingRelocations() && "cannot have pending relocs");
4483
4484 NextAvailableOffset =
4485 appendPadding(OS, Offset: NextAvailableOffset, Alignment: Section.getAlignment());
4486 Section.setOutputFileOffset(NextAvailableOffset);
4487
4488 LLVM_DEBUG(
4489 dbgs() << "BOLT-DEBUG: writing out new section " << Section.getName()
4490 << " of size " << Section.getOutputSize() << " at offset 0x"
4491 << Twine::utohexstr(Section.getOutputFileOffset()) << '\n');
4492
4493 NextAvailableOffset += Section.write(OS);
4494 }
4495}
4496
4497template <typename ELFT>
4498void RewriteInstance::finalizeSectionStringTable(ELFObjectFile<ELFT> *File) {
4499 // Pre-populate section header string table.
4500 for (const BinarySection &Section : BC->sections())
4501 if (!Section.isAnonymous())
4502 SHStrTab.add(S: Section.getOutputName());
4503 SHStrTab.finalize();
4504
4505 const size_t SHStrTabSize = SHStrTab.getSize();
4506 uint8_t *DataCopy = new uint8_t[SHStrTabSize];
4507 memset(s: DataCopy, c: 0, n: SHStrTabSize);
4508 SHStrTab.write(Buf: DataCopy);
4509 BC->registerOrUpdateNoteSection(Name: ".shstrtab",
4510 Data: DataCopy,
4511 Size: SHStrTabSize,
4512 /*Alignment=*/1,
4513 /*IsReadOnly=*/true,
4514 ELFType: ELF::SHT_STRTAB);
4515}
4516
4517void RewriteInstance::addBoltInfoSection() {
4518 std::string DescStr;
4519 raw_string_ostream DescOS(DescStr);
4520
4521 DescOS << "BOLT revision: " << BoltRevision << ", "
4522 << "command line:";
4523 for (int I = 0; I < Argc; ++I)
4524 DescOS << " " << Argv[I];
4525
4526 // Encode as GNU GOLD VERSION so it is easily printable by 'readelf -n'
4527 const std::string BoltInfo =
4528 BinarySection::encodeELFNote(NameStr: "GNU", DescStr, Type: 4 /*NT_GNU_GOLD_VERSION*/);
4529 BC->registerOrUpdateNoteSection(Name: ".note.bolt_info", Data: copyByteArray(Buffer: BoltInfo),
4530 Size: BoltInfo.size(),
4531 /*Alignment=*/1,
4532 /*IsReadOnly=*/true, ELFType: ELF::SHT_NOTE);
4533}
4534
4535void RewriteInstance::addBATSection() {
4536 BC->registerOrUpdateNoteSection(Name: BoltAddressTranslation::SECTION_NAME, Data: nullptr,
4537 Size: 0,
4538 /*Alignment=*/1,
4539 /*IsReadOnly=*/true, ELFType: ELF::SHT_NOTE);
4540}
4541
4542void RewriteInstance::encodeBATSection() {
4543 std::string DescStr;
4544 raw_string_ostream DescOS(DescStr);
4545
4546 BAT->write(BC: *BC, OS&: DescOS);
4547
4548 const std::string BoltInfo =
4549 BinarySection::encodeELFNote(NameStr: "BOLT", DescStr, Type: BinarySection::NT_BOLT_BAT);
4550 BC->registerOrUpdateNoteSection(Name: BoltAddressTranslation::SECTION_NAME,
4551 Data: copyByteArray(Buffer: BoltInfo), Size: BoltInfo.size(),
4552 /*Alignment=*/1,
4553 /*IsReadOnly=*/true, ELFType: ELF::SHT_NOTE);
4554 BC->outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size()
4555 << '\n';
4556}
4557
4558template <typename ELFShdrTy>
4559bool RewriteInstance::shouldStrip(const ELFShdrTy &Section,
4560 StringRef SectionName) {
4561 // Strip non-allocatable relocation sections.
4562 if (!(Section.sh_flags & ELF::SHF_ALLOC) && Section.sh_type == ELF::SHT_RELA)
4563 return true;
4564
4565 // Strip debug sections if not updating them.
4566 if (isDebugSection(SectionName) && !opts::UpdateDebugSections)
4567 return true;
4568
4569 // Strip symtab section if needed
4570 if (opts::RemoveSymtab && Section.sh_type == ELF::SHT_SYMTAB)
4571 return true;
4572
4573 return false;
4574}
4575
4576template <typename ELFT>
4577std::vector<typename object::ELFObjectFile<ELFT>::Elf_Shdr>
4578RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File,
4579 std::vector<uint32_t> &NewSectionIndex) {
4580 using ELFShdrTy = typename ELFObjectFile<ELFT>::Elf_Shdr;
4581 const ELFFile<ELFT> &Obj = File->getELFFile();
4582 typename ELFT::ShdrRange Sections = cantFail(Obj.sections());
4583
4584 // Keep track of section header entries attached to the corresponding section.
4585 std::vector<std::pair<BinarySection *, ELFShdrTy>> OutputSections;
4586 auto addSection = [&](const ELFShdrTy &Section, BinarySection &BinSec) {
4587 ELFShdrTy NewSection = Section;
4588 NewSection.sh_name = SHStrTab.getOffset(S: BinSec.getOutputName());
4589 OutputSections.emplace_back(&BinSec, std::move(NewSection));
4590 };
4591
4592 // Copy over entries for original allocatable sections using modified name.
4593 for (const ELFShdrTy &Section : Sections) {
4594 // Always ignore this section.
4595 if (Section.sh_type == ELF::SHT_NULL) {
4596 OutputSections.emplace_back(nullptr, Section);
4597 continue;
4598 }
4599
4600 if (!(Section.sh_flags & ELF::SHF_ALLOC))
4601 continue;
4602
4603 SectionRef SecRef = File->toSectionRef(&Section);
4604 BinarySection *BinSec = BC->getSectionForSectionRef(Section: SecRef);
4605 assert(BinSec && "Matching BinarySection should exist.");
4606
4607 // Exclude anonymous sections.
4608 if (BinSec->isAnonymous())
4609 continue;
4610
4611 addSection(Section, *BinSec);
4612 }
4613
4614 for (BinarySection &Section : BC->allocatableSections()) {
4615 if (!Section.isFinalized())
4616 continue;
4617
4618 if (Section.hasSectionRef() || Section.isAnonymous()) {
4619 if (opts::Verbosity)
4620 BC->outs() << "BOLT-INFO: not writing section header for section "
4621 << Section.getOutputName() << '\n';
4622 continue;
4623 }
4624
4625 if (opts::Verbosity >= 1)
4626 BC->outs() << "BOLT-INFO: writing section header for "
4627 << Section.getOutputName() << '\n';
4628 ELFShdrTy NewSection;
4629 NewSection.sh_type = ELF::SHT_PROGBITS;
4630 NewSection.sh_addr = Section.getOutputAddress();
4631 NewSection.sh_offset = Section.getOutputFileOffset();
4632 NewSection.sh_size = Section.getOutputSize();
4633 NewSection.sh_entsize = 0;
4634 NewSection.sh_flags = Section.getELFFlags();
4635 NewSection.sh_link = 0;
4636 NewSection.sh_info = 0;
4637 NewSection.sh_addralign = Section.getAlignment();
4638 addSection(NewSection, Section);
4639 }
4640
4641 // Sort all allocatable sections by their offset.
4642 llvm::stable_sort(OutputSections, [](const auto &A, const auto &B) {
4643 return A.second.sh_offset < B.second.sh_offset;
4644 });
4645
4646 // Fix section sizes to prevent overlapping.
4647 ELFShdrTy *PrevSection = nullptr;
4648 BinarySection *PrevBinSec = nullptr;
4649 for (auto &SectionKV : OutputSections) {
4650 ELFShdrTy &Section = SectionKV.second;
4651
4652 // Ignore NOBITS sections as they don't take any space in the file.
4653 if (Section.sh_type == ELF::SHT_NOBITS)
4654 continue;
4655
4656 // Note that address continuity is not guaranteed as sections could be
4657 // placed in different loadable segments.
4658 if (PrevSection &&
4659 PrevSection->sh_offset + PrevSection->sh_size > Section.sh_offset) {
4660 if (opts::Verbosity > 1)
4661 BC->outs() << "BOLT-INFO: adjusting size for section "
4662 << PrevBinSec->getOutputName() << '\n';
4663 PrevSection->sh_size = Section.sh_offset - PrevSection->sh_offset;
4664 }
4665
4666 PrevSection = &Section;
4667 PrevBinSec = SectionKV.first;
4668 }
4669
4670 uint64_t LastFileOffset = 0;
4671
4672 // Copy over entries for non-allocatable sections performing necessary
4673 // adjustments.
4674 for (const ELFShdrTy &Section : Sections) {
4675 if (Section.sh_type == ELF::SHT_NULL)
4676 continue;
4677 if (Section.sh_flags & ELF::SHF_ALLOC)
4678 continue;
4679
4680 StringRef SectionName =
4681 cantFail(Obj.getSectionName(Section), "cannot get section name");
4682
4683 if (shouldStrip(Section, SectionName))
4684 continue;
4685
4686 SectionRef SecRef = File->toSectionRef(&Section);
4687 BinarySection *BinSec = BC->getSectionForSectionRef(Section: SecRef);
4688 assert(BinSec && "Matching BinarySection should exist.");
4689
4690 ELFShdrTy NewSection = Section;
4691 NewSection.sh_offset = BinSec->getOutputFileOffset();
4692 NewSection.sh_size = BinSec->getOutputSize();
4693
4694 if (NewSection.sh_type == ELF::SHT_SYMTAB)
4695 NewSection.sh_info = NumLocalSymbols;
4696
4697 addSection(NewSection, *BinSec);
4698
4699 LastFileOffset = BinSec->getOutputFileOffset();
4700 }
4701
4702 // Create entries for new non-allocatable sections.
4703 for (BinarySection &Section : BC->nonAllocatableSections()) {
4704 if (Section.getOutputFileOffset() <= LastFileOffset)
4705 continue;
4706
4707 if (opts::Verbosity >= 1)
4708 BC->outs() << "BOLT-INFO: writing section header for "
4709 << Section.getOutputName() << '\n';
4710
4711 ELFShdrTy NewSection;
4712 NewSection.sh_type = Section.getELFType();
4713 NewSection.sh_addr = 0;
4714 NewSection.sh_offset = Section.getOutputFileOffset();
4715 NewSection.sh_size = Section.getOutputSize();
4716 NewSection.sh_entsize = 0;
4717 NewSection.sh_flags = Section.getELFFlags();
4718 NewSection.sh_link = 0;
4719 NewSection.sh_info = 0;
4720 NewSection.sh_addralign = Section.getAlignment();
4721
4722 addSection(NewSection, Section);
4723 }
4724
4725 // Assign indices to sections.
4726 for (uint32_t Index = 1; Index < OutputSections.size(); ++Index)
4727 OutputSections[Index].first->setIndex(Index);
4728
4729 // Update section index mapping
4730 NewSectionIndex.clear();
4731 NewSectionIndex.resize(Sections.size(), 0);
4732 for (const ELFShdrTy &Section : Sections) {
4733 if (Section.sh_type == ELF::SHT_NULL)
4734 continue;
4735
4736 size_t OrgIndex = std::distance(Sections.begin(), &Section);
4737
4738 SectionRef SecRef = File->toSectionRef(&Section);
4739 BinarySection *BinSec = BC->getSectionForSectionRef(Section: SecRef);
4740 assert(BinSec && "BinarySection should exist for an input section.");
4741
4742 // Some sections are stripped
4743 if (!BinSec->hasValidIndex())
4744 continue;
4745
4746 NewSectionIndex[OrgIndex] = BinSec->getIndex();
4747 }
4748
4749 std::vector<ELFShdrTy> SectionsOnly(OutputSections.size());
4750 llvm::copy(llvm::make_second_range(OutputSections), SectionsOnly.begin());
4751
4752 return SectionsOnly;
4753}
4754
4755// Rewrite section header table inserting new entries as needed. The sections
4756// header table size itself may affect the offsets of other sections,
4757// so we are placing it at the end of the binary.
4758//
4759// As we rewrite entries we need to track how many sections were inserted
4760// as it changes the sh_link value. We map old indices to new ones for
4761// existing sections.
4762template <typename ELFT>
4763void RewriteInstance::patchELFSectionHeaderTable(ELFObjectFile<ELFT> *File) {
4764 using ELFShdrTy = typename ELFObjectFile<ELFT>::Elf_Shdr;
4765 using ELFEhdrTy = typename ELFObjectFile<ELFT>::Elf_Ehdr;
4766 raw_fd_ostream &OS = Out->os();
4767 const ELFFile<ELFT> &Obj = File->getELFFile();
4768
4769 // Mapping from old section indices to new ones
4770 std::vector<uint32_t> NewSectionIndex;
4771 std::vector<ELFShdrTy> OutputSections =
4772 getOutputSections(File, NewSectionIndex);
4773 LLVM_DEBUG(
4774 dbgs() << "BOLT-DEBUG: old to new section index mapping:\n";
4775 for (uint64_t I = 0; I < NewSectionIndex.size(); ++I)
4776 dbgs() << " " << I << " -> " << NewSectionIndex[I] << '\n';
4777 );
4778
4779 // Align starting address for section header table. There's no architecutal
4780 // need to align this, it is just for pleasant human readability.
4781 uint64_t SHTOffset = OS.tell();
4782 SHTOffset = appendPadding(OS, Offset: SHTOffset, Alignment: 16);
4783
4784 // Write all section header entries while patching section references.
4785 for (ELFShdrTy &Section : OutputSections) {
4786 Section.sh_link = NewSectionIndex[Section.sh_link];
4787 if (Section.sh_type == ELF::SHT_REL || Section.sh_type == ELF::SHT_RELA)
4788 Section.sh_info = NewSectionIndex[Section.sh_info];
4789 OS.write(Ptr: reinterpret_cast<const char *>(&Section), Size: sizeof(Section));
4790 }
4791
4792 // Fix ELF header.
4793 ELFEhdrTy NewEhdr = Obj.getHeader();
4794
4795 if (BC->HasRelocations) {
4796 if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary())
4797 NewEhdr.e_entry = RtLibrary->getRuntimeStartAddress();
4798 else
4799 NewEhdr.e_entry = getNewFunctionAddress(OldAddress: NewEhdr.e_entry);
4800 assert((NewEhdr.e_entry || !Obj.getHeader().e_entry) &&
4801 "cannot find new address for entry point");
4802 }
4803 if (PHDRTableOffset) {
4804 NewEhdr.e_phoff = PHDRTableOffset;
4805 NewEhdr.e_phnum = Phnum;
4806 }
4807 NewEhdr.e_shoff = SHTOffset;
4808 NewEhdr.e_shnum = OutputSections.size();
4809 NewEhdr.e_shstrndx = NewSectionIndex[NewEhdr.e_shstrndx];
4810 OS.pwrite(Ptr: reinterpret_cast<const char *>(&NewEhdr), Size: sizeof(NewEhdr), Offset: 0);
4811}
4812
4813template <typename ELFT, typename WriteFuncTy, typename StrTabFuncTy>
4814void RewriteInstance::updateELFSymbolTable(
4815 ELFObjectFile<ELFT> *File, bool IsDynSym,
4816 const typename object::ELFObjectFile<ELFT>::Elf_Shdr &SymTabSection,
4817 const std::vector<uint32_t> &NewSectionIndex, WriteFuncTy Write,
4818 StrTabFuncTy AddToStrTab) {
4819 const ELFFile<ELFT> &Obj = File->getELFFile();
4820 using ELFSymTy = typename ELFObjectFile<ELFT>::Elf_Sym;
4821
4822 StringRef StringSection =
4823 cantFail(Obj.getStringTableForSymtab(SymTabSection));
4824
4825 unsigned NumHotTextSymsUpdated = 0;
4826 unsigned NumHotDataSymsUpdated = 0;
4827
4828 std::map<const BinaryFunction *, uint64_t> IslandSizes;
4829 auto getConstantIslandSize = [&IslandSizes](const BinaryFunction &BF) {
4830 auto Itr = IslandSizes.find(x: &BF);
4831 if (Itr != IslandSizes.end())
4832 return Itr->second;
4833 return IslandSizes[&BF] = BF.estimateConstantIslandSize();
4834 };
4835
4836 // Symbols for the new symbol table.
4837 std::vector<ELFSymTy> Symbols;
4838
4839 bool EmittedColdFileSymbol = false;
4840
4841 auto getNewSectionIndex = [&](uint32_t OldIndex) {
4842 // For dynamic symbol table, the section index could be wrong on the input,
4843 // and its value is ignored by the runtime if it's different from
4844 // SHN_UNDEF and SHN_ABS.
4845 // However, we still need to update dynamic symbol table, so return a
4846 // section index, even though the index is broken.
4847 if (IsDynSym && OldIndex >= NewSectionIndex.size())
4848 return OldIndex;
4849
4850 assert(OldIndex < NewSectionIndex.size() && "section index out of bounds");
4851 const uint32_t NewIndex = NewSectionIndex[OldIndex];
4852
4853 // We may have stripped the section that dynsym was referencing due to
4854 // the linker bug. In that case return the old index avoiding marking
4855 // the symbol as undefined.
4856 if (IsDynSym && NewIndex != OldIndex && NewIndex == ELF::SHN_UNDEF)
4857 return OldIndex;
4858 return NewIndex;
4859 };
4860
4861 // Get the extra symbol name of a split fragment; used in addExtraSymbols.
4862 auto getSplitSymbolName = [&](const FunctionFragment &FF,
4863 const ELFSymTy &FunctionSymbol) {
4864 SmallString<256> SymbolName;
4865 if (BC->HasWarmSection)
4866 SymbolName =
4867 formatv("{0}.{1}", cantFail(FunctionSymbol.getName(StringSection)),
4868 FF.getFragmentNum() == FragmentNum::warm() ? "warm" : "cold");
4869 else
4870 SymbolName = formatv("{0}.cold.{1}",
4871 cantFail(FunctionSymbol.getName(StringSection)),
4872 FF.getFragmentNum().get() - 1);
4873 return SymbolName;
4874 };
4875
4876 // Add extra symbols for the function.
4877 //
4878 // Note that addExtraSymbols() could be called multiple times for the same
4879 // function with different FunctionSymbol matching the main function entry
4880 // point.
4881 auto addExtraSymbols = [&](const BinaryFunction &Function,
4882 const ELFSymTy &FunctionSymbol) {
4883 if (Function.isFolded()) {
4884 BinaryFunction *ICFParent = Function.getFoldedIntoFunction();
4885 while (ICFParent->isFolded())
4886 ICFParent = ICFParent->getFoldedIntoFunction();
4887 ELFSymTy ICFSymbol = FunctionSymbol;
4888 SmallVector<char, 256> Buf;
4889 ICFSymbol.st_name =
4890 AddToStrTab(Twine(cantFail(FunctionSymbol.getName(StringSection)))
4891 .concat(Suffix: ".icf.0")
4892 .toStringRef(Out&: Buf));
4893 ICFSymbol.st_value = ICFParent->getOutputAddress();
4894 ICFSymbol.st_size = ICFParent->getOutputSize();
4895 ICFSymbol.st_shndx = ICFParent->getCodeSection()->getIndex();
4896 Symbols.emplace_back(ICFSymbol);
4897 }
4898 if (Function.isSplit()) {
4899 // Prepend synthetic FILE symbol to prevent local cold fragments from
4900 // colliding with existing symbols with the same name.
4901 if (!EmittedColdFileSymbol &&
4902 FunctionSymbol.getBinding() == ELF::STB_GLOBAL) {
4903 ELFSymTy FileSymbol;
4904 FileSymbol.st_shndx = ELF::SHN_ABS;
4905 FileSymbol.st_name = AddToStrTab(getBOLTFileSymbolName());
4906 FileSymbol.st_value = 0;
4907 FileSymbol.st_size = 0;
4908 FileSymbol.st_other = 0;
4909 FileSymbol.setBindingAndType(ELF::STB_LOCAL, ELF::STT_FILE);
4910 Symbols.emplace_back(FileSymbol);
4911 EmittedColdFileSymbol = true;
4912 }
4913 for (const FunctionFragment &FF :
4914 Function.getLayout().getSplitFragments()) {
4915 if (FF.getAddress()) {
4916 ELFSymTy NewColdSym = FunctionSymbol;
4917 const SmallString<256> SymbolName =
4918 getSplitSymbolName(FF, FunctionSymbol);
4919 NewColdSym.st_name = AddToStrTab(SymbolName);
4920 NewColdSym.st_shndx =
4921 Function.getCodeSection(Fragment: FF.getFragmentNum())->getIndex();
4922 NewColdSym.st_value = FF.getAddress();
4923 NewColdSym.st_size = FF.getImageSize();
4924 NewColdSym.setBindingAndType(ELF::STB_LOCAL, ELF::STT_FUNC);
4925 Symbols.emplace_back(NewColdSym);
4926 }
4927 }
4928 }
4929 if (Function.hasConstantIsland()) {
4930 uint64_t DataMark = Function.getOutputDataAddress();
4931 uint64_t CISize = getConstantIslandSize(Function);
4932 uint64_t CodeMark = DataMark + CISize;
4933 ELFSymTy DataMarkSym = FunctionSymbol;
4934 DataMarkSym.st_name = AddToStrTab("$d");
4935 DataMarkSym.st_value = DataMark;
4936 DataMarkSym.st_size = 0;
4937 DataMarkSym.setType(ELF::STT_NOTYPE);
4938 DataMarkSym.setBinding(ELF::STB_LOCAL);
4939 ELFSymTy CodeMarkSym = DataMarkSym;
4940 CodeMarkSym.st_name = AddToStrTab("$x");
4941 CodeMarkSym.st_value = CodeMark;
4942 Symbols.emplace_back(DataMarkSym);
4943 Symbols.emplace_back(CodeMarkSym);
4944 }
4945 if (Function.hasConstantIsland() && Function.isSplit()) {
4946 uint64_t DataMark = Function.getOutputColdDataAddress();
4947 uint64_t CISize = getConstantIslandSize(Function);
4948 uint64_t CodeMark = DataMark + CISize;
4949 ELFSymTy DataMarkSym = FunctionSymbol;
4950 DataMarkSym.st_name = AddToStrTab("$d");
4951 DataMarkSym.st_value = DataMark;
4952 DataMarkSym.st_size = 0;
4953 DataMarkSym.setType(ELF::STT_NOTYPE);
4954 DataMarkSym.setBinding(ELF::STB_LOCAL);
4955 ELFSymTy CodeMarkSym = DataMarkSym;
4956 CodeMarkSym.st_name = AddToStrTab("$x");
4957 CodeMarkSym.st_value = CodeMark;
4958 Symbols.emplace_back(DataMarkSym);
4959 Symbols.emplace_back(CodeMarkSym);
4960 }
4961 };
4962
4963 // For regular (non-dynamic) symbol table, exclude symbols referring
4964 // to non-allocatable sections.
4965 auto shouldStrip = [&](const ELFSymTy &Symbol) {
4966 if (Symbol.isAbsolute() || !Symbol.isDefined())
4967 return false;
4968
4969 // If we cannot link the symbol to a section, leave it as is.
4970 Expected<const typename ELFT::Shdr *> Section =
4971 Obj.getSection(Symbol.st_shndx);
4972 if (!Section)
4973 return false;
4974
4975 // Remove the section symbol iif the corresponding section was stripped.
4976 if (Symbol.getType() == ELF::STT_SECTION) {
4977 if (!getNewSectionIndex(Symbol.st_shndx))
4978 return true;
4979 return false;
4980 }
4981
4982 // Symbols in non-allocatable sections are typically remnants of relocations
4983 // emitted under "-emit-relocs" linker option. Delete those as we delete
4984 // relocations against non-allocatable sections.
4985 if (!((*Section)->sh_flags & ELF::SHF_ALLOC))
4986 return true;
4987
4988 return false;
4989 };
4990
4991 for (const ELFSymTy &Symbol : cantFail(Obj.symbols(&SymTabSection))) {
4992 // For regular (non-dynamic) symbol table strip unneeded symbols.
4993 if (!IsDynSym && shouldStrip(Symbol))
4994 continue;
4995
4996 const BinaryFunction *Function =
4997 BC->getBinaryFunctionAtAddress(Symbol.st_value);
4998 // Ignore false function references, e.g. when the section address matches
4999 // the address of the function.
5000 if (Function && Symbol.getType() == ELF::STT_SECTION)
5001 Function = nullptr;
5002
5003 // For non-dynamic symtab, make sure the symbol section matches that of
5004 // the function. It can mismatch e.g. if the symbol is a section marker
5005 // in which case we treat the symbol separately from the function.
5006 // For dynamic symbol table, the section index could be wrong on the input,
5007 // and its value is ignored by the runtime if it's different from
5008 // SHN_UNDEF and SHN_ABS.
5009 if (!IsDynSym && Function &&
5010 Symbol.st_shndx !=
5011 Function->getOriginSection()->getSectionRef().getIndex())
5012 Function = nullptr;
5013
5014 // Create a new symbol based on the existing symbol.
5015 ELFSymTy NewSymbol = Symbol;
5016
5017 // Handle special symbols based on their name.
5018 Expected<StringRef> SymbolName = Symbol.getName(StringSection);
5019 assert(SymbolName && "cannot get symbol name");
5020
5021 auto updateSymbolValue = [&](const StringRef Name,
5022 std::optional<uint64_t> Value = std::nullopt) {
5023 NewSymbol.st_value = Value ? *Value : getNewValueForSymbol(Name);
5024 NewSymbol.st_shndx = ELF::SHN_ABS;
5025 BC->outs() << "BOLT-INFO: setting " << Name << " to 0x"
5026 << Twine::utohexstr(Val: NewSymbol.st_value) << '\n';
5027 };
5028
5029 if (*SymbolName == "__hot_start" || *SymbolName == "__hot_end") {
5030 if (opts::HotText) {
5031 updateSymbolValue(*SymbolName);
5032 ++NumHotTextSymsUpdated;
5033 }
5034 goto registerSymbol;
5035 }
5036
5037 if (*SymbolName == "__hot_data_start" || *SymbolName == "__hot_data_end") {
5038 if (opts::HotData) {
5039 updateSymbolValue(*SymbolName);
5040 ++NumHotDataSymsUpdated;
5041 }
5042 goto registerSymbol;
5043 }
5044
5045 if (*SymbolName == "_end") {
5046 if (NextAvailableAddress > Symbol.st_value)
5047 updateSymbolValue(*SymbolName, NextAvailableAddress);
5048 goto registerSymbol;
5049 }
5050
5051 if (Function) {
5052 // If the symbol matched a function that was not emitted, update the
5053 // corresponding section index but otherwise leave it unchanged.
5054 if (Function->isEmitted()) {
5055 NewSymbol.st_value = Function->getOutputAddress();
5056 NewSymbol.st_size = Function->getOutputSize();
5057 NewSymbol.st_shndx = Function->getCodeSection()->getIndex();
5058 } else if (Symbol.st_shndx < ELF::SHN_LORESERVE) {
5059 NewSymbol.st_shndx = getNewSectionIndex(Symbol.st_shndx);
5060 }
5061
5062 // Add new symbols to the symbol table if necessary.
5063 if (!IsDynSym)
5064 addExtraSymbols(*Function, NewSymbol);
5065 } else {
5066 // Check if the function symbol matches address inside a function, i.e.
5067 // it marks a secondary entry point.
5068 Function =
5069 (Symbol.getType() == ELF::STT_FUNC)
5070 ? BC->getBinaryFunctionContainingAddress(Symbol.st_value,
5071 /*CheckPastEnd=*/false,
5072 /*UseMaxSize=*/true)
5073 : nullptr;
5074
5075 if (Function && Function->isEmitted()) {
5076 assert(Function->getLayout().isHotColdSplit() &&
5077 "Adding symbols based on cold fragment when there are more than "
5078 "2 fragments");
5079 const uint64_t OutputAddress =
5080 Function->translateInputToOutputAddress(Address: Symbol.st_value);
5081
5082 NewSymbol.st_value = OutputAddress;
5083 // Force secondary entry points to have zero size.
5084 NewSymbol.st_size = 0;
5085
5086 // Find fragment containing entrypoint
5087 FunctionLayout::fragment_const_iterator FF = llvm::find_if(
5088 Function->getLayout().fragments(), [&](const FunctionFragment &FF) {
5089 uint64_t Lo = FF.getAddress();
5090 uint64_t Hi = Lo + FF.getImageSize();
5091 return Lo <= OutputAddress && OutputAddress < Hi;
5092 });
5093
5094 if (FF == Function->getLayout().fragment_end()) {
5095 assert(
5096 OutputAddress >= Function->getCodeSection()->getOutputAddress() &&
5097 OutputAddress < (Function->getCodeSection()->getOutputAddress() +
5098 Function->getCodeSection()->getOutputSize()) &&
5099 "Cannot locate fragment containing secondary entrypoint");
5100 FF = Function->getLayout().fragment_begin();
5101 }
5102
5103 NewSymbol.st_shndx =
5104 Function->getCodeSection(Fragment: FF->getFragmentNum())->getIndex();
5105 } else {
5106 // Check if the symbol belongs to moved data object and update it.
5107 BinaryData *BD = opts::ReorderData.empty()
5108 ? nullptr
5109 : BC->getBinaryDataAtAddress(Symbol.st_value);
5110 if (BD && BD->isMoved() && !BD->isJumpTable()) {
5111 assert((!BD->getSize() || !Symbol.st_size ||
5112 Symbol.st_size == BD->getSize()) &&
5113 "sizes must match");
5114
5115 BinarySection &OutputSection = BD->getOutputSection();
5116 assert(OutputSection.getIndex());
5117 LLVM_DEBUG(dbgs()
5118 << "BOLT-DEBUG: moving " << BD->getName() << " from "
5119 << *BC->getSectionNameForAddress(Symbol.st_value) << " ("
5120 << Symbol.st_shndx << ") to " << OutputSection.getName()
5121 << " (" << OutputSection.getIndex() << ")\n");
5122 NewSymbol.st_shndx = OutputSection.getIndex();
5123 NewSymbol.st_value = BD->getOutputAddress();
5124 } else {
5125 // Otherwise just update the section for the symbol.
5126 if (Symbol.st_shndx < ELF::SHN_LORESERVE)
5127 NewSymbol.st_shndx = getNewSectionIndex(Symbol.st_shndx);
5128 }
5129
5130 // Detect local syms in the text section that we didn't update
5131 // and that were preserved by the linker to support relocations against
5132 // .text. Remove them from the symtab.
5133 if (Symbol.getType() == ELF::STT_NOTYPE &&
5134 Symbol.getBinding() == ELF::STB_LOCAL && Symbol.st_size == 0) {
5135 if (BC->getBinaryFunctionContainingAddress(Symbol.st_value,
5136 /*CheckPastEnd=*/false,
5137 /*UseMaxSize=*/true)) {
5138 // Can only delete the symbol if not patching. Such symbols should
5139 // not exist in the dynamic symbol table.
5140 assert(!IsDynSym && "cannot delete symbol");
5141 continue;
5142 }
5143 }
5144 }
5145 }
5146
5147 registerSymbol:
5148 if (IsDynSym)
5149 Write((&Symbol - cantFail(Obj.symbols(&SymTabSection)).begin()) *
5150 sizeof(ELFSymTy),
5151 NewSymbol);
5152 else
5153 Symbols.emplace_back(NewSymbol);
5154 }
5155
5156 if (IsDynSym) {
5157 assert(Symbols.empty());
5158 return;
5159 }
5160
5161 // Add symbols of injected functions
5162 for (BinaryFunction *Function : BC->getInjectedBinaryFunctions()) {
5163 if (Function->isAnonymous())
5164 continue;
5165 ELFSymTy NewSymbol;
5166 BinarySection *OriginSection = Function->getOriginSection();
5167 NewSymbol.st_shndx =
5168 OriginSection
5169 ? getNewSectionIndex(OriginSection->getSectionRef().getIndex())
5170 : Function->getCodeSection()->getIndex();
5171 NewSymbol.st_value = Function->getOutputAddress();
5172 NewSymbol.st_name = AddToStrTab(Function->getOneName());
5173 NewSymbol.st_size = Function->getOutputSize();
5174 NewSymbol.st_other = 0;
5175 NewSymbol.setBindingAndType(ELF::STB_LOCAL, ELF::STT_FUNC);
5176 Symbols.emplace_back(NewSymbol);
5177
5178 if (Function->isSplit()) {
5179 assert(Function->getLayout().isHotColdSplit() &&
5180 "Adding symbols based on cold fragment when there are more than "
5181 "2 fragments");
5182 ELFSymTy NewColdSym = NewSymbol;
5183 NewColdSym.setType(ELF::STT_NOTYPE);
5184 SmallVector<char, 256> Buf;
5185 NewColdSym.st_name = AddToStrTab(
5186 Twine(Function->getPrintName()).concat(Suffix: ".cold.0").toStringRef(Out&: Buf));
5187 const FunctionFragment &ColdFF =
5188 Function->getLayout().getFragment(Num: FragmentNum::cold());
5189 NewColdSym.st_value = ColdFF.getAddress();
5190 NewColdSym.st_size = ColdFF.getImageSize();
5191 Symbols.emplace_back(NewColdSym);
5192 }
5193 }
5194
5195 auto AddSymbol = [&](const StringRef &Name, uint64_t Address) {
5196 if (!Address)
5197 return;
5198
5199 ELFSymTy Symbol;
5200 Symbol.st_value = Address;
5201 Symbol.st_shndx = ELF::SHN_ABS;
5202 Symbol.st_name = AddToStrTab(Name);
5203 Symbol.st_size = 0;
5204 Symbol.st_other = 0;
5205 Symbol.setBindingAndType(ELF::STB_WEAK, ELF::STT_NOTYPE);
5206
5207 BC->outs() << "BOLT-INFO: setting " << Name << " to 0x"
5208 << Twine::utohexstr(Val: Symbol.st_value) << '\n';
5209
5210 Symbols.emplace_back(Symbol);
5211 };
5212
5213 // Add runtime library start and fini address symbols
5214 if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary()) {
5215 AddSymbol("__bolt_runtime_start", RtLibrary->getRuntimeStartAddress());
5216 AddSymbol("__bolt_runtime_fini", RtLibrary->getRuntimeFiniAddress());
5217 }
5218
5219 assert((!NumHotTextSymsUpdated || NumHotTextSymsUpdated == 2) &&
5220 "either none or both __hot_start/__hot_end symbols were expected");
5221 assert((!NumHotDataSymsUpdated || NumHotDataSymsUpdated == 2) &&
5222 "either none or both __hot_data_start/__hot_data_end symbols were "
5223 "expected");
5224
5225 auto AddEmittedSymbol = [&](const StringRef &Name) {
5226 AddSymbol(Name, getNewValueForSymbol(Name));
5227 };
5228
5229 if (opts::HotText && !NumHotTextSymsUpdated) {
5230 AddEmittedSymbol("__hot_start");
5231 AddEmittedSymbol("__hot_end");
5232 }
5233
5234 if (opts::HotData && !NumHotDataSymsUpdated) {
5235 AddEmittedSymbol("__hot_data_start");
5236 AddEmittedSymbol("__hot_data_end");
5237 }
5238
5239 // Put local symbols at the beginning.
5240 llvm::stable_sort(Symbols, [](const ELFSymTy &A, const ELFSymTy &B) {
5241 if (A.getBinding() == ELF::STB_LOCAL && B.getBinding() != ELF::STB_LOCAL)
5242 return true;
5243 return false;
5244 });
5245
5246 for (const ELFSymTy &Symbol : Symbols)
5247 Write(0, Symbol);
5248}
5249
5250template <typename ELFT>
5251void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
5252 const ELFFile<ELFT> &Obj = File->getELFFile();
5253 using ELFShdrTy = typename ELFObjectFile<ELFT>::Elf_Shdr;
5254 using ELFSymTy = typename ELFObjectFile<ELFT>::Elf_Sym;
5255
5256 // Compute a preview of how section indices will change after rewriting, so
5257 // we can properly update the symbol table based on new section indices.
5258 std::vector<uint32_t> NewSectionIndex;
5259 getOutputSections(File, NewSectionIndex);
5260
5261 // Update dynamic symbol table.
5262 const ELFShdrTy *DynSymSection = nullptr;
5263 for (const ELFShdrTy &Section : cantFail(Obj.sections())) {
5264 if (Section.sh_type == ELF::SHT_DYNSYM) {
5265 DynSymSection = &Section;
5266 break;
5267 }
5268 }
5269 assert((DynSymSection || BC->IsStaticExecutable) &&
5270 "dynamic symbol table expected");
5271 if (DynSymSection) {
5272 updateELFSymbolTable(
5273 File,
5274 /*IsDynSym=*/true,
5275 *DynSymSection,
5276 NewSectionIndex,
5277 [&](size_t Offset, const ELFSymTy &Sym) {
5278 Out->os().pwrite(Ptr: reinterpret_cast<const char *>(&Sym),
5279 Size: sizeof(ELFSymTy),
5280 Offset: DynSymSection->sh_offset + Offset);
5281 },
5282 [](StringRef) -> size_t { return 0; });
5283 }
5284
5285 if (opts::RemoveSymtab)
5286 return;
5287
5288 // (re)create regular symbol table.
5289 const ELFShdrTy *SymTabSection = nullptr;
5290 for (const ELFShdrTy &Section : cantFail(Obj.sections())) {
5291 if (Section.sh_type == ELF::SHT_SYMTAB) {
5292 SymTabSection = &Section;
5293 break;
5294 }
5295 }
5296 if (!SymTabSection) {
5297 BC->errs() << "BOLT-WARNING: no symbol table found\n";
5298 return;
5299 }
5300
5301 const ELFShdrTy *StrTabSection =
5302 cantFail(Obj.getSection(SymTabSection->sh_link));
5303 std::string NewContents;
5304 std::string NewStrTab = std::string(
5305 File->getData().substr(StrTabSection->sh_offset, StrTabSection->sh_size));
5306 StringRef SecName = cantFail(Obj.getSectionName(*SymTabSection));
5307 StringRef StrSecName = cantFail(Obj.getSectionName(*StrTabSection));
5308
5309 NumLocalSymbols = 0;
5310 updateELFSymbolTable(
5311 File,
5312 /*IsDynSym=*/false,
5313 *SymTabSection,
5314 NewSectionIndex,
5315 [&](size_t Offset, const ELFSymTy &Sym) {
5316 if (Sym.getBinding() == ELF::STB_LOCAL)
5317 ++NumLocalSymbols;
5318 NewContents.append(s: reinterpret_cast<const char *>(&Sym),
5319 n: sizeof(ELFSymTy));
5320 },
5321 [&](StringRef Str) {
5322 size_t Idx = NewStrTab.size();
5323 NewStrTab.append(str: NameResolver::restore(Name: Str).str());
5324 NewStrTab.append(n: 1, c: '\0');
5325 return Idx;
5326 });
5327
5328 BC->registerOrUpdateNoteSection(Name: SecName,
5329 Data: copyByteArray(Buffer: NewContents),
5330 Size: NewContents.size(),
5331 /*Alignment=*/1,
5332 /*IsReadOnly=*/true,
5333 ELFType: ELF::SHT_SYMTAB);
5334
5335 BC->registerOrUpdateNoteSection(Name: StrSecName,
5336 Data: copyByteArray(Buffer: NewStrTab),
5337 Size: NewStrTab.size(),
5338 /*Alignment=*/1,
5339 /*IsReadOnly=*/true,
5340 ELFType: ELF::SHT_STRTAB);
5341}
5342
5343template <typename ELFT>
5344void RewriteInstance::patchELFAllocatableRelrSection(
5345 ELFObjectFile<ELFT> *File) {
5346 if (!DynamicRelrAddress)
5347 return;
5348
5349 raw_fd_ostream &OS = Out->os();
5350 const uint8_t PSize = BC->AsmInfo->getCodePointerSize();
5351 const uint64_t MaxDelta = ((CHAR_BIT * DynamicRelrEntrySize) - 1) * PSize;
5352
5353 auto FixAddend = [&](const BinarySection &Section, const Relocation &Rel,
5354 uint64_t FileOffset) {
5355 // Fix relocation symbol value in place if no static relocation found
5356 // on the same address. We won't check the BF relocations here since it
5357 // is rare case and no optimization is required.
5358 if (Section.getRelocationAt(Offset: Rel.Offset))
5359 return;
5360
5361 // No fixup needed if symbol address was not changed
5362 const uint64_t Addend = getNewFunctionOrDataAddress(OldAddress: Rel.Addend);
5363 if (!Addend)
5364 return;
5365
5366 OS.pwrite(Ptr: reinterpret_cast<const char *>(&Addend), Size: PSize, Offset: FileOffset);
5367 };
5368
5369 // Fill new relative relocation offsets set
5370 std::set<uint64_t> RelOffsets;
5371 for (const BinarySection &Section : BC->allocatableSections()) {
5372 const uint64_t SectionInputAddress = Section.getAddress();
5373 uint64_t SectionAddress = Section.getOutputAddress();
5374 if (!SectionAddress)
5375 SectionAddress = SectionInputAddress;
5376
5377 for (const Relocation &Rel : Section.dynamicRelocations()) {
5378 if (!Rel.isRelative())
5379 continue;
5380
5381 uint64_t RelOffset =
5382 getNewFunctionOrDataAddress(OldAddress: SectionInputAddress + Rel.Offset);
5383
5384 RelOffset = RelOffset == 0 ? SectionAddress + Rel.Offset : RelOffset;
5385 assert((RelOffset & 1) == 0 && "Wrong relocation offset");
5386 RelOffsets.emplace(args&: RelOffset);
5387 FixAddend(Section, Rel, RelOffset);
5388 }
5389 }
5390
5391 ErrorOr<BinarySection &> Section =
5392 BC->getSectionForAddress(Address: *DynamicRelrAddress);
5393 assert(Section && "cannot get .relr.dyn section");
5394 assert(Section->isRelr() && "Expected section to be SHT_RELR type");
5395 uint64_t RelrDynOffset = Section->getInputFileOffset();
5396 const uint64_t RelrDynEndOffset = RelrDynOffset + Section->getSize();
5397
5398 auto WriteRelr = [&](uint64_t Value) {
5399 if (RelrDynOffset + DynamicRelrEntrySize > RelrDynEndOffset) {
5400 BC->errs() << "BOLT-ERROR: Offset overflow for relr.dyn section\n";
5401 exit(status: 1);
5402 }
5403
5404 OS.pwrite(Ptr: reinterpret_cast<const char *>(&Value), Size: DynamicRelrEntrySize,
5405 Offset: RelrDynOffset);
5406 RelrDynOffset += DynamicRelrEntrySize;
5407 };
5408
5409 for (auto RelIt = RelOffsets.begin(); RelIt != RelOffsets.end();) {
5410 WriteRelr(*RelIt);
5411 uint64_t Base = *RelIt++ + PSize;
5412 while (1) {
5413 uint64_t Bitmap = 0;
5414 for (; RelIt != RelOffsets.end(); ++RelIt) {
5415 const uint64_t Delta = *RelIt - Base;
5416 if (Delta >= MaxDelta || Delta % PSize)
5417 break;
5418
5419 Bitmap |= (1ULL << (Delta / PSize));
5420 }
5421
5422 if (!Bitmap)
5423 break;
5424
5425 WriteRelr((Bitmap << 1) | 1);
5426 Base += MaxDelta;
5427 }
5428 }
5429
5430 // Fill the rest of the section with empty bitmap value
5431 while (RelrDynOffset != RelrDynEndOffset)
5432 WriteRelr(1);
5433}
5434
5435template <typename ELFT>
5436void
5437RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
5438 using Elf_Rela = typename ELFT::Rela;
5439 raw_fd_ostream &OS = Out->os();
5440 const ELFFile<ELFT> &EF = File->getELFFile();
5441
5442 uint64_t RelDynOffset = 0, RelDynEndOffset = 0;
5443 uint64_t RelPltOffset = 0, RelPltEndOffset = 0;
5444
5445 auto setSectionFileOffsets = [&](uint64_t Address, uint64_t &Start,
5446 uint64_t &End) {
5447 ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);
5448 assert(Section && "cannot get relocation section");
5449 Start = Section->getInputFileOffset();
5450 End = Start + Section->getSize();
5451 };
5452
5453 if (!DynamicRelocationsAddress && !PLTRelocationsAddress)
5454 return;
5455
5456 if (DynamicRelocationsAddress)
5457 setSectionFileOffsets(*DynamicRelocationsAddress, RelDynOffset,
5458 RelDynEndOffset);
5459
5460 if (PLTRelocationsAddress)
5461 setSectionFileOffsets(*PLTRelocationsAddress, RelPltOffset,
5462 RelPltEndOffset);
5463
5464 DynamicRelativeRelocationsCount = 0;
5465
5466 auto writeRela = [&OS](const Elf_Rela *RelA, uint64_t &Offset) {
5467 OS.pwrite(Ptr: reinterpret_cast<const char *>(RelA), Size: sizeof(*RelA), Offset);
5468 Offset += sizeof(*RelA);
5469 };
5470
5471 auto writeRelocations = [&](bool PatchRelative) {
5472 for (BinarySection &Section : BC->allocatableSections()) {
5473 const uint64_t SectionInputAddress = Section.getAddress();
5474 uint64_t SectionAddress = Section.getOutputAddress();
5475 if (!SectionAddress)
5476 SectionAddress = SectionInputAddress;
5477
5478 for (const Relocation &Rel : Section.dynamicRelocations()) {
5479 const bool IsRelative = Rel.isRelative();
5480 if (PatchRelative != IsRelative)
5481 continue;
5482
5483 if (IsRelative)
5484 ++DynamicRelativeRelocationsCount;
5485
5486 Elf_Rela NewRelA;
5487 MCSymbol *Symbol = Rel.Symbol;
5488 uint32_t SymbolIdx = 0;
5489 uint64_t Addend = Rel.Addend;
5490 uint64_t RelOffset =
5491 getNewFunctionOrDataAddress(OldAddress: SectionInputAddress + Rel.Offset);
5492
5493 RelOffset = RelOffset == 0 ? SectionAddress + Rel.Offset : RelOffset;
5494 if (Rel.Symbol) {
5495 SymbolIdx = getOutputDynamicSymbolIndex(Symbol);
5496 } else {
5497 // Usually this case is used for R_*_(I)RELATIVE relocations
5498 const uint64_t Address = getNewFunctionOrDataAddress(OldAddress: Addend);
5499 if (Address)
5500 Addend = Address;
5501 }
5502
5503 NewRelA.setSymbolAndType(SymbolIdx, Rel.Type, EF.isMips64EL());
5504 NewRelA.r_offset = RelOffset;
5505 NewRelA.r_addend = Addend;
5506
5507 const bool IsJmpRel = IsJmpRelocation.contains(Val: Rel.Type);
5508 uint64_t &Offset = IsJmpRel ? RelPltOffset : RelDynOffset;
5509 const uint64_t &EndOffset =
5510 IsJmpRel ? RelPltEndOffset : RelDynEndOffset;
5511 if (!Offset || !EndOffset) {
5512 BC->errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n";
5513 exit(status: 1);
5514 }
5515
5516 if (Offset + sizeof(NewRelA) > EndOffset) {
5517 BC->errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n";
5518 exit(status: 1);
5519 }
5520
5521 writeRela(&NewRelA, Offset);
5522 }
5523 }
5524 };
5525
5526 // Place R_*_RELATIVE relocations in RELA section if RELR is not presented.
5527 // The dynamic linker expects all R_*_RELATIVE relocations in RELA
5528 // to be emitted first.
5529 if (!DynamicRelrAddress)
5530 writeRelocations(/* PatchRelative */ true);
5531 writeRelocations(/* PatchRelative */ false);
5532
5533 auto fillNone = [&](uint64_t &Offset, uint64_t EndOffset) {
5534 if (!Offset)
5535 return;
5536
5537 typename ELFObjectFile<ELFT>::Elf_Rela RelA;
5538 RelA.setSymbolAndType(0, Relocation::getNone(), EF.isMips64EL());
5539 RelA.r_offset = 0;
5540 RelA.r_addend = 0;
5541 while (Offset < EndOffset)
5542 writeRela(&RelA, Offset);
5543
5544 assert(Offset == EndOffset && "Unexpected section overflow");
5545 };
5546
5547 // Fill the rest of the sections with R_*_NONE relocations
5548 fillNone(RelDynOffset, RelDynEndOffset);
5549 fillNone(RelPltOffset, RelPltEndOffset);
5550}
5551
5552template <typename ELFT>
5553void RewriteInstance::patchELFGOT(ELFObjectFile<ELFT> *File) {
5554 raw_fd_ostream &OS = Out->os();
5555
5556 SectionRef GOTSection;
5557 for (const SectionRef &Section : File->sections()) {
5558 StringRef SectionName = cantFail(ValOrErr: Section.getName());
5559 if (SectionName == ".got") {
5560 GOTSection = Section;
5561 break;
5562 }
5563 }
5564 if (!GOTSection.getObject()) {
5565 if (!BC->IsStaticExecutable)
5566 BC->errs() << "BOLT-INFO: no .got section found\n";
5567 return;
5568 }
5569
5570 StringRef GOTContents = cantFail(ValOrErr: GOTSection.getContents());
5571 for (const uint64_t *GOTEntry =
5572 reinterpret_cast<const uint64_t *>(GOTContents.data());
5573 GOTEntry < reinterpret_cast<const uint64_t *>(GOTContents.data() +
5574 GOTContents.size());
5575 ++GOTEntry) {
5576 if (uint64_t NewAddress = getNewFunctionAddress(OldAddress: *GOTEntry)) {
5577 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: patching GOT entry 0x"
5578 << Twine::utohexstr(*GOTEntry) << " with 0x"
5579 << Twine::utohexstr(NewAddress) << '\n');
5580 OS.pwrite(Ptr: reinterpret_cast<const char *>(&NewAddress), Size: sizeof(NewAddress),
5581 Offset: reinterpret_cast<const char *>(GOTEntry) -
5582 File->getData().data());
5583 }
5584 }
5585}
5586
5587template <typename ELFT>
5588void RewriteInstance::patchELFDynamic(ELFObjectFile<ELFT> *File) {
5589 if (BC->IsStaticExecutable)
5590 return;
5591
5592 const ELFFile<ELFT> &Obj = File->getELFFile();
5593 raw_fd_ostream &OS = Out->os();
5594
5595 using Elf_Phdr = typename ELFFile<ELFT>::Elf_Phdr;
5596 using Elf_Dyn = typename ELFFile<ELFT>::Elf_Dyn;
5597
5598 // Locate DYNAMIC by looking through program headers.
5599 uint64_t DynamicOffset = 0;
5600 const Elf_Phdr *DynamicPhdr = nullptr;
5601 for (const Elf_Phdr &Phdr : cantFail(Obj.program_headers())) {
5602 if (Phdr.p_type == ELF::PT_DYNAMIC) {
5603 DynamicOffset = Phdr.p_offset;
5604 DynamicPhdr = &Phdr;
5605 assert(Phdr.p_memsz == Phdr.p_filesz && "dynamic sizes should match");
5606 break;
5607 }
5608 }
5609 assert(DynamicPhdr && "missing dynamic in ELF binary");
5610
5611 bool ZNowSet = false;
5612
5613 // Go through all dynamic entries and patch functions addresses with
5614 // new ones.
5615 typename ELFT::DynRange DynamicEntries =
5616 cantFail(Obj.dynamicEntries(), "error accessing dynamic table");
5617 auto DTB = DynamicEntries.begin();
5618 for (const Elf_Dyn &Dyn : DynamicEntries) {
5619 Elf_Dyn NewDE = Dyn;
5620 bool ShouldPatch = true;
5621 switch (Dyn.d_tag) {
5622 default:
5623 ShouldPatch = false;
5624 break;
5625 case ELF::DT_RELACOUNT:
5626 NewDE.d_un.d_val = DynamicRelativeRelocationsCount;
5627 break;
5628 case ELF::DT_INIT:
5629 case ELF::DT_FINI: {
5630 if (BC->HasRelocations) {
5631 if (uint64_t NewAddress = getNewFunctionAddress(OldAddress: Dyn.getPtr())) {
5632 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: patching dynamic entry of type "
5633 << Dyn.getTag() << '\n');
5634 NewDE.d_un.d_ptr = NewAddress;
5635 }
5636 }
5637 RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary();
5638 if (RtLibrary && Dyn.getTag() == ELF::DT_FINI) {
5639 if (uint64_t Addr = RtLibrary->getRuntimeFiniAddress())
5640 NewDE.d_un.d_ptr = Addr;
5641 }
5642 if (RtLibrary && Dyn.getTag() == ELF::DT_INIT && !BC->HasInterpHeader) {
5643 if (auto Addr = RtLibrary->getRuntimeStartAddress()) {
5644 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Set DT_INIT to 0x"
5645 << Twine::utohexstr(Addr) << '\n');
5646 NewDE.d_un.d_ptr = Addr;
5647 }
5648 }
5649 break;
5650 }
5651 case ELF::DT_FLAGS:
5652 if (BC->RequiresZNow) {
5653 NewDE.d_un.d_val |= ELF::DF_BIND_NOW;
5654 ZNowSet = true;
5655 }
5656 break;
5657 case ELF::DT_FLAGS_1:
5658 if (BC->RequiresZNow) {
5659 NewDE.d_un.d_val |= ELF::DF_1_NOW;
5660 ZNowSet = true;
5661 }
5662 break;
5663 }
5664 if (ShouldPatch)
5665 OS.pwrite(Ptr: reinterpret_cast<const char *>(&NewDE), Size: sizeof(NewDE),
5666 Offset: DynamicOffset + (&Dyn - DTB) * sizeof(Dyn));
5667 }
5668
5669 if (BC->RequiresZNow && !ZNowSet) {
5670 BC->errs()
5671 << "BOLT-ERROR: output binary requires immediate relocation "
5672 "processing which depends on DT_FLAGS or DT_FLAGS_1 presence in "
5673 ".dynamic. Please re-link the binary with -znow.\n";
5674 exit(status: 1);
5675 }
5676}
5677
5678template <typename ELFT>
5679Error RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) {
5680 const ELFFile<ELFT> &Obj = File->getELFFile();
5681
5682 using Elf_Phdr = typename ELFFile<ELFT>::Elf_Phdr;
5683 using Elf_Dyn = typename ELFFile<ELFT>::Elf_Dyn;
5684
5685 // Locate DYNAMIC by looking through program headers.
5686 const Elf_Phdr *DynamicPhdr = nullptr;
5687 for (const Elf_Phdr &Phdr : cantFail(Obj.program_headers())) {
5688 if (Phdr.p_type == ELF::PT_DYNAMIC) {
5689 DynamicPhdr = &Phdr;
5690 break;
5691 }
5692 }
5693
5694 if (!DynamicPhdr) {
5695 BC->outs() << "BOLT-INFO: static input executable detected\n";
5696 // TODO: static PIE executable might have dynamic header
5697 BC->IsStaticExecutable = true;
5698 return Error::success();
5699 }
5700
5701 if (DynamicPhdr->p_memsz != DynamicPhdr->p_filesz)
5702 return createStringError(EC: errc::executable_format_error,
5703 S: "dynamic section sizes should match");
5704
5705 // Go through all dynamic entries to locate entries of interest.
5706 auto DynamicEntriesOrErr = Obj.dynamicEntries();
5707 if (!DynamicEntriesOrErr)
5708 return DynamicEntriesOrErr.takeError();
5709 typename ELFT::DynRange DynamicEntries = DynamicEntriesOrErr.get();
5710
5711 for (const Elf_Dyn &Dyn : DynamicEntries) {
5712 switch (Dyn.d_tag) {
5713 case ELF::DT_INIT:
5714 if (!BC->HasInterpHeader) {
5715 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Set start function address\n");
5716 BC->StartFunctionAddress = Dyn.getPtr();
5717 }
5718 break;
5719 case ELF::DT_FINI:
5720 BC->FiniAddress = Dyn.getPtr();
5721 break;
5722 case ELF::DT_FINI_ARRAY:
5723 BC->FiniArrayAddress = Dyn.getPtr();
5724 break;
5725 case ELF::DT_FINI_ARRAYSZ:
5726 BC->FiniArraySize = Dyn.getPtr();
5727 break;
5728 case ELF::DT_RELA:
5729 DynamicRelocationsAddress = Dyn.getPtr();
5730 break;
5731 case ELF::DT_RELASZ:
5732 DynamicRelocationsSize = Dyn.getVal();
5733 break;
5734 case ELF::DT_JMPREL:
5735 PLTRelocationsAddress = Dyn.getPtr();
5736 break;
5737 case ELF::DT_PLTRELSZ:
5738 PLTRelocationsSize = Dyn.getVal();
5739 break;
5740 case ELF::DT_RELACOUNT:
5741 DynamicRelativeRelocationsCount = Dyn.getVal();
5742 break;
5743 case ELF::DT_RELR:
5744 DynamicRelrAddress = Dyn.getPtr();
5745 break;
5746 case ELF::DT_RELRSZ:
5747 DynamicRelrSize = Dyn.getVal();
5748 break;
5749 case ELF::DT_RELRENT:
5750 DynamicRelrEntrySize = Dyn.getVal();
5751 break;
5752 }
5753 }
5754
5755 if (!DynamicRelocationsAddress || !DynamicRelocationsSize) {
5756 DynamicRelocationsAddress.reset();
5757 DynamicRelocationsSize = 0;
5758 }
5759
5760 if (!PLTRelocationsAddress || !PLTRelocationsSize) {
5761 PLTRelocationsAddress.reset();
5762 PLTRelocationsSize = 0;
5763 }
5764
5765 if (!DynamicRelrAddress || !DynamicRelrSize) {
5766 DynamicRelrAddress.reset();
5767 DynamicRelrSize = 0;
5768 } else if (!DynamicRelrEntrySize) {
5769 BC->errs() << "BOLT-ERROR: expected DT_RELRENT to be presented "
5770 << "in DYNAMIC section\n";
5771 exit(status: 1);
5772 } else if (DynamicRelrSize % DynamicRelrEntrySize) {
5773 BC->errs() << "BOLT-ERROR: expected RELR table size to be divisible "
5774 << "by RELR entry size\n";
5775 exit(status: 1);
5776 }
5777
5778 return Error::success();
5779}
5780
5781uint64_t RewriteInstance::getNewFunctionAddress(uint64_t OldAddress) {
5782 const BinaryFunction *Function = BC->getBinaryFunctionAtAddress(Address: OldAddress);
5783 if (!Function)
5784 return 0;
5785
5786 return Function->getOutputAddress();
5787}
5788
5789uint64_t RewriteInstance::getNewFunctionOrDataAddress(uint64_t OldAddress) {
5790 if (uint64_t Function = getNewFunctionAddress(OldAddress))
5791 return Function;
5792
5793 const BinaryData *BD = BC->getBinaryDataAtAddress(Address: OldAddress);
5794 if (BD && BD->isMoved())
5795 return BD->getOutputAddress();
5796
5797 if (const BinaryFunction *BF =
5798 BC->getBinaryFunctionContainingAddress(Address: OldAddress)) {
5799 if (BF->isEmitted()) {
5800 // If OldAddress is the another entry point of
5801 // the function, then BOLT could get the new address.
5802 if (BF->isMultiEntry()) {
5803 for (const BinaryBasicBlock &BB : *BF)
5804 if (BB.isEntryPoint() &&
5805 (BF->getAddress() + BB.getOffset()) == OldAddress)
5806 return BB.getOutputStartAddress();
5807 }
5808 BC->errs() << "BOLT-ERROR: unable to get new address corresponding to "
5809 "input address 0x"
5810 << Twine::utohexstr(Val: OldAddress) << " in function " << *BF
5811 << ". Consider adding this function to --skip-funcs=...\n";
5812 exit(status: 1);
5813 }
5814 }
5815
5816 return 0;
5817}
5818
5819void RewriteInstance::rewriteFile() {
5820 std::error_code EC;
5821 Out = std::make_unique<ToolOutputFile>(args&: opts::OutputFilename, args&: EC,
5822 args: sys::fs::OF_None);
5823 check_error(EC, Message: "cannot create output executable file");
5824
5825 raw_fd_ostream &OS = Out->os();
5826
5827 // Copy allocatable part of the input.
5828 OS << InputFile->getData().substr(Start: 0, N: FirstNonAllocatableOffset);
5829
5830 auto Streamer = BC->createStreamer(OS);
5831 // Make sure output stream has enough reserved space, otherwise
5832 // pwrite() will fail.
5833 uint64_t Offset = std::max(a: getFileOffsetForAddress(Address: NextAvailableAddress),
5834 b: FirstNonAllocatableOffset);
5835 Offset = OS.seek(off: Offset);
5836 assert((Offset != (uint64_t)-1) && "Error resizing output file");
5837
5838 // Overwrite functions with fixed output address. This is mostly used by
5839 // non-relocation mode, with one exception: injected functions are covered
5840 // here in both modes.
5841 uint64_t CountOverwrittenFunctions = 0;
5842 uint64_t OverwrittenScore = 0;
5843 for (BinaryFunction *Function : BC->getAllBinaryFunctions()) {
5844 if (Function->getImageAddress() == 0 || Function->getImageSize() == 0)
5845 continue;
5846
5847 assert(Function->getImageSize() <= Function->getMaxSize() &&
5848 "Unexpected large function");
5849
5850 const auto HasAddress = [](const FunctionFragment &FF) {
5851 return FF.empty() ||
5852 (FF.getImageAddress() != 0 && FF.getImageSize() != 0);
5853 };
5854 const bool SplitFragmentsHaveAddress =
5855 llvm::all_of(Range: Function->getLayout().getSplitFragments(), P: HasAddress);
5856 if (Function->isSplit() && !SplitFragmentsHaveAddress) {
5857 const auto HasNoAddress = [](const FunctionFragment &FF) {
5858 return FF.getImageAddress() == 0 && FF.getImageSize() == 0;
5859 };
5860 assert(llvm::all_of(Function->getLayout().getSplitFragments(),
5861 HasNoAddress) &&
5862 "Some split fragments have an address while others do not");
5863 (void)HasNoAddress;
5864 continue;
5865 }
5866
5867 OverwrittenScore += Function->getFunctionScore();
5868 ++CountOverwrittenFunctions;
5869
5870 // Overwrite function in the output file.
5871 if (opts::Verbosity >= 2)
5872 BC->outs() << "BOLT: rewriting function \"" << *Function << "\"\n";
5873
5874 OS.pwrite(Ptr: reinterpret_cast<char *>(Function->getImageAddress()),
5875 Size: Function->getImageSize(), Offset: Function->getFileOffset());
5876
5877 // Write nops at the end of the function.
5878 if (Function->getMaxSize() != std::numeric_limits<uint64_t>::max()) {
5879 uint64_t Pos = OS.tell();
5880 OS.seek(off: Function->getFileOffset() + Function->getImageSize());
5881 BC->MAB->writeNopData(
5882 OS, Count: Function->getMaxSize() - Function->getImageSize(), STI: &*BC->STI);
5883
5884 OS.seek(off: Pos);
5885 }
5886
5887 if (!Function->isSplit())
5888 continue;
5889
5890 // Write cold part
5891 if (opts::Verbosity >= 2) {
5892 BC->outs() << formatv(Fmt: "BOLT: rewriting function \"{0}\" (split parts)\n",
5893 Vals&: *Function);
5894 }
5895
5896 for (const FunctionFragment &FF :
5897 Function->getLayout().getSplitFragments()) {
5898 OS.pwrite(Ptr: reinterpret_cast<char *>(FF.getImageAddress()),
5899 Size: FF.getImageSize(), Offset: FF.getFileOffset());
5900 }
5901 }
5902
5903 // Print function statistics for non-relocation mode.
5904 if (!BC->HasRelocations) {
5905 BC->outs() << "BOLT: " << CountOverwrittenFunctions << " out of "
5906 << BC->getBinaryFunctions().size()
5907 << " functions were overwritten.\n";
5908 if (BC->TotalScore != 0) {
5909 double Coverage = OverwrittenScore / (double)BC->TotalScore * 100.0;
5910 BC->outs() << format(Fmt: "BOLT-INFO: rewritten functions cover %.2lf",
5911 Vals: Coverage)
5912 << "% of the execution count of simple functions of "
5913 "this binary\n";
5914 }
5915 }
5916
5917 if (BC->HasRelocations && opts::TrapOldCode) {
5918 uint64_t SavedPos = OS.tell();
5919 // Overwrite function body to make sure we never execute these instructions.
5920 for (auto &BFI : BC->getBinaryFunctions()) {
5921 BinaryFunction &BF = BFI.second;
5922 if (!BF.getFileOffset() || !BF.isEmitted())
5923 continue;
5924 OS.seek(off: BF.getFileOffset());
5925 StringRef TrapInstr = BC->MIB->getTrapFillValue();
5926 unsigned NInstr = BF.getMaxSize() / TrapInstr.size();
5927 for (unsigned I = 0; I < NInstr; ++I)
5928 OS.write(Ptr: TrapInstr.data(), Size: TrapInstr.size());
5929 }
5930 OS.seek(off: SavedPos);
5931 }
5932
5933 // Write all allocatable sections - reloc-mode text is written here as well
5934 for (BinarySection &Section : BC->allocatableSections()) {
5935 if (!Section.isFinalized() || !Section.getOutputData()) {
5936 LLVM_DEBUG(if (opts::Verbosity > 1) {
5937 dbgs() << "BOLT-INFO: new section is finalized or !getOutputData, skip "
5938 << Section.getName() << '\n';
5939 });
5940 continue;
5941 }
5942 if (Section.isLinkOnly()) {
5943 LLVM_DEBUG(if (opts::Verbosity > 1) {
5944 dbgs() << "BOLT-INFO: new section is link only, skip "
5945 << Section.getName() << '\n';
5946 });
5947 continue;
5948 }
5949
5950 if (opts::Verbosity >= 1)
5951 BC->outs() << "BOLT: writing new section " << Section.getName()
5952 << "\n data at 0x"
5953 << Twine::utohexstr(Val: Section.getAllocAddress()) << "\n of size "
5954 << Section.getOutputSize() << "\n at offset "
5955 << Section.getOutputFileOffset() << " with content size "
5956 << Section.getOutputContents().size() << '\n';
5957 OS.seek(off: Section.getOutputFileOffset());
5958 Section.write(OS);
5959 }
5960
5961 for (BinarySection &Section : BC->allocatableSections())
5962 Section.flushPendingRelocations(OS, Resolver: [this](const MCSymbol *S) {
5963 return getNewValueForSymbol(Name: S->getName());
5964 });
5965
5966 // If .eh_frame is present create .eh_frame_hdr.
5967 if (EHFrameSection)
5968 writeEHFrameHeader();
5969
5970 // Add BOLT Addresses Translation maps to allow profile collection to
5971 // happen in the output binary
5972 if (opts::EnableBAT)
5973 addBATSection();
5974
5975 // Patch program header table.
5976 if (!BC->IsLinuxKernel) {
5977 updateSegmentInfo();
5978 patchELFPHDRTable();
5979 }
5980
5981 // Finalize memory image of section string table.
5982 finalizeSectionStringTable();
5983
5984 // Update symbol tables.
5985 patchELFSymTabs();
5986
5987 if (opts::EnableBAT)
5988 encodeBATSection();
5989
5990 // Copy non-allocatable sections once allocatable part is finished.
5991 rewriteNoteSections();
5992
5993 if (BC->HasRelocations) {
5994 patchELFAllocatableRelaSections();
5995 patchELFAllocatableRelrSection();
5996 patchELFGOT();
5997 }
5998
5999 // Patch dynamic section/segment.
6000 patchELFDynamic();
6001
6002 // Update ELF book-keeping info.
6003 patchELFSectionHeaderTable();
6004
6005 if (opts::PrintSections) {
6006 BC->outs() << "BOLT-INFO: Sections after processing:\n";
6007 BC->printSections(OS&: BC->outs());
6008 }
6009
6010 Out->keep();
6011 EC = sys::fs::setPermissions(
6012 Path: opts::OutputFilename,
6013 Permissions: static_cast<sys::fs::perms>(sys::fs::perms::all_all &
6014 ~sys::fs::getUmask()));
6015 check_error(EC, Message: "cannot set permissions of output file");
6016}
6017
6018void RewriteInstance::writeEHFrameHeader() {
6019 BinarySection *NewEHFrameSection =
6020 getSection(Name: getNewSecPrefix() + getEHFrameSectionName());
6021
6022 // No need to update the header if no new .eh_frame was created.
6023 if (!NewEHFrameSection)
6024 return;
6025
6026 DWARFDebugFrame NewEHFrame(BC->TheTriple->getArch(), true,
6027 NewEHFrameSection->getOutputAddress());
6028 Error E = NewEHFrame.parse(Data: DWARFDataExtractor(
6029 NewEHFrameSection->getOutputContents(), BC->AsmInfo->isLittleEndian(),
6030 BC->AsmInfo->getCodePointerSize()));
6031 check_error(E: std::move(E), Message: "failed to parse EH frame");
6032
6033 uint64_t RelocatedEHFrameAddress = 0;
6034 StringRef RelocatedEHFrameContents;
6035 BinarySection *RelocatedEHFrameSection =
6036 getSection(Name: ".relocated" + getEHFrameSectionName());
6037 if (RelocatedEHFrameSection) {
6038 RelocatedEHFrameAddress = RelocatedEHFrameSection->getOutputAddress();
6039 RelocatedEHFrameContents = RelocatedEHFrameSection->getOutputContents();
6040 }
6041 DWARFDebugFrame RelocatedEHFrame(BC->TheTriple->getArch(), true,
6042 RelocatedEHFrameAddress);
6043 Error Er = RelocatedEHFrame.parse(Data: DWARFDataExtractor(
6044 RelocatedEHFrameContents, BC->AsmInfo->isLittleEndian(),
6045 BC->AsmInfo->getCodePointerSize()));
6046 check_error(E: std::move(Er), Message: "failed to parse EH frame");
6047
6048 LLVM_DEBUG(dbgs() << "BOLT: writing a new " << getEHFrameHdrSectionName()
6049 << '\n');
6050
6051 // Try to overwrite the original .eh_frame_hdr if the size permits.
6052 uint64_t EHFrameHdrOutputAddress = 0;
6053 uint64_t EHFrameHdrFileOffset = 0;
6054 std::vector<char> NewEHFrameHdr;
6055 BinarySection *OldEHFrameHdrSection = getSection(Name: getEHFrameHdrSectionName());
6056 if (OldEHFrameHdrSection) {
6057 NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(
6058 OldEHFrame: RelocatedEHFrame, NewEHFrame, EHFrameHeaderAddress: OldEHFrameHdrSection->getAddress());
6059 if (NewEHFrameHdr.size() <= OldEHFrameHdrSection->getSize()) {
6060 BC->outs() << "BOLT-INFO: rewriting " << getEHFrameHdrSectionName()
6061 << " in-place\n";
6062 EHFrameHdrOutputAddress = OldEHFrameHdrSection->getAddress();
6063 EHFrameHdrFileOffset = OldEHFrameHdrSection->getInputFileOffset();
6064 } else {
6065 OldEHFrameHdrSection->setOutputName(getOrgSecPrefix() +
6066 getEHFrameHdrSectionName());
6067 OldEHFrameHdrSection = nullptr;
6068 }
6069 }
6070
6071 // If there was not enough space, allocate more memory for .eh_frame_hdr.
6072 if (!OldEHFrameHdrSection) {
6073 NextAvailableAddress =
6074 appendPadding(OS&: Out->os(), Offset: NextAvailableAddress, Alignment: EHFrameHdrAlign);
6075
6076 EHFrameHdrOutputAddress = NextAvailableAddress;
6077 EHFrameHdrFileOffset = getFileOffsetForAddress(Address: NextAvailableAddress);
6078
6079 NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(
6080 OldEHFrame: RelocatedEHFrame, NewEHFrame, EHFrameHeaderAddress: EHFrameHdrOutputAddress);
6081
6082 NextAvailableAddress += NewEHFrameHdr.size();
6083 if (!BC->BOLTReserved.empty() &&
6084 (NextAvailableAddress > BC->BOLTReserved.end())) {
6085 BC->errs() << "BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName()
6086 << " into reserved space\n";
6087 exit(status: 1);
6088 }
6089
6090 // Create a new entry in the section header table.
6091 const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true,
6092 /*IsText=*/false,
6093 /*IsAllocatable=*/true);
6094 BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection(
6095 Name: getNewSecPrefix() + getEHFrameHdrSectionName(), ELFType: ELF::SHT_PROGBITS,
6096 ELFFlags: Flags, Data: nullptr, Size: NewEHFrameHdr.size(), /*Alignment=*/1);
6097 EHFrameHdrSec.setOutputFileOffset(EHFrameHdrFileOffset);
6098 EHFrameHdrSec.setOutputAddress(EHFrameHdrOutputAddress);
6099 EHFrameHdrSec.setOutputName(getEHFrameHdrSectionName());
6100 }
6101
6102 Out->os().seek(off: EHFrameHdrFileOffset);
6103 Out->os().write(Ptr: NewEHFrameHdr.data(), Size: NewEHFrameHdr.size());
6104
6105 // Pad the contents if overwriting in-place.
6106 if (OldEHFrameHdrSection)
6107 Out->os().write_zeros(NumZeros: OldEHFrameHdrSection->getSize() -
6108 NewEHFrameHdr.size());
6109
6110 // Merge new .eh_frame with the relocated original so that gdb can locate all
6111 // FDEs.
6112 if (RelocatedEHFrameSection) {
6113 const uint64_t NewEHFrameSectionSize =
6114 RelocatedEHFrameSection->getOutputAddress() +
6115 RelocatedEHFrameSection->getOutputSize() -
6116 NewEHFrameSection->getOutputAddress();
6117 NewEHFrameSection->updateContents(NewData: NewEHFrameSection->getOutputData(),
6118 NewSize: NewEHFrameSectionSize);
6119 BC->deregisterSection(Section&: *RelocatedEHFrameSection);
6120 }
6121
6122 LLVM_DEBUG(dbgs() << "BOLT-DEBUG: size of .eh_frame after merge is "
6123 << NewEHFrameSection->getOutputSize() << '\n');
6124}
6125
6126uint64_t RewriteInstance::getNewValueForSymbol(const StringRef Name) {
6127 auto Value = Linker->lookupSymbolInfo(Name);
6128 if (Value)
6129 return Value->Address;
6130
6131 // Return the original value if we haven't emitted the symbol.
6132 BinaryData *BD = BC->getBinaryDataByName(Name);
6133 if (!BD)
6134 return 0;
6135
6136 return BD->getAddress();
6137}
6138
6139uint64_t RewriteInstance::getFileOffsetForAddress(uint64_t Address) const {
6140 // Check if it's possibly part of the new segment.
6141 if (NewTextSegmentAddress && Address >= NewTextSegmentAddress)
6142 return Address - NewTextSegmentAddress + NewTextSegmentOffset;
6143
6144 // Find an existing segment that matches the address.
6145 const auto SegmentInfoI = BC->SegmentMapInfo.upper_bound(x: Address);
6146 if (SegmentInfoI == BC->SegmentMapInfo.begin())
6147 return 0;
6148
6149 const SegmentInfo &SegmentInfo = std::prev(x: SegmentInfoI)->second;
6150 if (Address < SegmentInfo.Address ||
6151 Address >= SegmentInfo.Address + SegmentInfo.FileSize)
6152 return 0;
6153
6154 return SegmentInfo.FileOffset + Address - SegmentInfo.Address;
6155}
6156
6157bool RewriteInstance::willOverwriteSection(StringRef SectionName) {
6158 if (llvm::is_contained(Range: SectionsToOverwrite, Element: SectionName))
6159 return true;
6160 if (llvm::is_contained(Range&: DebugSectionsToOverwrite, Element: SectionName))
6161 return true;
6162
6163 ErrorOr<BinarySection &> Section = BC->getUniqueSectionByName(SectionName);
6164 return Section && Section->isAllocatable() && Section->isFinalized();
6165}
6166
6167bool RewriteInstance::isDebugSection(StringRef SectionName) {
6168 if (SectionName.starts_with(Prefix: ".debug_") ||
6169 SectionName.starts_with(Prefix: ".zdebug_") || SectionName == ".gdb_index" ||
6170 SectionName == ".stab" || SectionName == ".stabstr")
6171 return true;
6172
6173 return false;
6174}
6175

source code of bolt/lib/Rewrite/RewriteInstance.cpp