diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index bd96c051d160d..9d514fe258af6 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -6,37 +6,22 @@ // //===----------------------------------------------------------------------===// // -// This file contains platform-independent functions to process relocations. -// I'll describe the overview of this file here. +// This file implements the core relocation processing logic. It analyzes +// relocations and determines what auxiliary data structures (GOT, PLT, copy +// relocations) need to be created during linking. // -// Simple relocations are easy to handle for the linker. For example, -// for R_X86_64_PC64 relocs, the linker just has to fix up locations -// with the relative offsets to the target symbols. It would just be -// reading records from relocation sections and applying them to output. +// The main entry point is scanRelocations(), which calls scanSection() +// to process all relocations within an input section. For each relocation, +// scan() analyzes the type and target, and determines whether a synthetic +// section entry or dynamic relocation is needed. // -// But not all relocations are that easy to handle. For example, for -// R_386_GOTOFF relocs, the linker has to create new GOT entries for -// symbols if they don't exist, and fix up locations with GOT entry -// offsets from the beginning of GOT section. So there is more than -// fixing addresses in relocation processing. +// Note: This file analyzes what needs to be done but doesn't apply the +// actual relocations - that happens later in InputSection::writeTo(). +// Instead, it populates Relocation objects in InputSectionBase::relocations +// and creates necessary synthetic sections (GOT, PLT, etc.). // -// ELF defines a large number of complex relocations. -// -// The functions in this file analyze relocations and do whatever needs -// to be done. It includes, but not limited to, the following. -// -// - create GOT/PLT entries -// - create new relocations in .dynsym to let the dynamic linker resolve -// them at runtime (since ELF supports dynamic linking, not all -// relocations can be resolved at link-time) -// - create COPY relocs and reserve space in .bss -// - replace expensive relocs (in terms of runtime cost) with cheap ones -// - error out infeasible combinations such as PIC and non-relative relocs -// -// Note that the functions in this file don't actually apply relocations -// because it doesn't know about the output file nor the output file buffer. -// It instead stores Relocation objects to InputSection's Relocations -// vector to let it apply later in InputSection::writeTo. +// In addition, this file implements the core Thunk creation logic, called +// during finalizeAddressDependentContent(). // //===----------------------------------------------------------------------===// @@ -466,14 +451,14 @@ class RelocationScanner { int64_t computeMipsAddend(const RelTy &rel, RelExpr expr, bool isLocal) const; bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym, uint64_t relOff) const; - void processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, - int64_t addend) const; + void process(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, + int64_t addend) const; unsigned handleTlsRelocation(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, int64_t addend); template - void scanOne(typename Relocs::const_iterator &i); - template void scan(Relocs rels); + void scan(typename Relocs::const_iterator &i); + template void scanSectionImpl(Relocs rels); }; } // namespace @@ -961,7 +946,7 @@ static bool canDefineSymbolInExecutable(Ctx &ctx, Symbol &sym) { } // Returns true if a given relocation can be computed at link-time. -// This only handles relocation types expected in processAux. +// This only handles relocation types expected in process(). // // For instance, we know the offset from a relocation to its target at // link-time if the relocation is PC-relative and refers a @@ -1052,8 +1037,8 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type, // sections. Given that it is ro, we will need an extra PT_LOAD. This // complicates things for the dynamic linker and means we would have to reserve // space for the extra PT_LOAD even if we end up not using it. -void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset, - Symbol &sym, int64_t addend) const { +void RelocationScanner::process(RelExpr expr, RelType type, uint64_t offset, + Symbol &sym, int64_t addend) const { // If non-ifunc non-preemptible, change PLT to direct call and optimize GOT // indirection. const bool isIfunc = sym.isGnuIFunc(); @@ -1493,7 +1478,7 @@ unsigned RelocationScanner::handleTlsRelocation(RelExpr expr, RelType type, } template -void RelocationScanner::scanOne(typename Relocs::const_iterator &i) { +void RelocationScanner::scan(typename Relocs::const_iterator &i) { const RelTy &rel = *i; uint32_t symIndex = rel.getSymbol(ctx.arg.isMips64EL); Symbol &sym = sec->getFile()->getSymbol(symIndex); @@ -1587,7 +1572,7 @@ void RelocationScanner::scanOne(typename Relocs::const_iterator &i) { } // Process TLS relocations, including TLS optimizations. Note that - // R_TPREL and R_TPREL_NEG relocations are resolved in processAux. + // R_TPREL and R_TPREL_NEG relocations are resolved in process(). // // Some RISCV TLSDESC relocations reference a local NOTYPE symbol, // but we need to process them in handleTlsRelocation. @@ -1599,7 +1584,7 @@ void RelocationScanner::scanOne(typename Relocs::const_iterator &i) { } } - processAux(expr, type, offset, sym, addend); + process(expr, type, offset, sym, addend); } // R_PPC64_TLSGD/R_PPC64_TLSLD is required to mark `bl __tls_get_addr` for @@ -1642,7 +1627,7 @@ static void checkPPC64TLSRelax(InputSectionBase &sec, Relocs rels) { } template -void RelocationScanner::scan(Relocs rels) { +void RelocationScanner::scanSectionImpl(Relocs rels) { // Not all relocations end up in Sec->Relocations, but a lot do. sec->relocations.reserve(rels.size()); @@ -1660,12 +1645,12 @@ void RelocationScanner::scan(Relocs rels) { if constexpr (RelTy::IsCrel) { for (auto i = rels.begin(); i != rels.end();) - scanOne(i); + scan(i); } else { // The non-CREL code path has additional check for PPC64 TLS. end = static_cast(rels.end()); for (auto i = rels.begin(); i != end;) - scanOne(i); + scan(i); } // Sort relocations by offset for more efficient searching for @@ -1686,11 +1671,11 @@ void RelocationScanner::scanSection(InputSectionBase &s, bool isEH) { getter = OffsetGetter(s); const RelsOrRelas rels = s.template relsOrRelas(!isEH); if (rels.areRelocsCrel()) - scan(rels.crels); + scanSectionImpl(rels.crels); else if (rels.areRelocsRel()) - scan(rels.rels); + scanSectionImpl(rels.rels); else - scan(rels.relas); + scanSectionImpl(rels.relas); } template void elf::scanRelocations(Ctx &ctx) {