[ELF][MIPS] Make _gp, _gp_disp, __gnu_local_gp global symbols

These MIPS specific symbols should be global because in general they can
have an arbitrary value. By default this value is a fixed offset from .got
section.

This patch adds more checks to the mips-gp-local.s test case but marks
it as XFAIL because LLD does not allow redefinition of absolute symbols
value by a linker script. This should be fixed by D27276.

Differential revision: https://reviews.llvm.org/D27524

llvm-svn: 289025
This commit is contained in:
Simon Atanasyan 2016-12-08 06:19:47 +00:00
parent f4257528e9
commit 6a4eb75c46
19 changed files with 99 additions and 54 deletions

View File

@ -348,9 +348,14 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type,
// resolve to the image base. This is a little strange, but it allows us to
// link function calls to such symbols. Normally such a call will be guarded
// with a comparison, which will load a zero from the GOT.
// Another special case is MIPS _gp_disp symbol which represents offset
// between start of a function and '_gp' value and defined as absolute just
// to simplify the code.
if (AbsVal && RelE) {
if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
return true;
if (&Body == ElfSym<ELFT>::MipsGpDisp)
return true;
error(S.getLocation(RelOff) + ": relocation " + toString(Type) +
" cannot refer to absolute symbol '" + toString(Body) +
"' defined in " + toString(Body.File));

View File

@ -127,9 +127,10 @@ template <class ELFT> void SymbolTable<ELFT>::addCombinedLTOObject() {
template <class ELFT>
DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name,
uint8_t Visibility) {
Symbol *Sym = addRegular(Name, Visibility, STT_NOTYPE, 0, 0, STB_GLOBAL,
nullptr, nullptr);
uint8_t Visibility,
uint8_t Type) {
Symbol *Sym =
addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Type, nullptr, nullptr);
return cast<DefinedRegular<ELFT>>(Sym->body());
}

View File

@ -50,7 +50,8 @@ public:
ArrayRef<SharedFile<ELFT> *> getSharedFiles() const { return SharedFiles; }
DefinedRegular<ELFT> *addAbsolute(StringRef Name,
uint8_t Visibility = llvm::ELF::STV_HIDDEN);
uint8_t Visibility = llvm::ELF::STV_HIDDEN,
uint8_t Type = llvm::ELF::STB_GLOBAL);
DefinedRegular<ELFT> *addIgnored(StringRef Name,
uint8_t Visibility = llvm::ELF::STV_HIDDEN);

View File

@ -351,7 +351,7 @@ template <class ELFT> struct ElfSym {
// The content for _gp_disp/__gnu_local_gp symbols for MIPS target.
static DefinedRegular<ELFT> *MipsGpDisp;
static DefinedRegular<ELFT> *MipsLocalGp;
static SymbolBody *MipsGp;
static DefinedRegular<ELFT> *MipsGp;
};
template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::EhdrStart;
@ -363,7 +363,7 @@ template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End;
template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::End2;
template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsGpDisp;
template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsLocalGp;
template <class ELFT> SymbolBody *ElfSym<ELFT>::MipsGp;
template <class ELFT> DefinedRegular<ELFT> *ElfSym<ELFT>::MipsGp;
// A real symbol object, SymbolBody, is usually stored within a Symbol. There's
// always one Symbol for each symbol name. The resolver updates the SymbolBody

View File

