forked from OSchip/llvm-project
[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:
parent
f4257528e9
commit
6a4eb75c46
|
@ -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));
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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: ]
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue