[lld] r248196 - [ELF2] Support relocs for local symbols
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 21 12:30:12 PDT 2015
Author: davide
Date: Mon Sep 21 14:30:11 2015
New Revision: 248196
URL: http://llvm.org/viewvc/llvm-project?rev=248196&view=rev
Log:
[ELF2] Support relocs for local symbols
Differential Revision: http://reviews.llvm.org/D12978
Added:
lld/trunk/test/elf2/relocation-local.s
Modified:
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=248196&r1=248195&r2=248196&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Sep 21 14:30:11 2015
@@ -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,
@@ -734,6 +735,21 @@ getSymVA(const DefinedRegular<ELFT> *DR)
}
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,
uintX_t SymVA) {
@@ -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);
Added: lld/trunk/test/elf2/relocation-local.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/relocation-local.s?rev=248196&view=auto
==============================================================================
--- lld/trunk/test/elf2/relocation-local.s (added)
+++ lld/trunk/test/elf2/relocation-local.s Mon Sep 21 14:30:11 2015
@@ -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", at 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", at 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", at progbits
+R_X86_64_64:
+ .quad R_X86_64_64
+
+// CHECK: Contents of section .R_X86_64_64:
+// CHECK-NEXT: 12000 00200100 00000000
More information about the llvm-commits
mailing list