@ -1972,10 +1972,10 @@ RelExpr MipsTargetInfo<ELFT>::getRelExpr(uint32_t Type,
case R_MIPS_HI16:
case R_MIPS_LO16:
case R_MIPS_GOT_OFST:
// MIPS _gp_disp designates offset between start of function and 'gp'
// pointer into GOT. __gnu_local_gp is equal to the current value of
// the 'gp'. Therefore any relocations against them do not require
// dynamic relocation.
// R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate
// offset between start of function and 'gp' value which by default
// equal to the start of .got section. In that case we consider these
// relocations as relative.
if (&S == ElfSym<ELFT>::MipsGpDisp)
return R_PC;
return R_ABS;

View File

@ -662,23 +662,28 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
if (Config->EMachine == EM_MIPS) {
// Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
// so that it points to an absolute address which is relative to GOT.
// Default offset is 0x7ff0.
// so that it points to an absolute address which by default is relative
// to GOT. Default offset is 0x7ff0.
// See "Global Data Symbols" in Chapter 6 in the following document:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
ElfSym<ELFT>::MipsGp = addRegular("_gp", In<ELFT>::MipsGot, 0x7ff0)->body();
ElfSym<ELFT>::MipsGp =
Symtab<ELFT>::X->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL);
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
// start of function and 'gp' pointer into GOT.
if (Symbol *S = addOptionalRegular("_gp_disp", In<ELFT>::MipsGot, 0))
ElfSym<ELFT>::MipsGpDisp = cast<DefinedRegular<ELFT>>(S->body());
// start of function and 'gp' pointer into GOT. To simplify relocation
// calculation we assign _gp value to it and calculate corresponding
// relocations as relative to this value.
if (Symtab<ELFT>::X->find("_gp_disp"))
ElfSym<ELFT>::MipsGpDisp =
Symtab<ELFT>::X->addAbsolute("_gp_disp", STV_HIDDEN, STB_LOCAL);
// The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
// pointer. This symbol is used in the code generated by .cpload pseudo-op
// in case of using -mno-shared option.
// https://sourceware.org/ml/binutils/2004-12/msg00094.html
if (Symbol *S = addOptionalRegular("__gnu_local_gp", In<ELFT>::MipsGot, 0))
ElfSym<ELFT>::MipsLocalGp = cast<DefinedRegular<ELFT>>(S->body());
if (Symtab<ELFT>::X->find("__gnu_local_gp"))
ElfSym<ELFT>::MipsLocalGp =
Symtab<ELFT>::X->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL);
}
// In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
@ -1473,11 +1478,12 @@ template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
// Setup MIPS _gp_disp/__gnu_local_gp symbols which should
// be equal to the _gp symbol's value.
if (Config->EMachine == EM_MIPS) {
uintX_t GpDisp = In<ELFT>::MipsGot->getGp() - In<ELFT>::MipsGot->getVA();
if (!ElfSym<ELFT>::MipsGp->Value)
ElfSym<ELFT>::MipsGp->Value = In<ELFT>::MipsGot->getVA() + 0x7ff0;
if (ElfSym<ELFT>::MipsGpDisp)
ElfSym<ELFT>::MipsGpDisp->Value = GpDisp;
ElfSym<ELFT>::MipsGpDisp->Value = ElfSym<ELFT>::MipsGp->Value;
if (ElfSym<ELFT>::MipsLocalGp)
ElfSym<ELFT>::MipsLocalGp->Value = GpDisp;
ElfSym<ELFT>::MipsLocalGp->Value = ElfSym<ELFT>::MipsGp->Value;
}
}

View File

@ -228,7 +228,7 @@ __start:
# CHECK-NEXT: Other [ (0x2)
# CHECK-NEXT: STV_HIDDEN (0x2)
# CHECK-NEXT: ]
# CHECK-NEXT: Section: .got
# CHECK-NEXT: Section: Absolute
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: __start

View File

@ -18,7 +18,7 @@
# CHECK-NEXT: 20010: 24 42 80 38 addiu $2, $2, -32712
# CHECK: 0000000000020014 .text 00000000 foo
# CHECK: 0000000000037ff0 .got 00000000 .hidden _gp
# CHECK: 0000000000037ff0 *ABS* 00000000 .hidden _gp
# CHECK: 0000000000020000 .text 00000000 __start
# CHECK: 0000000000000000 g F *UND* 00000000 foo1a

View File

@ -19,7 +19,7 @@
# CHECK-NEXT: 20010: 24 42 80 38 addiu $2, $2, -32712
# CHECK: 0000000000020018 .text 00000000 foo
# CHECK: 0000000000037ff0 .got 00000000 .hidden _gp
# CHECK: 0000000000037ff0 *ABS* 00000000 .hidden _gp
# CHECK: 0000000000020000 .text 00000000 __start
# CHECK: 0000000000020014 .text 00000000 bar

