Index: lld/trunk/ELF/Relocations.h =================================================================== --- lld/trunk/ELF/Relocations.h +++ lld/trunk/ELF/Relocations.h @@ -18,6 +18,7 @@ class InputSectionData; template class InputSection; template class InputSectionBase; +class OutputSectionBase; // List of target-independent relocation types. Relocations read // from files are converted to these types so that the main code @@ -113,7 +114,8 @@ template void scanRelocations(InputSectionBase &); -template void createThunks(InputSectionBase &); +template +void createThunks(ArrayRef OutputSections); template static inline typename ELFT::uint getAddend(const typename ELFT::Rel &Rel) { Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -467,7 +467,7 @@ if (Expr == R_GOT_PC && !isAbsoluteValue(Body)) Expr = Target->adjustRelaxExpr(Type, Data, Expr); } - Expr = Target->getThunkExpr(Expr, Type, File, Body); + Expr = Target->getThunkExpr(Expr, Type, &File, Body); if (IsWrite || isStaticLinkTimeConstant(Expr, Type, Body, S, RelOff)) return Expr; @@ -805,31 +805,38 @@ scanRelocs(S, S.rels()); } -template -static void createThunks(InputSectionBase &C, ArrayRef Rels) { - const elf::ObjectFile *File = C.getFile(); - for (const RelTy &Rel : Rels) { - SymbolBody &Body = File->getRelocTargetSym(Rel); - uint32_t Type = Rel.getType(Config->Mips64EL); - RelExpr Expr = Target->getRelExpr(Type, Body); - if (!isPreemptible(Body, Type) && needsPlt(Expr)) - Expr = fromPlt(Expr); - Expr = Target->getThunkExpr(Expr, Type, *File, Body); - // Some targets might require creation of thunks for relocations. - // Now we support only MIPS which requires LA25 thunk to call PIC - // code from non-PIC one, and ARM which requires interworking. - if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC || Expr == R_THUNK_PLT_PC) { - auto *Sec = cast>(&C); - addThunk(Type, Body, *Sec); +template +void createThunks(ArrayRef OutputSections) { + for (OutputSectionBase *Base : OutputSections) { + if (auto *OS = dyn_cast>(Base)) { + for (InputSection *IS : OS->Sections) { + for (const Relocation &Rel : IS->Relocations) { + if (Rel.Sym == nullptr) { + continue; + } + SymbolBody &Body = *Rel.Sym; + uint32_t Type = Rel.Type; + RelExpr Expr = Rel.Expr; + if (!isPreemptible(Body, Type) && needsPlt(Expr)) + Expr = fromPlt(Expr); + Expr = Target->getThunkExpr(Expr, Type, IS->getFile(), Body); + // Some targets might require creation of thunks for relocations. + // Now we support only MIPS which requires LA25 thunk to call PIC + // code from non-PIC one, and ARM which requires interworking. + if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC || + Expr == R_THUNK_PLT_PC) + addThunk(Type, Body, *IS); + } + } } } -} - -template void createThunks(InputSectionBase &S) { - if (S.AreRelocsRela) - createThunks(S, S.relas()); - else - createThunks(S, S.rels()); + // Added thunks may affect the output section offset + for (OutputSectionBase *Base : OutputSections) + if (auto *OS = dyn_cast>(Base)) + if (OS->Type == SHT_PROGBITS) { + OS->Size = 0; + OS->assignOffsets(); + } } template void scanRelocations(InputSectionBase &); @@ -837,9 +844,9 @@ template void scanRelocations(InputSectionBase &); template void scanRelocations(InputSectionBase &); -template void createThunks(InputSectionBase &); -template void createThunks(InputSectionBase &); -template void createThunks(InputSectionBase &); -template void createThunks(InputSectionBase &); +template void createThunks(ArrayRef); +template void createThunks(ArrayRef); +template void createThunks(ArrayRef); +template void createThunks(ArrayRef); } } Index: lld/trunk/ELF/Target.h =================================================================== --- lld/trunk/ELF/Target.h +++ lld/trunk/ELF/Target.h @@ -56,7 +56,7 @@ // R_THUNK_PC if thunk is required and expression is pc rel // R_THUNK_PLT_PC if thunk is required to PLT entry and expression is pc rel virtual RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, - const InputFile &File, + const InputFile *File, const SymbolBody &S) const; virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const = 0; virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0; Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -223,7 +223,7 @@ void writePltHeader(uint8_t *Buf) const override; void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const override; - RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile &File, + RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile *File, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; }; @@ -241,7 +241,7 @@ void writePltHeader(uint8_t *Buf) const override; void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const override; - RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile &File, + RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile *File, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; bool usesOnlyLowPageBits(uint32_t Type) const override; @@ -294,7 +294,7 @@ bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; } RelExpr TargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType, - const InputFile &File, + const InputFile *File, const SymbolBody &S) const { return Expr; } @@ -1749,13 +1749,13 @@ } RelExpr ARMTargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType, - const InputFile &File, + const InputFile *File, const SymbolBody &S) const { // If S is an undefined weak symbol in an executable we don't need a Thunk. // In a DSO calls to undefined symbols, including weak ones get PLT entries // which may need a thunk. - if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak() - && !Config->Shared) + if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak() && + !Config->Shared) return Expr; // A state change from ARM to Thumb and vice versa must go through an // interworking thunk if the relocation type is not R_ARM_CALL or @@ -2193,7 +2193,7 @@ template RelExpr MipsTargetInfo::getThunkExpr(RelExpr Expr, uint32_t Type, - const InputFile &File, + const InputFile *File, const SymbolBody &S) const { // Any MIPS PIC code function is invoked with its address in register $t9. // So if we have a branch instruction from non-PIC code to the PIC one @@ -2202,7 +2202,7 @@ // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf if (Type != R_MIPS_26) return Expr; - auto *F = dyn_cast>(&File); + auto *F = dyn_cast_or_null>(File); if (!F) return Expr; // If current file has PIC code, LA25 stub is not required. Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -158,12 +158,6 @@ if (!Config->Relocatable) addReservedSymbols(); - // Some architectures use small displacements for jump instructions. - // It is linker's responsibility to create thunks containing long - // jump instructions if jump targets are too far. Create thunks. - if (Target->NeedsThunks) - forEachRelSec(createThunks); - // Create output sections. Script::X->OutputSections = &OutputSections; if (ScriptConfig->HasSections) { @@ -1088,6 +1082,12 @@ fixHeaders(); } + // Some architectures use small displacements for jump instructions. + // It is linker's responsibility to create thunks containing long + // jump instructions if jump targets are too far. Create thunks. + if (Target->NeedsThunks) + createThunks(OutputSections); + // Fill other section headers. The dynamic table is finalized // at the end because some tags like RELSZ depend on result // of finalizing other sections.