[ELF] - fixed not properly handled @GOTTPOFF relocation against local symbols
This patch changes sequence of applying relocations, moving tls optimized relocation handling code before code for other locals.
Without that change relocation @GOTTPOFF against local symbol caused runtime error ("unrecognized reloc ...").
That change also should fix other tls optimized relocations, but I did not check them, that's a field for another patch.
R_X86_64_GOTTPOFF relocations against locals can be found when linking against libc.a(malloc.o):
000000000036 000600000016 R_X86_64_GOTTPOFF 0000000000000000 libc_tsd_MALLOC - 4
000000000131 000600000016 R_X86_64_GOTTPOFF 0000000000000000 libc_tsd_MALLOC - 4
Differential revision: http://reviews.llvm.org/D15581
llvm-svn: 256145
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 71dbc6c..51fac66 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -161,60 +161,66 @@
continue;
}
+ const Elf_Shdr *SymTab = File->getSymbolTable();
+ SymbolBody *Body = nullptr;
+ if (SymIndex >= SymTab->sh_info)
+ Body = File->getSymbolBody(SymIndex)->repl();
+
+ if (Target->isTlsOptimized(Type, Body)) {
+ uintX_t SymVA;
+ if (!Body)
+ SymVA = getLocalRelTarget(*File, RI, 0);
+ else if (Target->relocNeedsGot(Type, *Body))
+ SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
+ else
+ SymVA = getSymVA<ELFT>(*Body);
+ // By optimizing TLS relocations, it is sometimes needed to skip
+ // relocations that immediately follow TLS relocations. This function
+ // knows how many slots we need to skip.
+ I += Target->relocateTlsOptimize(BufLoc, BufEnd, Type, AddrLoc, SymVA,
+ *Body);
+ continue;
+ }
+
// Handle relocations for local symbols -- they never get
// resolved so we don't allocate a SymbolBody.
- const Elf_Shdr *SymTab = File->getSymbolTable();
- if (SymIndex < SymTab->sh_info) {
- uintX_t SymVA = getLocalRelTarget(*File, RI);
+ uintX_t A = getAddend<ELFT>(RI);
+ if (!Body) {
+ uintX_t SymVA = getLocalRelTarget(*File, RI, A);
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, 0,
findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs));
continue;
}
- SymbolBody &Body = *File->getSymbolBody(SymIndex)->repl();
-
if (Target->isTlsGlobalDynamicReloc(Type) &&
- !Target->isTlsOptimized(Type, &Body)) {
+ !Target->isTlsOptimized(Type, Body)) {
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
- Out<ELFT>::Got->getGlobalDynAddr(Body) +
+ Out<ELFT>::Got->getGlobalDynAddr(*Body) +
getAddend<ELFT>(RI));
continue;
}
- if (Target->isTlsOptimized(Type, &Body)) {
- uintX_t SymVA = Target->relocNeedsGot(Type, Body)
- ? Out<ELFT>::Got->getEntryAddr(Body)
- : getSymVA<ELFT>(Body);
- // By optimizing TLS relocations, it is sometimes needed to skip
- // relocations that immediately follow TLS relocations. This function
- // knows how many slots we need to skip.
- I += Target->relocateTlsOptimize(BufLoc, BufEnd, Type, AddrLoc, SymVA,
- Body);
- continue;
- }
-
- uintX_t SymVA = getSymVA<ELFT>(Body);
- if (Target->relocNeedsPlt(Type, Body)) {
- SymVA = Out<ELFT>::Plt->getEntryAddr(Body);
+ uintX_t SymVA = getSymVA<ELFT>(*Body);
+ if (Target->relocNeedsPlt(Type, *Body)) {
+ SymVA = Out<ELFT>::Plt->getEntryAddr(*Body);
Type = Target->getPltRefReloc(Type);
- } else if (Target->relocNeedsGot(Type, Body)) {
- SymVA = Out<ELFT>::Got->getEntryAddr(Body);
- if (Body.isTls())
+ } else if (Target->relocNeedsGot(Type, *Body)) {
+ SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
+ if (Body->isTls())
Type = Target->getTlsGotReloc(Type);
- } else if (!Target->needsCopyRel(Type, Body) &&
- isa<SharedSymbol<ELFT>>(Body)) {
+ } else if (!Target->needsCopyRel(Type, *Body) &&
+ isa<SharedSymbol<ELFT>>(*Body)) {
continue;
- } else if (Target->isTlsDynReloc(Type, Body) ||
- Target->isSizeDynReloc(Type, Body)) {
+ } else if (Target->isTlsDynReloc(Type, *Body) ||
+ Target->isSizeDynReloc(Type, *Body)) {
continue;
} else if (Config->EMachine == EM_MIPS) {
- if (Type == R_MIPS_HI16 && &Body == Config->MipsGpDisp)
+ if (Type == R_MIPS_HI16 && Body == Config->MipsGpDisp)
SymVA = getMipsGpAddr<ELFT>() - AddrLoc;
- else if (Type == R_MIPS_LO16 && &Body == Config->MipsGpDisp)
+ else if (Type == R_MIPS_LO16 && Body == Config->MipsGpDisp)
SymVA = getMipsGpAddr<ELFT>() - AddrLoc + 4;
}
- uintX_t A = getAddend<ELFT>(RI);
- uintX_t Size = getSymSize<ELFT>(Body);
+ uintX_t Size = getSymSize<ELFT>(*Body);
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + A, Size + A,
findMipsPairedReloc(Buf, SymIndex, Type, NextRelocs));
}