View File

@ -12,7 +12,7 @@
# CHECK-NEXT: 10004: 03 99 e0 2d daddu $gp, $gp, $25
# CHECK-NEXT: 10008: 67 9c 7f f0 daddiu $gp, $gp, 32752
# CHECK: 0000000000027ff0 .got 00000000 .hidden _gp
# CHECK: 0000000000027ff0 *ABS* 00000000 .hidden _gp
# CHECK: 0000000000010000 .text 00000000 foo
.text

View File

@ -24,7 +24,7 @@
# ^-- 0x20004 - 0x37ff0 = 0xfffffffffffe8014
# CHECK: 0000000000020004 .text 00000000 loc
# CHECK: 0000000000037ff0 .got 00000000 .hidden _gp
# CHECK: 0000000000037ff0 *ABS* 00000000 .hidden _gp
# CHECK: 0000000000020000 .text 00000000 __start
# REL: Relocations [

View File

@ -47,7 +47,7 @@ v1:
# EXE_SYM: Sections:
# EXE_SYM: .got 0000000c 0000000000030000 DATA
# EXE_SYM: SYMBOL TABLE:
# EXE_SYM: 00037ff0 .got 00000000 .hidden _gp
# EXE_SYM: 00037ff0 *ABS* 00000000 .hidden _gp
# ^-- .got + GP offset (0x7ff0)
# EXE_SYM: 00040000 g .data 00000004 v1
@ -71,7 +71,7 @@ v1:
# DSO_SYM: Sections:
# DSO_SYM: .got 0000000c 0000000000020000 DATA
# DSO_SYM: SYMBOL TABLE:
# DSO_SYM: 00027ff0 .got 00000000 .hidden _gp
# DSO_SYM: 00027ff0 *ABS* 00000000 .hidden _gp
# ^-- .got + GP offset (0x7ff0)
# DSO_SYM: 00030000 g .data 00000004 v1

View File

@ -24,7 +24,7 @@
# DIS-NEXT: 10000: 3c 08 00 01 lui $8, 1
# DIS-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752
# ^-- 0x37ff0 & 0xffff
# DIS: 00027ff0 .got 00000000 .hidden _gp
# DIS: 00027ff0 *ABS* 00000000 .hidden _gp
# REL: Relocations [
# REL-NEXT: ]

View File

