[lld] r256143 - [ELF] - R_386_GOTOFF relocation implemented.
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 21 02:00:13 PST 2015
Author: grimar
Date: Mon Dec 21 04:00:12 2015
New Revision: 256143
URL: http://llvm.org/viewvc/llvm-project?rev=256143&view=rev
Log:
[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
Added:
lld/trunk/test/ELF/got-i386.s
Modified:
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
lld/trunk/ELF/Target.cpp
lld/trunk/ELF/Target.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon Dec 21 04:00:12 2015
@@ -21,6 +21,8 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf2;
+bool lld::elf2::HasGotOffRel = false;
+
template <class ELFT>
OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t sh_type,
uintX_t sh_flags)
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Mon Dec 21 04:00:12 2015
@@ -37,6 +37,10 @@ template <class ELFT> class ObjectFile;
template <class ELFT> class DefinedRegular;
template <class ELFT> class ELFSymbolBody;
+// Flag to force GOT to be in output if we have relocations
+// that relies on its address.
+extern bool HasGotOffRel;
+
template <class ELFT>
static inline typename llvm::object::ELFFile<ELFT>::uintX_t
getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rel &Rel) {
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Mon Dec 21 04:00:12 2015
@@ -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 T
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
(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
add32le(Loc, SA);
break;
case R_386_GOT32:
+ case R_386_GOTOFF:
add32le(Loc, SA - Out<ELF32LE>::Got->getVA());
break;
case R_386_GOTPC:
Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Mon Dec 21 04:00:12 2015
@@ -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,
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=256143&r1=256142&r2=256143&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Dec 21 04:00:12 2015
@@ -209,6 +209,9 @@ void Writer<ELFT>::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 <class ELFT> void Writer<ELFT>:
}
}
+ bool needsGot = !Out<ELFT>::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<ELFT>::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<ELFT>::Got);
if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
OutputSections.push_back(Out<ELFT>::GotPlt);
Added: lld/trunk/test/ELF/got-i386.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/got-i386.s?rev=256143&view=auto
==============================================================================
--- lld/trunk/test/ELF/got-i386.s (added)
+++ lld/trunk/test/ELF/got-i386.s Mon Dec 21 04:00:12 2015
@@ -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 at GOTOFF(%ecx)
+ movl $2, obj at GOTOFF(%ecx)
+ movl $3, obj+5 at GOTOFF(%ecx)
+ .type bar, @object
+ .comm bar, 10
+ .type obj, @object
+ .comm obj, 10
More information about the llvm-commits
mailing list