forked from OSchip/llvm-project
[ELF2] Support relocs for local symbols
Differential Revision: http://reviews.llvm.org/D12978 llvm-svn: 248196
This commit is contained in:
parent
b12db0e42c
commit
8ca741d51d
|
@ -263,6 +263,7 @@ class lld::elf2::OutputSection final
|
||||||
public:
|
public:
|
||||||
typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
|
typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
|
||||||
typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
|
typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
|
||||||
|
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
|
||||||
typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
|
typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
|
||||||
typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
|
typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
|
||||||
OutputSection(const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec,
|
OutputSection(const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec,
|
||||||
|
@ -733,6 +734,21 @@ getSymVA(const DefinedRegular<ELFT> *DR) {
|
||||||
return OS->getVA() + SC->getOutputSectionOff() + DR->Sym.st_value;
|
return OS->getVA() + SC->getOutputSectionOff() + DR->Sym.st_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
static typename ELFFile<ELFT>::uintX_t
|
||||||
|
getLocalSymVA(const typename ELFFile<ELFT>::Elf_Sym *Sym,
|
||||||
|
const ObjectFile<ELFT> &File) {
|
||||||
|
uint32_t SecIndex = Sym->st_shndx;
|
||||||
|
|
||||||
|
if (SecIndex == SHN_XINDEX)
|
||||||
|
SecIndex = File.getObj()->getExtendedSymbolTableIndex(
|
||||||
|
Sym, File.getSymbolTable(), File.getSymbolTableShndx());
|
||||||
|
ArrayRef<InputSection<ELFT> *> Chunks = File.getChunks();
|
||||||
|
InputSection<ELFT> *Section = Chunks[SecIndex];
|
||||||
|
OutputSection<ELFT> *Out = Section->getOutputSection();
|
||||||
|
return Out->getVA() + Section->getOutputSectionOff() + Sym->st_value;
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,
|
void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,
|
||||||
uint32_t Type, uintX_t BaseAddr,
|
uint32_t Type, uintX_t BaseAddr,
|
||||||
|
@ -789,42 +805,51 @@ void OutputSection<ELFT>::relocate(
|
||||||
bool IsMips64EL = File.getObj()->isMips64EL();
|
bool IsMips64EL = File.getObj()->isMips64EL();
|
||||||
for (const RelType &RI : Rels) {
|
for (const RelType &RI : Rels) {
|
||||||
uint32_t SymIndex = RI.getSymbol(IsMips64EL);
|
uint32_t SymIndex = RI.getSymbol(IsMips64EL);
|
||||||
const SymbolBody *Body = File.getSymbolBody(SymIndex);
|
|
||||||
if (!Body)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint32_t Type = RI.getType(IsMips64EL);
|
uint32_t Type = RI.getType(IsMips64EL);
|
||||||
uintX_t SymVA;
|
uintX_t SymVA;
|
||||||
|
|
||||||
switch (Body->kind()) {
|
// Handle relocations for local symbols -- they never get
|
||||||
case SymbolBody::DefinedRegularKind:
|
// resolved so we don't allocate a SymbolBody.
|
||||||
SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));
|
const Elf_Shdr *SymTab = File.getSymbolTable();
|
||||||
break;
|
if (SymIndex < SymTab->sh_info) {
|
||||||
case SymbolBody::DefinedAbsoluteKind:
|
const Elf_Sym *Sym = File.getObj()->getRelocationSymbol(&RI, SymTab);
|
||||||
SymVA = cast<DefinedAbsolute<ELFT>>(Body)->Sym.st_value;
|
if (!Sym)
|
||||||
break;
|
|
||||||
case SymbolBody::DefinedCommonKind: {
|
|
||||||
auto *DC = cast<DefinedCommon<ELFT>>(Body);
|
|
||||||
SymVA = DC->OutputSec->getVA() + DC->OffsetInBSS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SymbolBody::SharedKind:
|
|
||||||
if (relocNeedsPLT(Type)) {
|
|
||||||
SymVA = PltSec.getEntryAddr(*Body);
|
|
||||||
Type = R_X86_64_PC32;
|
|
||||||
} else if (relocNeedsGOT(Type)) {
|
|
||||||
SymVA = GotSec.getEntryAddr(*Body);
|
|
||||||
Type = R_X86_64_PC32;
|
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
|
SymVA = getLocalSymVA(Sym, File);
|
||||||
|
} else {
|
||||||
|
const SymbolBody *Body = File.getSymbolBody(SymIndex);
|
||||||
|
if (!Body)
|
||||||
|
continue;
|
||||||
|
switch (Body->kind()) {
|
||||||
|
case SymbolBody::DefinedRegularKind:
|
||||||
|
SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));
|
||||||
|
break;
|
||||||
|
case SymbolBody::DefinedAbsoluteKind:
|
||||||
|
SymVA = cast<DefinedAbsolute<ELFT>>(Body)->Sym.st_value;
|
||||||
|
break;
|
||||||
|
case SymbolBody::DefinedCommonKind: {
|
||||||
|
auto *DC = cast<DefinedCommon<ELFT>>(Body);
|
||||||
|
SymVA = DC->OutputSec->getVA() + DC->OffsetInBSS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SymbolBody::SharedKind:
|
||||||
|
if (relocNeedsPLT(Type)) {
|
||||||
|
SymVA = PltSec.getEntryAddr(*Body);
|
||||||
|
Type = R_X86_64_PC32;
|
||||||
|
} else if (relocNeedsGOT(Type)) {
|
||||||
|
SymVA = GotSec.getEntryAddr(*Body);
|
||||||
|
Type = R_X86_64_PC32;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SymbolBody::UndefinedKind:
|
||||||
|
assert(Body->isWeak() && "Undefined symbol reached writer");
|
||||||
|
SymVA = 0;
|
||||||
|
break;
|
||||||
|
case SymbolBody::LazyKind:
|
||||||
|
llvm_unreachable("Lazy symbol reached writer");
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case SymbolBody::UndefinedKind:
|
|
||||||
assert(Body->isWeak() && "Undefined symbol reached writer");
|
|
||||||
SymVA = 0;
|
|
||||||
break;
|
|
||||||
case SymbolBody::LazyKind:
|
|
||||||
llvm_unreachable("Lazy symbol reached writer");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
relocateOne(Buf, RI, Type, BaseAddr, SymVA);
|
relocateOne(Buf, RI, Type, BaseAddr, SymVA);
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Test that relocation of local symbols is working.
|
||||||
|
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
|
||||||
|
// RUN: lld -flavor gnu2 %t -o %t2
|
||||||
|
// RUN: llvm-objdump -s -d %t2 | FileCheck %s
|
||||||
|
// REQUIRES: x86
|
||||||
|
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
call lulz
|
||||||
|
|
||||||
|
.zero 4
|
||||||
|
lulz:
|
||||||
|
|
||||||
|
.section .text2,"ax",@progbits
|
||||||
|
R_X86_64_32:
|
||||||
|
movl $R_X86_64_32, %edx
|
||||||
|
|
||||||
|
// FIXME: this would be far more self evident if llvm-objdump printed
|
||||||
|
// constants in hex.
|
||||||
|
// CHECK: Disassembly of section .text2:
|
||||||
|
// CHECK-NEXT: R_X86_64_32:
|
||||||
|
// CHECK-NEXT: 1100c: {{.*}} movl $69644, %edx
|
||||||
|
|
||||||
|
.section .R_X86_64_32S,"ax",@progbits
|
||||||
|
R_X86_64_32S:
|
||||||
|
movq lulz - 0x100000, %rdx
|
||||||
|
|
||||||
|
// CHECK: Disassembly of section .R_X86_64_32S:
|
||||||
|
// CHECK-NEXT: R_X86_64_32S:
|
||||||
|
// CHECK-NEXT: {{.*}}: {{.*}} movq -978935, %rdx
|
||||||
|
|
||||||
|
.section .R_X86_64_64,"a",@progbits
|
||||||
|
R_X86_64_64:
|
||||||
|
.quad R_X86_64_64
|
||||||
|
|
||||||
|
// CHECK: Contents of section .R_X86_64_64:
|
||||||
|
// CHECK-NEXT: 12000 00200100 00000000
|
Loading…
Reference in New Issue