[lld] r306282 - [ELF] Define _GLOBAL_OFFSET_TABLE_ symbol relative to .got
Peter Smith via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 26 03:22:17 PDT 2017
Author: psmith
Date: Mon Jun 26 03:22:17 2017
New Revision: 306282
URL: http://llvm.org/viewvc/llvm-project?rev=306282&view=rev
Log:
[ELF] Define _GLOBAL_OFFSET_TABLE_ symbol relative to .got
On many architectures gcc and clang will recognize _GLOBAL_OFFSET_TABLE_ - .
and produce a relocation that can be processed without needing to know the
value of _GLOBAL_OFFSET_TABLE_. This is not always the case; for example ARM
gcc produces R_ARM_BASE_PREL but clang produces the more general
R_ARM_REL32 to _GLOBAL_OFFSET_TABLE_. To evaluate this relocation
correctly _GLOBAL_OFFSET_TABLE_ must be defined to be the either the base of
the GOT or end of the GOT dependent on architecture..
If/when llvm-mc is changed to recognize _GLOBAL_OFFSET_TABLE_ - . this
change will not be necessary for new objects. However there may still be
old objects and versions of clang.
Differential Revision: https://reviews.llvm.org/D34355
Added:
lld/trunk/test/ELF/global-offset-table-position-aarch64.s
lld/trunk/test/ELF/global-offset-table-position-arm.s
lld/trunk/test/ELF/global-offset-table-position-i386.s
lld/trunk/test/ELF/global-offset-table-position-mips.s
lld/trunk/test/ELF/global-offset-table-position.s
Modified:
lld/trunk/ELF/Arch/PPC.cpp
lld/trunk/ELF/Arch/X86.cpp
lld/trunk/ELF/Arch/X86_64.cpp
lld/trunk/ELF/Relocations.cpp
lld/trunk/ELF/Target.h
lld/trunk/ELF/Writer.cpp
lld/trunk/test/ELF/arm-got-relative.s
lld/trunk/test/ELF/global_offset_table_shared.s
Modified: lld/trunk/ELF/Arch/PPC.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC.cpp?rev=306282&r1=306281&r2=306282&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC.cpp (original)
+++ lld/trunk/ELF/Arch/PPC.cpp Mon Jun 26 03:22:17 2017
@@ -21,7 +21,7 @@ using namespace lld::elf;
namespace {
class PPC final : public TargetInfo {
public:
- PPC() {}
+ PPC() { GotBaseSymOff = 0x8000; }
void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
const uint8_t *Loc) const override;
Modified: lld/trunk/ELF/Arch/X86.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86.cpp?rev=306282&r1=306281&r2=306282&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86.cpp (original)
+++ lld/trunk/ELF/Arch/X86.cpp Mon Jun 26 03:22:17 2017
@@ -46,6 +46,7 @@ public:
} // namespace
X86::X86() {
+ GotBaseSymOff = -1;
CopyRel = R_386_COPY;
GotRel = R_386_GLOB_DAT;
PltRel = R_386_JUMP_SLOT;
Modified: lld/trunk/ELF/Arch/X86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86_64.cpp?rev=306282&r1=306281&r2=306282&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86_64.cpp (original)
+++ lld/trunk/ELF/Arch/X86_64.cpp Mon Jun 26 03:22:17 2017
@@ -51,6 +51,7 @@ private:
} // namespace
template <class ELFT> X86_64<ELFT>::X86_64() {
+ GotBaseSymOff = -1;
CopyRel = R_X86_64_COPY;
GotRel = R_X86_64_GLOB_DAT;
PltRel = R_X86_64_JUMP_SLOT;
Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=306282&r1=306281&r2=306282&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Mon Jun 26 03:22:17 2017
@@ -361,7 +361,7 @@ static bool isStaticLinkTimeConstant(Rel
// These expressions always compute a constant
if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
- R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC,
+ R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC,
R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_PC, R_TLSGD,
R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E))
return true;
Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=306282&r1=306281&r2=306282&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Mon Jun 26 03:22:17 2017
@@ -66,6 +66,10 @@ public:
// Given that, the smallest value that can be used in here is 0x10000.
uint64_t DefaultImageBase = 0x10000;
+ // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got section. Use -1 for
+ // end of .got
+ uint64_t GotBaseSymOff = 0;
+
uint32_t CopyRel;
uint32_t GotRel;
uint32_t PltRel;
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=306282&r1=306281&r2=306282&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Jun 26 03:22:17 2017
@@ -87,6 +87,8 @@ private:
uint64_t FileSize;
uint64_t SectionHeaderOff;
+
+ bool HasGotBaseSym = false;
};
} // anonymous namespace
@@ -815,19 +817,13 @@ template <class ELFT> void Writer<ELFT>:
Symtab<ELFT>::X->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL);
}
- // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
- // is magical and is used to produce a R_386_GOTPC relocation.
- // The R_386_GOTPC relocation value doesn't actually depend on the
- // symbol value, so it could use an index of STN_UNDEF which, according
- // to the spec, means the symbol value is 0.
- // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in
- // the object file.
- // The situation is even stranger on x86_64 where the assembly doesn't
- // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as
- // an undefined symbol in the .o files.
- // Given that the symbol is effectively unused, we just create a dummy
- // hidden one to avoid the undefined symbol error.
- Symtab<ELFT>::X->addIgnored("_GLOBAL_OFFSET_TABLE_");
+ // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to
+ // be at some offset from the base of the .got section, usually 0 or the end
+ // of the .got
+ InputSection *GotSection = (InX::MipsGot) ? cast<InputSection>(InX::MipsGot)
+ : cast<InputSection>(InX::Got);
+ HasGotBaseSym = addOptionalRegular<ELFT>("_GLOBAL_OFFSET_TABLE_", GotSection,
+ Target->GotBaseSymOff) != nullptr;
// __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For
// static linking the linker is required to optimize away any references to
@@ -1136,7 +1132,8 @@ static void applySynthetic(const std::ve
// to make them visible from linkescript side. But not all sections are always
// required to be in output. For example we don't need dynamic section content
// sometimes. This function filters out such unused sections from the output.
-static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) {
+static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V,
+ bool HasGotBaseSym) {
// All input synthetic sections that can be empty are placed after
// all regular ones. We iterate over them all and exit at first
// non-synthetic.
@@ -1147,6 +1144,8 @@ static void removeUnusedSyntheticSection
OutputSection *OS = SS->getParent();
if (!SS->empty() || !OS)
continue;
+ if ((SS == InX::Got || SS == InX::MipsGot) && HasGotBaseSym)
+ continue;
OS->Sections.erase(std::find(OS->Sections.begin(), OS->Sections.end(), SS));
SS->Live = false;
// If there are no other sections in the output section, remove it from the
@@ -1220,7 +1219,7 @@ template <class ELFT> void Writer<ELFT>:
return;
addPredefinedSections();
- removeUnusedSyntheticSections(OutputSections);
+ removeUnusedSyntheticSections(OutputSections, HasGotBaseSym);
clearOutputSections();
sortSections();
Modified: lld/trunk/test/ELF/arm-got-relative.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-got-relative.s?rev=306282&r1=306281&r2=306282&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-got-relative.s (original)
+++ lld/trunk/test/ELF/arm-got-relative.s Mon Jun 26 03:22:17 2017
@@ -16,9 +16,9 @@ _start:
bx lr
.align 2
.LGOT:
- // gas implicitly uses (GOT_PREL) for _GLOBAL_OFFSET_TABLE_ in PIC
- // llvm-mc needs the (GOT_PREL) suffix or it generates R_ARM_REL32
- .word _GLOBAL_OFFSET_TABLE_(GOT_PREL) - (.LPIC+8)
+ // gas implicitly uses (R_ARM_BASE_PREL) for _GLOBAL_OFFSET_TABLE_ in PIC
+ // llvm-mc generates R_ARM_REL32, this will need updating when MC changes
+ .word _GLOBAL_OFFSET_TABLE_ - (.LPIC+8)
.word function(GOT)
.globl function
@@ -28,17 +28,17 @@ function:
bx lr
// CHECK: Dynamic Relocations {
-// CHECK-NEXT: 0x204C R_ARM_GLOB_DAT function 0x0
+// CHECK-NEXT: 0x2048 R_ARM_GLOB_DAT function 0x0
// CHECK: Name: _GLOBAL_OFFSET_TABLE_
-// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Value: 0x2048
// CHECK-NEXT: Size:
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
// CHECK-NEXT: Other [
// CHECK-NEXT: STV_HIDDEN
// CHECK-NEXT: ]
-// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: Section: .got
// CODE: Disassembly of section .text:
// CODE-NEXT: _start:
@@ -49,5 +49,5 @@ function:
// CODE:$d.1:
// (_GLOBAL_OFFSET_TABLE_ = 0x2048) - (0x1008 + 8) 0x1038
// CODE-NEXT: 1010: 38 10 00 00
-// (Got(function) - GotBase = 0x4
-// CODE-NEXT: 1014: 04 00 00 00
+// (Got(function) - GotBase = 0x0
+// CODE-NEXT: 1014: 00 00 00 00
Added: lld/trunk/test/ELF/global-offset-table-position-aarch64.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/global-offset-table-position-aarch64.s?rev=306282&view=auto
==============================================================================
--- lld/trunk/test/ELF/global-offset-table-position-aarch64.s (added)
+++ lld/trunk/test/ELF/global-offset-table-position-aarch64.s Mon Jun 26 03:22:17 2017
@@ -0,0 +1,30 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t
+// RUN: ld.lld -shared %t -o %t2
+// RUN: llvm-readobj -t %t2 | FileCheck %s
+// REQUIRES: aarch64
+.globl a
+.type a, at object
+.comm a,4,4
+
+.globl f
+.type f, at function
+f:
+ adrp x0, :got:a
+ ldr x0, [x0, #:got_lo12:a]
+
+.global _start
+.type _start, at function
+_start:
+ bl f
+.data
+.long _GLOBAL_OFFSET_TABLE_ - .
+
+// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (11)
+// CHECK-NEXT: Value: 0x30090
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local (0x0)
+// CHECK-NEXT: Type: None (0x0)
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .got
Added: lld/trunk/test/ELF/global-offset-table-position-arm.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/global-offset-table-position-arm.s?rev=306282&view=auto
==============================================================================
--- lld/trunk/test/ELF/global-offset-table-position-arm.s (added)
+++ lld/trunk/test/ELF/global-offset-table-position-arm.s Mon Jun 26 03:22:17 2017
@@ -0,0 +1,35 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t
+// RUN: ld.lld -shared %t -o %t2
+// RUN: llvm-readobj -t %t2 | FileCheck %s
+// REQUIRES: arm
+
+// The ARM _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got
+.globl a
+.type a,%object
+.comm a,4,4
+
+.globl f
+.type f,%function
+f:
+ ldr r2, .L1
+.L0:
+ add r2, pc
+.L1:
+.word _GLOBAL_OFFSET_TABLE_ - (.L0+4)
+.word a(GOT)
+
+.global _start
+.type _start,%function
+_start:
+ bl f
+.data
+
+// CHECK: Name: _GLOBAL_OFFSET_TABLE_
+// CHECK-NEXT: Value: 0x3068
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .got
Added: lld/trunk/test/ELF/global-offset-table-position-i386.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/global-offset-table-position-i386.s?rev=306282&view=auto
==============================================================================
--- lld/trunk/test/ELF/global-offset-table-position-i386.s (added)
+++ lld/trunk/test/ELF/global-offset-table-position-i386.s Mon Jun 26 03:22:17 2017
@@ -0,0 +1,31 @@
+// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t
+// RUN: ld.lld -shared %t -o %t2
+// RUN: llvm-readobj -t %t2 | FileCheck %s
+// REQUIRES: x86
+
+// The X86 _GLOBAL_OFFSET_TABLE_ is defined at the end of the .got section.
+.globl a
+.type a, at object
+.comm a,4,4
+
+.globl f
+.type f, at function
+f:
+addl $_GLOBAL_OFFSET_TABLE_, %eax
+movl a at GOT(%eax), %eax
+
+.global _start
+.type _start, at function
+_start:
+addl $_GLOBAL_OFFSET_TABLE_, %eax
+calll f at PLT
+
+// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (1)
+// CHECK-NEXT: Value: 0x306C
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local (0x0)
+// CHECK-NEXT: Type: None (0x0)
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .got (0xA)
Added: lld/trunk/test/ELF/global-offset-table-position-mips.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/global-offset-table-position-mips.s?rev=306282&view=auto
==============================================================================
--- lld/trunk/test/ELF/global-offset-table-position-mips.s (added)
+++ lld/trunk/test/ELF/global-offset-table-position-mips.s Mon Jun 26 03:22:17 2017
@@ -0,0 +1,33 @@
+// RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t
+// RUN: ld.lld -shared %t -o %t2
+// RUN: llvm-readobj -t %t2 | FileCheck %s
+
+// REQUIRES: mips
+
+// The Mips _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got
+
+.globl a
+.hidden a
+.type a, at object
+.comm a,4,4
+
+.globl f
+.type f, at function
+f:
+ ld $v0,%got_page(a)($gp)
+ daddiu $v0,$v0,%got_ofst(a)
+
+.global _start
+.type _start, at function
+_start:
+ lw $t0,%call16(f)($gp)
+ .word _GLOBAL_OFFSET_TABLE_ - .
+// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (1)
+// CHECK-NEXT: Value: 0x20000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local (0x0)
+// CHECK-NEXT: Type: None (0x0)
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .got (0x9)
Added: lld/trunk/test/ELF/global-offset-table-position.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/global-offset-table-position.s?rev=306282&view=auto
==============================================================================
--- lld/trunk/test/ELF/global-offset-table-position.s (added)
+++ lld/trunk/test/ELF/global-offset-table-position.s Mon Jun 26 03:22:17 2017
@@ -0,0 +1,31 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld -shared %t -o %t2
+// RUN: llvm-readobj -t %t2 | FileCheck %s
+// REQUIRES: x86
+
+// The X86_64 _GLOBAL_OFFSET_TABLE_ is defined at the end of the .got section.
+.globl a
+.type a, at object
+.comm a,4,4
+
+.globl f
+.type f, at function
+f:
+movq a at GOTPCREL(%rip), %rax
+
+.global _start
+.type _start, at function
+_start:
+callq f at PLT
+.data
+.long _GLOBAL_OFFSET_TABLE_ - .
+
+// CHECK: Name: _GLOBAL_OFFSET_TABLE_
+// CHECK-NEXT: Value: 0x30D8
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None (0x0)
+// CHECK-NEXT: Other [
+// CHECK-NEXT: STV_HIDDEN
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .got
Modified: lld/trunk/test/ELF/global_offset_table_shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/global_offset_table_shared.s?rev=306282&r1=306281&r2=306282&view=diff
==============================================================================
--- lld/trunk/test/ELF/global_offset_table_shared.s (original)
+++ lld/trunk/test/ELF/global_offset_table_shared.s Mon Jun 26 03:22:17 2017
@@ -1,9 +1,14 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
// RUN: ld.lld -shared %t -o %t2
// RUN: llvm-readobj -t %t2 | FileCheck %s
-.long _GLOBAL_OFFSET_TABLE_
+.long _GLOBAL_OFFSET_TABLE_ - .
// CHECK: Name: _GLOBAL_OFFSET_TABLE_
-// CHECK-NEXT: Value:
+// CHECK-NEXT: Value: 0x2060
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other [ (0x2)
+// CHECK-NEXT: STV_HIDDEN (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Section: .got
More information about the llvm-commits
mailing list