From bfb7bf742959537f47cb569b7d42f83be3e02bd6 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Mon, 21 Dec 2015 10:00:12 +0000 Subject: [PATCH] [ELF] - R_386_GOTOFF relocation implemented. R_386_GOTOFF is calculated as S + A - GOT, where: S - Represents the value of the symbol whose index resides in the relocation entry. A - Represents the addend used to compute the value of the relocatable field. GOT - Represents the address of the global offset table. Differential revision: http://reviews.llvm.org/D15383 llvm-svn: 256143 --- lld/ELF/OutputSections.cpp | 2 ++ lld/ELF/OutputSections.h | 4 ++++ lld/ELF/Target.cpp | 11 +++++++++ lld/ELF/Target.h | 1 + lld/ELF/Writer.cpp | 14 ++++++++++-- lld/test/ELF/got-i386.s | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 lld/test/ELF/got-i386.s diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 9b5fad1..4d72f5e 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -21,6 +21,8 @@ using namespace llvm::ELF; using namespace lld; using namespace lld::elf2; +bool lld::elf2::HasGotOffRel = false; + template OutputSectionBase::OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_flags) diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index d01eb73..66dad5e 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -37,6 +37,10 @@ template class ObjectFile; template class DefinedRegular; template class ELFSymbolBody; +// Flag to force GOT to be in output if we have relocations +// that relies on its address. +extern bool HasGotOffRel; + template static inline typename llvm::object::ELFFile::uintX_t getAddend(const typename llvm::object::ELFFile::Elf_Rel &Rel) { diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 2ea6c65..c540e55 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -95,6 +95,7 @@ public: unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, const SymbolBody &S) const override; + bool isGotRelative(uint32_t Type) const override; private: void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P, @@ -232,6 +233,8 @@ bool TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const { return false; } +bool TargetInfo::isGotRelative(uint32_t Type) const { return false; } + unsigned TargetInfo::getPltRefReloc(unsigned Type) const { return PCRelReloc; } bool TargetInfo::isRelRelative(uint32_t Type) const { return true; } @@ -358,6 +361,13 @@ bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const { (Type == R_386_PC32 && S.isShared()); } +bool X86TargetInfo::isGotRelative(uint32_t Type) const { + // This relocation does not require got entry, + // but it is relative to got and needs it to be created. + // Here we request for that. + return Type == R_386_GOTOFF; +} + void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA, uint8_t *PairedLoc) const { @@ -366,6 +376,7 @@ void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, add32le(Loc, SA); break; case R_386_GOT32: + case R_386_GOTOFF: add32le(Loc, SA - Out::Got->getVA()); break; case R_386_GOTPC: diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 8b24e46..f2ca0f09 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -64,6 +64,7 @@ public: virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA = 0, uint8_t *PairedLoc = nullptr) const = 0; + virtual bool isGotRelative(uint32_t Type) const; virtual bool isTlsOptimized(unsigned Type, const SymbolBody *S) const; virtual bool needsCopyRel(uint32_t Type, const SymbolBody &S) const; virtual unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index b5fa2b9..3fc272e 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -209,6 +209,9 @@ void Writer::scanRelocs( SymbolBody *Body = File.getSymbolBody(SymIndex); uint32_t Type = RI.getType(Config->Mips64EL); + if (Target->isGotRelative(Type)) + HasGotOffRel = true; + if (Target->isTlsLocalDynamicReloc(Type)) { if (Target->isTlsOptimized(Type, nullptr)) continue; @@ -774,10 +777,17 @@ template void Writer::createSections() { } } + bool needsGot = !Out::Got->empty(); // We add the .got section to the result for dynamic MIPS target because // its address and properties are mentioned in the .dynamic section. - if (!Out::Got->empty() || - (isOutputDynamic() && Config->EMachine == EM_MIPS)) + if (Config->EMachine == EM_MIPS) + needsGot |= isOutputDynamic(); + // If we have a relocation that is relative to GOT (such as GOTOFFREL), + // we need to emit a GOT even if it's empty. + if (HasGotOffRel) + needsGot = true; + + if (needsGot) OutputSections.push_back(Out::Got); if (Out::GotPlt && !Out::GotPlt->empty()) OutputSections.push_back(Out::GotPlt); diff --git a/lld/test/ELF/got-i386.s b/lld/test/ELF/got-i386.s new file mode 100644 index 0000000..679eb2e --- /dev/null +++ b/lld/test/ELF/got-i386.s @@ -0,0 +1,56 @@ +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o +// RUN: ld.lld %t.o -o %t +// RUN: llvm-readobj -s -r -t %t | FileCheck %s +// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s +// REQUIRES: x86 + +// CHECK: Name: .got +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x12000 +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Link: +// CHECK-NEXT: Info: +// CHECK-NEXT: AddressAlignment: + +// CHECK: Symbol { +// CHECK: Name: bar +// CHECK-NEXT: Value: 0x12000 +// CHECK-NEXT: Size: 10 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: Object +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .bss +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: obj +// CHECK-NEXT: Value: 0x1200A +// CHECK-NEXT: Size: 10 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: Object +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .bss +// CHECK-NEXT: } + +// 0x12000 - 0 = addr(.got) = 0x12000 +// 0x1200A - 10 = addr(.got) = 0x12000 +// 0x1200A + 5 - 15 = addr(.got) = 0x12000 +// DISASM: Disassembly of section .text: +// DISASM-NEXT: _start: +// DISASM-NEXT: 11000: c7 81 00 00 00 00 01 00 00 00 movl $1, (%ecx) +// DISASM-NEXT: 1100a: c7 81 0a 00 00 00 02 00 00 00 movl $2, 10(%ecx) +// DISASM-NEXT: 11014: c7 81 0f 00 00 00 03 00 00 00 movl $3, 15(%ecx) + +.global _start +_start: + movl $1, bar@GOTOFF(%ecx) + movl $2, obj@GOTOFF(%ecx) + movl $3, obj+5@GOTOFF(%ecx) + .type bar, @object + .comm bar, 10 + .type obj, @object + .comm obj, 10 -- 2.7.4