@ -1,35 +1,67 @@
# Check that the linker use a value of _gp symbol defined
# in a linker script to calculate GOT relocations.
# FIXME: This test is xfailed because it depends on D27276 patch
# that enables absolute symbols redefinition by a linker's script.
# XFAIL: *
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
# RUN: echo "SECTIONS { \
# RUN: .text : { *(.text) } \
# RUN: _gp = . + 0x100; \
# RUN: .got : { *(.got) } }" > %t.script
# RUN: ld.lld -shared -o %t.so --script %t.script %t.o
# RUN: llvm-objdump -s -t %t.so | FileCheck %s
# RUN: .got : { *(.got) } }" > %t.rel.script
# RUN: ld.lld -shared -o %t.rel.so --script %t.rel.script %t.o
# RUN: llvm-objdump -s -t %t.rel.so | FileCheck --check-prefix=REL %s
# RUN: echo "SECTIONS { \
# RUN: .text : { *(.text) } \
# RUN: _gp = 0x200; \
# RUN: .got : { *(.got) } }" > %t.abs.script
# RUN: ld.lld -shared -o %t.abs.so --script %t.abs.script %t.o
# RUN: llvm-objdump -s -t %t.abs.so | FileCheck --check-prefix=ABS %s
# REQUIRES: mips
# CHECK: Contents of section .text:
# CHECK-NEXT: 0000 3c080000 2108010c 8f82ffe4
# REL: Contents of section .text:
# REL-NEXT: 0000 3c080000 2108010c 8f82ffe4
# ^-- %hi(_gp_disp)
# ^-- %lo(_gp_disp)
# ^-- 8 - (0x10c - 0xe8)
# G - (GP - .got)
# CHECK: Contents of section .reginfo:
# CHECK-NEXT: 0028 10000104 00000000 00000000 00000000
# CHECK-NEXT: 0038 00000000 0000010c
# REL: Contents of section .reginfo:
# REL-NEXT: 0028 10000104 00000000 00000000 00000000
# REL-NEXT: 0038 00000000 0000010c
# ^-- _gp
# CHECK: Contents of section .data:
# CHECK-NEXT: 0100 fffffef4
# REL: Contents of section .data:
# REL-NEXT: 0100 fffffef4
# ^-- 0-0x10c
# CHECK: 00000000 .text 00000000 foo
# CHECK: 0000010c .got 00000000 .hidden _gp_disp
# CHECK: 0000010c .text 00000000 .hidden _gp
# REL: 00000000 .text 00000000 foo
# REL: 0000010c *ABS* 00000000 .hidden _gp_disp
# REL: 0000010c *ABS* 00000000 .hidden _gp
# ABS: Contents of section .text:
# ABS-NEXT: 0000 3c080000 21080200 8f82fef0
# ^-- %hi(_gp_disp)
# ^-- %lo(_gp_disp)
# ^-- 8 - (0x200 - 0xe8)
# G - (GP - .got)
# ABS: Contents of section .reginfo:
# ABS-NEXT: 0028 10000104 00000000 00000000 00000000
# ABS-NEXT: 0038 00000000 00000200
# ^-- _gp
# ABS: Contents of section .data:
# ABS-NEXT: 0100 fffffe00
# ^-- 0-0x200
# ABS: 00000000 .text 00000000 foo
# ABS: 00000200 *ABS* 00000000 .hidden _gp_disp
# ABS: 00000200 *ABS* 00000000 .hidden _gp
.text
foo:

View File

@ -11,7 +11,7 @@
# CHECK-NEXT: 20000: 3c 08 00 03 lui $8, 3
# CHECK-NEXT: 20004: 21 08 7f f0 addi $8, $8, 32752
# CHECK: 00037ff0 .got 00000000 .hidden _gp
# CHECK: 00037ff0 *ABS* 00000000 .hidden _gp
.text
.globl __start

View File

@ -29,7 +29,7 @@
# DUMP: SYMBOL TABLE:
# DUMP: 00010008 .text 00000000 bar
# DUMP: 00010004 .text 00000000 foo
# DUMP: 00027ff0 .got 00000000 .hidden _gp
# DUMP: 00027ff0 *ABS* 00000000 .hidden _gp
# ERR: error: {{.*}}mips-gp0-non-zero.o: unsupported non-zero ri_gp_value

View File

@ -28,4 +28,4 @@ v1:
# CHECK: SYMBOL TABLE:
# CHECK: 00010008 .text 00000000 bar
# CHECK: 00010004 .text 00000000 foo
# CHECK: 00027ff0 .got 00000000 .hidden _gp
# CHECK: 00027ff0 *ABS* 00000000 .hidden _gp

View File

@ -34,7 +34,7 @@ bar:
# EXE: SYMBOL TABLE:
# EXE: 0002000c .text 00000000 bar
# EXE: 00037ff0 .got 00000000 .hidden _gp
# EXE: 00037ff0 *ABS* 00000000 .hidden _gp
# EXE: 00020000 .text 00000000 __start
# SO: Disassembly of section .text:
@ -51,5 +51,5 @@ bar:
# SO: SYMBOL TABLE:
# SO: 0001000c .text 00000000 bar
# SO: 00027ff0 .got 00000000 .hidden _gp
# SO: 00027ff0 *ABS* 00000000 .hidden _gp
# SO: 00010000 .text 00000000 __start

View File

@ -42,7 +42,7 @@
# ^-- loc
# CHECK: 00020004 .text 00000000 loc
# CHECK: 00037ff0 .got 00000000 .hidden _gp
# CHECK: 00037ff0 *ABS* 00000000 .hidden _gp
# CHECK: 00020000 g F .text 00000000 __start
# ELF: Format: ELF32-mips