Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -338,7 +338,7 @@ const unsigned Bits = sizeof(uintX_t) * 8; for (const Relocation &Rel : Relocations) { - uintX_t Offset = Rel.InputSec->getOffset(Rel.Offset); + uintX_t Offset = Rel.Offset; uint8_t *BufLoc = Buf + Offset; uint32_t Type = Rel.Type; uintX_t A = Rel.Addend; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1278,7 +1278,7 @@ typename ELFT::uint DynamicReloc::getOffset() const { if (OutputSec) return OutputSec->getVA() + OffsetInSec; - return InputSec->OutSec->getVA() + InputSec->getOffset(OffsetInSec); + return InputSec->OutSec->getVA() + OffsetInSec; } template Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -73,12 +73,13 @@ SymbolBody *Sym; }; -template void scanRelocations(InputSection &); - template void scanRelocations(InputSectionBase &, const typename ELFT::Shdr &); template +void createThunks(InputSectionBase &, const typename ELFT::Shdr &); + +template static inline typename ELFT::uint getAddend(const typename ELFT::Rel &Rel) { return 0; } Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -548,9 +548,17 @@ while (PieceI != PieceE && (PieceI->InputOff + PieceI->size() <= RI.r_offset)) ++PieceI; - if (PieceI != PieceE && PieceI->InputOff <= RI.r_offset && - PieceI->OutputOff == (uintX_t)-1) - continue; + + uintX_t Offset; + if (PieceI != PieceE) { + assert(PieceI->InputOff <= RI.r_offset && "Relocation not in any piece"); + if (PieceI->OutputOff == (uintX_t)-1) + continue; + Offset = PieceI->OutputOff + (RI.r_offset - PieceI->InputOff); + assert(Offset == C.getOffset(RI.r_offset)); + } else { + Offset = C.getOffset(RI.r_offset); + } // This relocation does not require got entry, but it is relative to got and // needs it to be created. Here we request for that. @@ -559,8 +567,8 @@ uintX_t Addend = computeAddend(File, Buf, E, RI, Expr, Body); - if (unsigned Processed = handleTlsRelocation( - Type, Body, C, RI.r_offset, Addend, Expr)) { + if (unsigned Processed = + handleTlsRelocation(Type, Body, C, Offset, Addend, Expr)) { I += (Processed - 1); continue; } @@ -581,17 +589,17 @@ // relocation. We can process some of it and and just ask the dynamic // linker to add the load address. if (!Constant) - AddDyn({Target->RelativeRel, &C, RI.r_offset, true, &Body, Addend}); + AddDyn({Target->RelativeRel, &C, Offset, true, &Body, Addend}); // If the produced value is a constant, we just remember to write it // when outputting this section. We also have to do it if the format // uses Elf_Rel, since in that case the written value is the addend. if (Constant || !RelTy::IsRela) - C.Relocations.push_back({Expr, Type, &C, RI.r_offset, Addend, &Body}); + C.Relocations.push_back({Expr, Type, &C, Offset, Addend, &Body}); } else { // We don't know anything about the finaly symbol. Just ask the dynamic // linker to handle the relocation for us. - AddDyn({Target->getDynRel(Type), &C, RI.r_offset, false, &Body, Addend}); + AddDyn({Target->getDynRel(Type), &C, Offset, false, &Body, Addend}); // MIPS ABI turns using of GOT and dynamic relocations inside out. // While regular ABI uses dynamic relocations to fill up GOT entries // MIPS ABI requires dynamic linker to fills up GOT entries using @@ -612,14 +620,6 @@ continue; } - // 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); - } - // At this point we are done with the relocated position. Some relocations // also require us to create a got or plt entry. @@ -676,19 +676,6 @@ } } -template void scanRelocations(InputSection &C) { - typedef typename ELFT::Shdr Elf_Shdr; - - // Scan all relocations. Each relocation goes through a series - // of tests to determine if it needs special treatment, such as - // creating GOT, PLT, copy relocations, etc. - // Note that relocations for non-alloc sections are directly - // processed by InputSection::relocateNonAlloc. - if (C.getSectionHdr()->sh_flags & SHF_ALLOC) - for (const Elf_Shdr *RelSec : C.RelocSections) - scanRelocations(C, *RelSec); -} - template void scanRelocations(InputSectionBase &S, const typename ELFT::Shdr &RelSec) { @@ -699,10 +686,36 @@ scanRelocs(S, EObj.rels(&RelSec)); } -template void scanRelocations(InputSection &); -template void scanRelocations(InputSection &); -template void scanRelocations(InputSection &); -template void scanRelocations(InputSection &); +template +static void createThunks(InputSectionBase &C, ArrayRef Rels) { + const elf::ObjectFile &File = *C.getFile(); + for (auto I = Rels.begin(), E = Rels.end(); I != E; ++I) { + const RelTy &RI = *I; + SymbolBody &Body = File.getRelocTargetSym(RI); + uint32_t Type = RI.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(InputSectionBase &S, + const typename ELFT::Shdr &RelSec) { + ELFFile &EObj = S.getFile()->getObj(); + if (RelSec.sh_type == SHT_RELA) + createThunks(S, EObj.relas(&RelSec)); + else + createThunks(S, EObj.rels(&RelSec)); +} template void scanRelocations(InputSectionBase &, const ELF32LE::Shdr &); @@ -712,5 +725,14 @@ const ELF64LE::Shdr &); template void scanRelocations(InputSectionBase &, const ELF64BE::Shdr &); + +template void createThunks(InputSectionBase &, + const ELF32LE::Shdr &); +template void createThunks(InputSectionBase &, + const ELF32BE::Shdr &); +template void createThunks(InputSectionBase &, + const ELF64LE::Shdr &); +template void createThunks(InputSectionBase &, + const ELF64BE::Shdr &); } } Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -92,6 +92,8 @@ // Set to 0 for variant 2 unsigned TcbSize = 0; + bool NeedsThunks = false; + virtual RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, RelExpr Expr) const; virtual void relaxGot(uint8_t *Loc, uint64_t Val) const; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -1496,6 +1496,7 @@ PltHeaderSize = 20; // ARM uses Variant 1 TLS TcbSize = 8; + NeedsThunks = true; } RelExpr ARMTargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const { @@ -1836,6 +1837,7 @@ PltHeaderSize = 32; CopyRel = R_MIPS_COPY; PltRel = R_MIPS_JUMP_SLOT; + NeedsThunks = true; if (ELFT::Is64Bits) { RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32; TlsGotRel = R_MIPS_TLS_TPREL64; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -49,6 +49,9 @@ void copyLocalSymbols(); void addReservedSymbols(); std::vector>> createSections(); + void forEachRelSec( + std::function &, const typename ELFT::Shdr &)> + Fn); void finalizeSections(); void addPredefinedSections(); bool needsGot(); @@ -637,6 +640,34 @@ } template +void Writer::forEachRelSec( + std::function &, const typename ELFT::Shdr &)> + Fn) { + for (const std::unique_ptr> &F : + Symtab.getObjectFiles()) { + for (InputSectionBase *C : F->getSections()) { + if (isDiscarded(C)) + continue; + // Scan all relocations. Each relocation goes through a series + // of tests to determine if it needs special treatment, such as + // creating GOT, PLT, copy relocations, etc. + // Note that relocations for non-alloc sections are directly + // processed by InputSection::relocateNonAlloc. + if (!(C->getSectionHdr()->sh_flags & SHF_ALLOC)) + continue; + if (auto *S = dyn_cast>(C)) { + for (const Elf_Shdr *RelSec : S->RelocSections) + Fn(*S, *RelSec); + continue; + } + if (auto *S = dyn_cast>(C)) + if (S->RelocSection) + Fn(*S, *S->RelocSection); + } + } +} + +template std::vector>> Writer::createSections() { std::vector>> Result; @@ -711,26 +742,16 @@ Out::EhFrame->finalize(); } - // Scan relocations. This must be done after every symbol is declared so that - // we can correctly decide if a dynamic relocation is needed. - for (const std::unique_ptr> &F : - Symtab.getObjectFiles()) { - for (InputSectionBase *C : F->getSections()) { - if (isDiscarded(C)) - continue; - if (auto *S = dyn_cast>(C)) { - scanRelocations(*S); - continue; - } - if (auto *S = dyn_cast>(C)) - if (S->RelocSection) - scanRelocations(*S, *S->RelocSection); - } - } + if (Target->NeedsThunks) + forEachRelSec(createThunks); for (OutputSectionBase *Sec : OutputSections) Sec->assignOffsets(); + // Scan relocations. This must be done after every symbol is declared so that + // we can correctly decide if a dynamic relocation is needed. + forEachRelSec(scanRelocations); + // Now that we have defined all possible symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. std::vector CommonSymbols;