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:
|
||||
typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
|
||||
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_Rela Elf_Rela;
|
||||
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;
|
||||
}
|
||||
|
||||
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>
|
||||
void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,
|
||||
uint32_t Type, uintX_t BaseAddr,
|
||||
|
@ -789,42 +805,51 @@ void OutputSection<ELFT>::relocate(
|
|||
bool IsMips64EL = File.getObj()->isMips64EL();
|
||||
for (const RelType &RI : Rels) {
|
||||
uint32_t SymIndex = RI.getSymbol(IsMips64EL);
|
||||
const SymbolBody *Body = File.getSymbolBody(SymIndex);
|
||||
if (!Body)
|
||||
continue;
|
||||
|
||||
uint32_t Type = RI.getType(IsMips64EL);
|
||||
uintX_t SymVA;
|
||||
|
||||
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 {
|
||||
// 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) {
|
||||
const Elf_Sym *Sym = File.getObj()->getRelocationSymbol(&RI, SymTab);
|
||||
if (!Sym)
|
||||
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);
|
||||
|
|
|
@ -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