mirror of
https://github.com/intel/llvm.git
synced 2026-01-18 16:50:51 +08:00
[ELF][MIPS] Support MIPS TLS relocations
The patch adds one more partition to the MIPS GOT. This time it is for TLS related GOT entries. Such entries are located after 'local' and 'global' ones. We cannot get a final offset for these entries at the time of creation because we do not know size of 'local' and 'global' partitions. So we have to adjust the offset later using `getMipsTlsOffset()` method. All MIPS TLS relocations which need GOT entries operates MIPS style GOT offset - 'offset from the GOT's beginning' - MipsGPOffset constant. That is why I add new types of relocation expressions. One more difference from othe ABIs is that the MIPS ABI does not support any TLS relocation relaxations. I decided to make a separate function `handleMipsTlsRelocation` and put MIPS TLS relocation handling code there. It is similar to `handleTlsRelocation` routine and duplicates its code. But it allows to make the code cleaner and prevent pollution of the `handleTlsRelocation` by MIPS 'if' statements. Differential Revision: http://reviews.llvm.org/D21606 llvm-svn: 273569
This commit is contained in:
@@ -220,6 +220,12 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
|
||||
// should be applied to the GOT entry content not to the GOT entry offset.
|
||||
// That is why we use separate expression type.
|
||||
return Out<ELFT>::Got->getMipsGotOffset(Body, A);
|
||||
case R_MIPS_TLSGD:
|
||||
return Out<ELFT>::Got->getGlobalDynOffset(Body) +
|
||||
Out<ELFT>::Got->getMipsTlsOffset() - MipsGPOffset;
|
||||
case R_MIPS_TLSLD:
|
||||
return Out<ELFT>::Got->getTlsIndexOff() +
|
||||
Out<ELFT>::Got->getMipsTlsOffset() - MipsGPOffset;
|
||||
case R_PPC_OPD: {
|
||||
uint64_t SymVA = Body.getVA<ELFT>(A);
|
||||
// If we have an undefined weak symbol, we might get here with a symbol
|
||||
|
||||
@@ -135,6 +135,14 @@ void GotSection<ELFT>::addMipsEntry(SymbolBody &Sym, uintX_t Addend,
|
||||
MipsOutSections.insert(OutSec);
|
||||
return;
|
||||
}
|
||||
if (Sym.isTls()) {
|
||||
// GOT entries created for MIPS TLS relocations behave like
|
||||
// almost GOT entries from other ABIs. They go to the end
|
||||
// of the global offset table.
|
||||
Sym.GotIndex = Entries.size();
|
||||
Entries.push_back(&Sym);
|
||||
return;
|
||||
}
|
||||
auto AddEntry = [&](SymbolBody &S, uintX_t A, MipsGotEntries &Items) {
|
||||
if (S.isInGot() && !A)
|
||||
return;
|
||||
@@ -192,7 +200,9 @@ template <class ELFT>
|
||||
typename GotSection<ELFT>::uintX_t
|
||||
GotSection<ELFT>::getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const {
|
||||
uintX_t Off = MipsPageEntries;
|
||||
if (B.IsInGlobalMipsGot)
|
||||
if (B.isTls())
|
||||
Off += MipsLocal.size() + MipsGlobal.size() + B.GotIndex;
|
||||
else if (B.IsInGlobalMipsGot)
|
||||
Off += MipsLocal.size() + B.GotIndex;
|
||||
else if (B.isInGot())
|
||||
Off += B.GotIndex;
|
||||
@@ -204,6 +214,12 @@ GotSection<ELFT>::getMipsGotOffset(const SymbolBody &B, uintX_t Addend) const {
|
||||
return Off * sizeof(uintX_t) - MipsGPOffset;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
typename GotSection<ELFT>::uintX_t GotSection<ELFT>::getMipsTlsOffset() {
|
||||
return (MipsPageEntries + MipsLocal.size() + MipsGlobal.size()) *
|
||||
sizeof(uintX_t);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
typename GotSection<ELFT>::uintX_t
|
||||
GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const {
|
||||
@@ -355,6 +371,11 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
if (Config->Rela)
|
||||
P->r_addend = Rel.getAddend();
|
||||
P->r_offset = Rel.getOffset();
|
||||
if (Config->EMachine == EM_MIPS && Rel.getOutputSec() == Out<ELFT>::Got)
|
||||
// Dynamic relocation against MIPS GOT section make deal TLS entries
|
||||
// allocated in the end of the GOT. We need to adjust the offset to take
|
||||
// in account 'local' and 'global' GOT entries.
|
||||
P->r_offset += Out<ELFT>::Got->getMipsTlsOffset();
|
||||
P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->Mips64EL);
|
||||
}
|
||||
|
||||
|
||||
@@ -134,6 +134,10 @@ public:
|
||||
// the number of reserved entries. This method is MIPS-specific.
|
||||
unsigned getMipsLocalEntriesNum() const;
|
||||
|
||||
// Returns offset of TLS part of the MIPS GOT table. This part goes
|
||||
// after 'local' and 'global' entries.
|
||||
uintX_t getMipsTlsOffset();
|
||||
|
||||
uintX_t getTlsIndexVA() { return Base::getVA() + TlsIndexOff; }
|
||||
uint32_t getTlsIndexOff() { return TlsIndexOff; }
|
||||
|
||||
@@ -215,6 +219,7 @@ public:
|
||||
uintX_t getOffset() const;
|
||||
uintX_t getAddend() const;
|
||||
uint32_t getSymIndex() const;
|
||||
const OutputSectionBase<ELFT> *getOutputSec() const { return OutputSec; }
|
||||
|
||||
uint32_t Type;
|
||||
|
||||
|
||||
@@ -60,7 +60,8 @@ namespace elf {
|
||||
|
||||
static bool refersToGotEntry(RelExpr Expr) {
|
||||
return Expr == R_GOT || Expr == R_GOT_OFF || Expr == R_MIPS_GOT_LOCAL_PAGE ||
|
||||
Expr == R_MIPS_GOT_OFF || Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC ||
|
||||
Expr == R_MIPS_GOT_OFF || Expr == R_MIPS_TLSGD ||
|
||||
Expr == R_MIPS_TLSLD || Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC ||
|
||||
Expr == R_GOT_FROM_END || Expr == R_TLSGD || Expr == R_TLSGD_PC ||
|
||||
Expr == R_TLSDESC || Expr == R_TLSDESC_PAGE;
|
||||
}
|
||||
@@ -81,6 +82,39 @@ static bool isPreemptible(const SymbolBody &Body, uint32_t Type) {
|
||||
return Body.isPreemptible();
|
||||
}
|
||||
|
||||
// This function is similar to the `handleTlsRelocation`. MIPS does not support
|
||||
// any relaxations for TLS relocations so by factoring out MIPS handling into
|
||||
// the separate function we can simplify the code and does not pollute
|
||||
// `handleTlsRelocation` by MIPS `ifs` statements.
|
||||
template <class ELFT>
|
||||
static unsigned
|
||||
handleMipsTlsRelocation(uint32_t Type, SymbolBody &Body,
|
||||
InputSectionBase<ELFT> &C, typename ELFT::uint Offset,
|
||||
typename ELFT::uint Addend, RelExpr Expr) {
|
||||
if (Expr == R_MIPS_TLSLD) {
|
||||
if (Out<ELFT>::Got->addTlsIndex())
|
||||
Out<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, Out<ELFT>::Got,
|
||||
Out<ELFT>::Got->getTlsIndexOff(), false,
|
||||
nullptr, 0});
|
||||
C.Relocations.push_back({Expr, Type, &C, Offset, Addend, &Body});
|
||||
return 1;
|
||||
}
|
||||
if (Target->isTlsGlobalDynamicRel(Type)) {
|
||||
if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
|
||||
typedef typename ELFT::uint uintX_t;
|
||||
uintX_t Off = Out<ELFT>::Got->getGlobalDynOffset(Body);
|
||||
Out<ELFT>::RelaDyn->addReloc(
|
||||
{Target->TlsModuleIndexRel, Out<ELFT>::Got, Off, false, &Body, 0});
|
||||
Out<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, Out<ELFT>::Got,
|
||||
Off + (uintX_t)sizeof(uintX_t), false,
|
||||
&Body, 0});
|
||||
}
|
||||
C.Relocations.push_back({Expr, Type, &C, Offset, Addend, &Body});
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the number of relocations processed.
|
||||
template <class ELFT>
|
||||
static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
|
||||
@@ -95,6 +129,9 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
|
||||
|
||||
typedef typename ELFT::uint uintX_t;
|
||||
|
||||
if (Config->EMachine == EM_MIPS)
|
||||
return handleMipsTlsRelocation<ELFT>(Type, Body, C, Offset, Addend, Expr);
|
||||
|
||||
if ((Expr == R_TLSDESC || Expr == R_TLSDESC_PAGE || Expr == R_HINT) &&
|
||||
Config->Shared) {
|
||||
if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
|
||||
@@ -254,9 +291,9 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type,
|
||||
const SymbolBody &Body) {
|
||||
// These expressions always compute a constant
|
||||
if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF ||
|
||||
E == R_MIPS_GOT_LOCAL_PAGE || E == R_MIPS_GOT_OFF || E == R_GOT_PAGE_PC ||
|
||||
E == R_GOT_PC || E == R_PLT_PC || E == R_TLSGD_PC || E == R_TLSGD ||
|
||||
E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE || E == R_HINT)
|
||||
E == R_MIPS_GOT_LOCAL_PAGE || E == R_MIPS_GOT_OFF || E == R_MIPS_TLSGD ||
|
||||
E == R_GOT_PAGE_PC || E == R_GOT_PC || E == R_PLT_PC || E == R_TLSGD_PC ||
|
||||
E == R_TLSGD || E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE || E == R_HINT)
|
||||
return true;
|
||||
|
||||
// These never do, except if the entire file is position dependent or if
|
||||
@@ -603,6 +640,9 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
|
||||
// for detailed description:
|
||||
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
||||
Out<ELFT>::Got->addMipsEntry(Body, Addend, Expr);
|
||||
if (Body.isTls())
|
||||
AddDyn({Target->TlsGotRel, Out<ELFT>::Got, Body.getGotOffset<ELFT>(),
|
||||
!Preemptible, &Body, 0});
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ enum RelExpr {
|
||||
R_HINT,
|
||||
R_MIPS_GOT_LOCAL_PAGE,
|
||||
R_MIPS_GOT_OFF,
|
||||
R_MIPS_TLSGD,
|
||||
R_MIPS_TLSLD,
|
||||
R_NEG_TLS,
|
||||
R_PAGE_PC,
|
||||
R_PC,
|
||||
|
||||
@@ -190,6 +190,8 @@ public:
|
||||
RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const override;
|
||||
uint64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override;
|
||||
uint32_t getDynRel(uint32_t Type) const override;
|
||||
bool isTlsLocalDynamicRel(uint32_t Type) const override;
|
||||
bool isTlsGlobalDynamicRel(uint32_t Type) const override;
|
||||
void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override;
|
||||
void writePltHeader(uint8_t *Buf) const override;
|
||||
void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
|
||||
@@ -1706,10 +1708,17 @@ template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
|
||||
ThunkSize = 16;
|
||||
CopyRel = R_MIPS_COPY;
|
||||
PltRel = R_MIPS_JUMP_SLOT;
|
||||
if (ELFT::Is64Bits)
|
||||
if (ELFT::Is64Bits) {
|
||||
RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32;
|
||||
else
|
||||
TlsGotRel = R_MIPS_TLS_TPREL64;
|
||||
TlsModuleIndexRel = R_MIPS_TLS_DTPMOD64;
|
||||
TlsOffsetRel = R_MIPS_TLS_DTPREL64;
|
||||
} else {
|
||||
RelativeRel = R_MIPS_REL32;
|
||||
TlsGotRel = R_MIPS_TLS_TPREL32;
|
||||
TlsModuleIndexRel = R_MIPS_TLS_DTPMOD32;
|
||||
TlsOffsetRel = R_MIPS_TLS_DTPREL32;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
@@ -1752,9 +1761,14 @@ RelExpr MipsTargetInfo<ELFT>::getRelExpr(uint32_t Type,
|
||||
// fallthrough
|
||||
case R_MIPS_CALL16:
|
||||
case R_MIPS_GOT_DISP:
|
||||
case R_MIPS_TLS_GOTTPREL:
|
||||
return R_MIPS_GOT_OFF;
|
||||
case R_MIPS_GOT_PAGE:
|
||||
return R_MIPS_GOT_LOCAL_PAGE;
|
||||
case R_MIPS_TLS_GD:
|
||||
return R_MIPS_TLSGD;
|
||||
case R_MIPS_TLS_LDM:
|
||||
return R_MIPS_TLSLD;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1767,6 +1781,16 @@ uint32_t MipsTargetInfo<ELFT>::getDynRel(uint32_t Type) const {
|
||||
return R_MIPS_32;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
bool MipsTargetInfo<ELFT>::isTlsLocalDynamicRel(uint32_t Type) const {
|
||||
return Type == R_MIPS_TLS_LDM;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
bool MipsTargetInfo<ELFT>::isTlsGlobalDynamicRel(uint32_t Type) const {
|
||||
return Type == R_MIPS_TLS_GD;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void MipsTargetInfo<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
|
||||
write32<ELFT::TargetEndianness>(Buf, Out<ELFT>::Plt->getVA());
|
||||
@@ -1961,6 +1985,8 @@ void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type,
|
||||
case R_MIPS_GOT_PAGE:
|
||||
case R_MIPS_GOT16:
|
||||
case R_MIPS_GPREL16:
|
||||
case R_MIPS_TLS_GD:
|
||||
case R_MIPS_TLS_LDM:
|
||||
checkInt<16>(Val, Type);
|
||||
// fallthrough
|
||||
case R_MIPS_CALL16:
|
||||
@@ -1968,6 +1994,7 @@ void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type,
|
||||
case R_MIPS_LO16:
|
||||
case R_MIPS_PCLO16:
|
||||
case R_MIPS_TLS_DTPREL_LO16:
|
||||
case R_MIPS_TLS_GOTTPREL:
|
||||
case R_MIPS_TLS_TPREL_LO16:
|
||||
writeMipsLo16<E>(Loc, Val);
|
||||
break;
|
||||
|
||||
5
lld/test/ELF/Inputs/mips-tls.s
Normal file
5
lld/test/ELF/Inputs/mips-tls.s
Normal file
@@ -0,0 +1,5 @@
|
||||
.globl foo
|
||||
.section .tdata,"awT",%progbits
|
||||
.type foo, %object
|
||||
foo:
|
||||
.word 0
|
||||
86
lld/test/ELF/mips-tls-64.s
Normal file
86
lld/test/ELF/mips-tls-64.s
Normal file
@@ -0,0 +1,86 @@
|
||||
# Check MIPS TLS 64-bit relocations handling.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \
|
||||
# RUN: %p/Inputs/mips-dynamic.s -o %t.so.o
|
||||
# RUN: ld.lld -shared %t.so.o -o %t.so
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
|
||||
# RUN: ld.lld %t.o %t.so -o %t.exe
|
||||
# RUN: llvm-objdump -d -s -t %t.exe | FileCheck -check-prefix=DIS %s
|
||||
# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s
|
||||
|
||||
# REQUIRES: mips
|
||||
|
||||
# DIS: __start:
|
||||
# DIS-NEXT: 20000: 24 62 80 28 addiu $2, $3, -32728
|
||||
# DIS-NEXT: 20004: 24 62 80 38 addiu $2, $3, -32712
|
||||
# DIS-NEXT: 20008: 8f 82 80 20 lw $2, -32736($gp)
|
||||
# DIS-NEXT: 2000c: 24 62 80 48 addiu $2, $3, -32696
|
||||
|
||||
# DIS: Contents of section .got:
|
||||
# DIS_NEXT: 30008 00000000 00000000 80000000 00000000
|
||||
# DIS_NEXT: 30018 00000000 00020000 00000000 00000000
|
||||
# DIS_NEXT: 30028 00000000 00000004 00000000 00000000
|
||||
# DIS_NEXT: 30038 00000000 00000000 00000000 00000004
|
||||
|
||||
# DIS: 0000000000030000 l .tdata 00000000 .tdata
|
||||
# DIS: 0000000000030000 l .tdata 00000000 loc
|
||||
# DIS: 0000000000000004 g .tdata 00000000 foo
|
||||
|
||||
# CHECK: Relocations [
|
||||
# CHECK-NEXT: Section (7) .rela.dyn {
|
||||
# CHECK-NEXT: 0x30020 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE - 0x0
|
||||
# CHECK-NEXT: 0x30028 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE - 0x0
|
||||
# CHECK-NEXT: 0x30030 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE - 0x0
|
||||
# CHECK-NEXT: 0x30040 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE - 0x4
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Primary GOT {
|
||||
# CHECK-NEXT: Canonical gp value: 0x37FF8
|
||||
# CHECK-NEXT: Reserved entries [
|
||||
# CHECK-NEXT: Entry {
|
||||
# CHECK-NEXT: Address: 0x30008
|
||||
# CHECK-NEXT: Access: -32752
|
||||
# CHECK-NEXT: Initial: 0x0
|
||||
# CHECK-NEXT: Purpose: Lazy resolver
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Entry {
|
||||
# CHECK-NEXT: Address: 0x30010
|
||||
# CHECK-NEXT: Access: -32744
|
||||
# CHECK-NEXT: Initial: 0x80000000
|
||||
# CHECK-NEXT: Purpose: Module pointer (GNU extension)
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Local entries [
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Global entries [
|
||||
# CHECK-NEXT: Entry {
|
||||
# CHECK-NEXT: Address: 0x30018
|
||||
# CHECK-NEXT: Access: -32736
|
||||
# CHECK-NEXT: Initial: 0x0
|
||||
# CHECK-NEXT: Value: 0x0
|
||||
# CHECK-NEXT: Type: Function
|
||||
# CHECK-NEXT: Section: Undefined
|
||||
# CHECK-NEXT: Name: foo0
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Number of TLS and multi-GOT entries: 5
|
||||
# ^-- 0x30020 / -32728 - R_MIPS_TLS_GD - R_MIPS_TLS_DTPMOD32 foo
|
||||
# ^-- 0x30028 / -32720 - R_MIPS_TLS_DTPREL32 foo
|
||||
# ^-- 0x30030 / -32712 - R_MIPS_TLS_LDM - R_MIPS_TLS_DTPMOD32 loc
|
||||
# ^-- 0x30038 / -32704
|
||||
# ^-- 0x30040 / -32696 - R_MIPS_TLS_GOTTPREL - R_MIPS_TLS_TPREL32
|
||||
|
||||
.text
|
||||
.global __start
|
||||
__start:
|
||||
addiu $2, $3, %tlsgd(foo) # R_MIPS_TLS_GD
|
||||
addiu $2, $3, %tlsldm(loc) # R_MIPS_TLS_LDM
|
||||
lw $2, %got(foo0)($gp)
|
||||
addiu $2, $3, %gottprel(foo) # R_MIPS_TLS_GOTTPREL
|
||||
|
||||
.section .tdata,"awT",%progbits
|
||||
.global foo
|
||||
loc:
|
||||
.word 0
|
||||
foo:
|
||||
.word 0
|
||||
77
lld/test/ELF/mips-tls.s
Normal file
77
lld/test/ELF/mips-tls.s
Normal file
@@ -0,0 +1,77 @@
|
||||
# Check MIPS TLS relocations handling.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
|
||||
# RUN: %p/Inputs/mips-tls.s -o %t.so.o
|
||||
# RUN: ld.lld -shared %t.so.o -o %t.so
|
||||
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
|
||||
# RUN: ld.lld %t.o %t.so -o %t.exe
|
||||
# RUN: llvm-objdump -d -s -t %t.exe | FileCheck -check-prefix=DIS %s
|
||||
# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s
|
||||
|
||||
# REQUIRES: mips
|
||||
|
||||
# DIS: __start:
|
||||
# DIS-NEXT: 20000: 24 62 80 1c addiu $2, $3, -32740
|
||||
# DIS-NEXT: 20004: 24 62 80 24 addiu $2, $3, -32732
|
||||
# DIS-NEXT: 20008: 8f 82 80 18 lw $2, -32744($gp)
|
||||
# DIS-NEXT: 2000c: 24 62 80 2c addiu $2, $3, -32724
|
||||
|
||||
# DIS: Contents of section .got:
|
||||
# DIS_NEXT: 30004 00000000 80000000 00020000 00000000
|
||||
# DIS_NEXT: 30014 00000000 00000000 00000000 00000000
|
||||
|
||||
# DIS: 00030000 l .tdata 00000000 .tdata
|
||||
# DIS: 00030000 l .tdata 00000000 loc
|
||||
# DIS: 00000000 g *UND* 00000000 foo
|
||||
|
||||
# CHECK: Relocations [
|
||||
# CHECK-NEXT: Section (7) .rel.dyn {
|
||||
# CHECK-NEXT: 0x30018 R_MIPS_TLS_DTPMOD32 - 0x0
|
||||
# CHECK-NEXT: 0x30010 R_MIPS_TLS_DTPMOD32 foo 0x0
|
||||
# CHECK-NEXT: 0x30014 R_MIPS_TLS_DTPREL32 foo 0x0
|
||||
# CHECK-NEXT: 0x30020 R_MIPS_TLS_TPREL32 foo 0x0
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Primary GOT {
|
||||
# CHECK-NEXT: Canonical gp value: 0x37FF4
|
||||
# CHECK-NEXT: Reserved entries [
|
||||
# CHECK-NEXT: Entry {
|
||||
# CHECK-NEXT: Address: 0x30004
|
||||
# CHECK-NEXT: Access: -32752
|
||||
# CHECK-NEXT: Initial: 0x0
|
||||
# CHECK-NEXT: Purpose: Lazy resolver
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: Entry {
|
||||
# CHECK-NEXT: Address: 0x30008
|
||||
# CHECK-NEXT: Access: -32748
|
||||
# CHECK-NEXT: Initial: 0x80000000
|
||||
# CHECK-NEXT: Purpose: Module pointer (GNU extension)
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Local entries [
|
||||
# CHECK-NEXT: Entry {
|
||||
# CHECK-NEXT: Address: 0x3000C
|
||||
# CHECK-NEXT: Access: -32744
|
||||
# CHECK-NEXT: Initial: 0x20000
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Global entries [
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Number of TLS and multi-GOT entries: 5
|
||||
# ^-- 0x30010 / -32740 - R_MIPS_TLS_GD - R_MIPS_TLS_DTPMOD32 foo
|
||||
# ^-- 0x30018 / -32736 - R_MIPS_TLS_DTPREL32 foo
|
||||
# ^-- 0x3001C / -32732 - R_MIPS_TLS_LDM - R_MIPS_TLS_DTPMOD32 loc
|
||||
# ^-- 0x30020 / -32728
|
||||
# ^-- 0x30024 / -32724 - R_MIPS_TLS_GOTTPREL - R_MIPS_TLS_TPREL32
|
||||
|
||||
.text
|
||||
.global __start
|
||||
__start:
|
||||
addiu $2, $3, %tlsgd(foo) # R_MIPS_TLS_GD
|
||||
addiu $2, $3, %tlsldm(loc) # R_MIPS_TLS_LDM
|
||||
lw $2, %got(__start)($gp)
|
||||
addiu $2, $3, %gottprel(foo) # R_MIPS_TLS_GOTTPREL
|
||||
|
||||
.section .tdata,"awT",%progbits
|
||||
loc:
|
||||
.word 0
|
||||
Reference in New Issue
Block a user