Relocation in LLD

Reference reference

Relocation after Address Assignment

Each section has a relocate method that can relocate itself. It happens after the dot address resolution, phdrs creation.

Relocation per Section

Relocation for each relocatable section:

// lld/ELF/InputSection.h

// class InputSectionBase

  // Each section knows how to relocate itself. These functions apply
  // relocations, assuming that Buf points to this section's copy in
  // the mmap'ed output buffer.
  template <class ELFT> void relocate(uint8_t *buf, uint8_t *bufEnd);
  void relocateAlloc(uint8_t *buf, uint8_t *bufEnd);
  static uint64_t getRelocTargetVA(const InputFile *File, RelType Type,
   relocateNoSym                                int64_t A, uint64_t P, const Symbol &Sym,
                                   RelExpr Expr, InputSectionBase *isec,
                                   uint64_t offset);

Call path for relocate, relocateAlloc and getRelocTargetVA:

void InputSection::writeTo(uint8_t *buf)
=> relocate<ELFT>(buf, bufEnd);
   => adjustSplitStackFunctionPrologues<ELFT>(buf, bufEnd); // if (flags & SHF_EXECINSTR)
   => relocateAlloc(buf, bufEnd); // if (flags & SHF_ALLOC)
      => targetVA = getRelocTargetVA(file, type, rel.addend, addrLoc, *rel.sym, expr, this, rel.offset);
      => target->relocate(bufLoc, rel, targetVA);
   => relocateNonAllocForRelocatable(sec, buf); // if (config->relocatable)
   => sec->relocateNonAlloc<ELFT>(buf, sec->template relas<ELFT>()); // if (sec->areRelocsRela)
   => sec->relocateNonAlloc<ELFT>(buf, sec->template rels<ELFT>());

// call path to InputSection::writeTo

Target Specific Relocation impl

Relocation per target:

// lld/ELF/Target.h

// class TargetInfo

class TargetInfo{
  ...
  virtual void relocate(uint8_t *loc, const Relocation &rel,
                        uint64_t val) const = 0;
  void relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const {
    relocate(loc, Relocation{R_NONE, type, 0, 0, nullptr}, val);
  }
}

// lld/ELF/Arch/Mips.cpp
class MIPS final: public TargetInfo{
  ...
  void relocate(uint8_t *loc, const Relocation &rel,
                uint64_t val) const override;
}

Call path for target relocate

// lld/ELF/InputSection.cpp
void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd)
=> static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf)
   => target->relocate(..)

void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd)
=> target->relocate(..)

call path for target relocateNoSym:

void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels)
=> void TargetInfo::relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const 
   => this->relocate(...)

void ARMExidxSyntheticSection::writeTo(uint8_t *buf) // lld/ELF/SyntheticSections.cpp
=> void TargetInfo::relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const 
   => this->relocate(...)

// lld/ELF/Thunks.cpp
void ARMThunk::writeTo(uint8_t *buf)
void ThumbThunk::writeTo(uint8_t *buf)
void MipsThunk::writeTo(uint8_t *buf) 
=> void TargetInfo::relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const 
   => this->relocate(...)

// lld/ELF/Arch/Mips.cpp
void MIPS<ELFT>::writePltHeader(uint8_t *buf) const
void MIPS<ELFT>::writePlt(uint8_t *buf, const Symbol &sym,
                          uint64_t pltEntryAddr) const
=> void TargetInfo::relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const 
   => this->relocate(...)

// lld/ELF/Arch/RISCV.cpp (recursive???)
void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const
=> void TargetInfo::relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const 
   => this->relocate(...)

Ending

  • Sythetic Relocation Sections
  • Reference reference Synthetic Input Sections for relocation .got or .mipsgot are synthetic input sections created before relocation can actually happen on them. They are created before finalizeSections(), so that they can be placed into the finall output; they are updated during finalizeSections(), where they got allocated in the virtual space; After the location of sections are finalized, virtual addresses are mostly available for relocation to happen. Now here tracks the first step where synthetic relocation sections such as .

Created Aug 5, 2020 // Last Updated May 18, 2021

If you could revise
the fundmental principles of
computer system design
to improve security...

... what would you change?