forked from OSchip/llvm-project
[ELF] - implemented @indntpoff (x86) relocation and its optimization.
@indntpoff is similar to @gotntpoff, but for use in position dependent code. While @gotntpoff resolves to GOT slot address relative to the start of the GOT in the movl or addl instructions, @indntpoff resolves to the absolute GOT slot address. ("ELF Handling For Thread-Local Storage", Ulrich Drepper). Differential revision: http://reviews.llvm.org/D15494 llvm-svn: 255884
This commit is contained in:
parent
003be4fd58
commit
6f17e09307
|
@ -198,11 +198,11 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
|||
} else if (Target->relocNeedsGot(Type, Body)) {
|
||||
SymVA = Out<ELFT>::Got->getEntryAddr(Body);
|
||||
if (Body.isTls())
|
||||
Type = Target->getTlsGotReloc();
|
||||
Type = Target->getTlsGotReloc(Type);
|
||||
} else if (!Target->needsCopyRel(Type, Body) &&
|
||||
isa<SharedSymbol<ELFT>>(Body)) {
|
||||
continue;
|
||||
} else if (Target->isTlsDynReloc(Type) ||
|
||||
} else if (Target->isTlsDynReloc(Type, Body) ||
|
||||
Target->isSizeDynReloc(Type, Body)) {
|
||||
continue;
|
||||
} else if (Config->EMachine == EM_MIPS) {
|
||||
|
|
|
@ -263,10 +263,11 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
bool CanBePreempted = canBePreempted(Body, NeedsGot);
|
||||
bool LazyReloc = Body && Target->supportsLazyRelocations() &&
|
||||
Target->relocNeedsPlt(Type, *Body);
|
||||
bool IsDynRelative = Type == Target->getRelativeReloc();
|
||||
|
||||
unsigned Sym = CanBePreempted ? Body->DynamicSymbolTableIndex : 0;
|
||||
unsigned Reloc;
|
||||
if (!CanBePreempted)
|
||||
if (!CanBePreempted || IsDynRelative)
|
||||
Reloc = Target->getRelativeReloc();
|
||||
else if (LazyReloc)
|
||||
Reloc = Target->getPltReloc();
|
||||
|
@ -297,7 +298,7 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
uintX_t Addend;
|
||||
if (NeedsCopy)
|
||||
Addend = 0;
|
||||
else if (CanBePreempted)
|
||||
else if (CanBePreempted || IsDynRelative)
|
||||
Addend = OrigAddend;
|
||||
else if (Body)
|
||||
Addend = getSymVA<ELFT>(cast<ELFSymbolBody<ELFT>>(*Body)) + OrigAddend;
|
||||
|
|
|
@ -76,7 +76,8 @@ public:
|
|||
X86TargetInfo();
|
||||
void writeGotPltHeaderEntries(uint8_t *Buf) const override;
|
||||
unsigned getDynReloc(unsigned Type) const override;
|
||||
bool isTlsDynReloc(unsigned Type) const override;
|
||||
unsigned getTlsGotReloc(unsigned Type) const override;
|
||||
bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
|
||||
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
|
||||
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
|
||||
uint64_t PltEntryAddr) const override;
|
||||
|
@ -84,6 +85,7 @@ public:
|
|||
uint64_t PltEntryAddr, int32_t Index,
|
||||
unsigned RelOff) const override;
|
||||
bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
|
||||
bool relocNeedsDynRelative(unsigned Type) const override;
|
||||
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
|
||||
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
|
||||
void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
|
||||
|
@ -101,15 +103,15 @@ private:
|
|||
uint64_t SA) const;
|
||||
void relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
|
||||
uint64_t SA) const;
|
||||
void relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
|
||||
uint64_t SA) const;
|
||||
void relocateTlsIeToLe(unsigned Type, uint8_t *Loc, uint8_t *BufEnd,
|
||||
uint64_t P, uint64_t SA) const;
|
||||
};
|
||||
|
||||
class X86_64TargetInfo final : public TargetInfo {
|
||||
public:
|
||||
X86_64TargetInfo();
|
||||
unsigned getPltRefReloc(unsigned Type) const override;
|
||||
bool isTlsDynReloc(unsigned Type) const override;
|
||||
bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
|
||||
void writeGotPltHeaderEntries(uint8_t *Buf) const override;
|
||||
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
|
||||
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
|
||||
|
@ -253,6 +255,7 @@ X86TargetInfo::X86TargetInfo() {
|
|||
PCRelReloc = R_386_PC32;
|
||||
GotReloc = R_386_GLOB_DAT;
|
||||
PltReloc = R_386_JUMP_SLOT;
|
||||
RelativeReloc = R_386_RELATIVE;
|
||||
TlsGotReloc = R_386_TLS_TPOFF;
|
||||
TlsGlobalDynamicReloc = R_386_TLS_GD;
|
||||
TlsLocalDynamicReloc = R_386_TLS_LDM;
|
||||
|
@ -280,10 +283,18 @@ unsigned X86TargetInfo::getDynReloc(unsigned Type) const {
|
|||
return Type;
|
||||
}
|
||||
|
||||
bool X86TargetInfo::isTlsDynReloc(unsigned Type) const {
|
||||
unsigned X86TargetInfo::getTlsGotReloc(unsigned Type) const {
|
||||
if (Type == R_386_TLS_IE)
|
||||
return Type;
|
||||
return TlsGotReloc;
|
||||
}
|
||||
|
||||
bool X86TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
|
||||
if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 ||
|
||||
Type == R_386_TLS_GOTIE)
|
||||
return Config->Shared;
|
||||
if (Type == R_386_TLS_IE)
|
||||
return canBePreempted(&S, true);
|
||||
return Type == R_386_TLS_GD;
|
||||
}
|
||||
|
||||
|
@ -337,7 +348,7 @@ bool X86TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
|
|||
bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
|
||||
if (S.isTls() && Type == R_386_TLS_GD)
|
||||
return Target->isTlsOptimized(Type, &S) && canBePreempted(&S, true);
|
||||
if (Type == R_386_TLS_GOTIE)
|
||||
if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
|
||||
return !isTlsOptimized(Type, &S);
|
||||
return Type == R_386_GOT32 || relocNeedsPlt(Type, S);
|
||||
}
|
||||
|
@ -373,6 +384,7 @@ void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
|||
write32le(Loc, V);
|
||||
break;
|
||||
}
|
||||
case R_386_TLS_IE:
|
||||
case R_386_TLS_LDO_32:
|
||||
write32le(Loc, SA);
|
||||
break;
|
||||
|
@ -392,9 +404,14 @@ bool X86TargetInfo::isTlsOptimized(unsigned Type, const SymbolBody *S) const {
|
|||
return false;
|
||||
return Type == R_386_TLS_LDO_32 || Type == R_386_TLS_LDM ||
|
||||
Type == R_386_TLS_GD ||
|
||||
(Type == R_386_TLS_IE && !canBePreempted(S, true)) ||
|
||||
(Type == R_386_TLS_GOTIE && !canBePreempted(S, true));
|
||||
}
|
||||
|
||||
bool X86TargetInfo::relocNeedsDynRelative(unsigned Type) const {
|
||||
return Config->Shared && Type == R_386_TLS_IE;
|
||||
}
|
||||
|
||||
unsigned X86TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
|
||||
uint32_t Type, uint64_t P,
|
||||
uint64_t SA,
|
||||
|
@ -408,7 +425,8 @@ unsigned X86TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
|
|||
// The next relocation should be against __tls_get_addr, so skip it
|
||||
return 1;
|
||||
case R_386_TLS_GOTIE:
|
||||
relocateTlsIeToLe(Loc, BufEnd, P, SA);
|
||||
case R_386_TLS_IE:
|
||||
relocateTlsIeToLe(Type, Loc, BufEnd, P, SA);
|
||||
return 0;
|
||||
case R_386_TLS_LDM:
|
||||
relocateTlsLdToLe(Loc, BufEnd, P, SA);
|
||||
|
@ -478,27 +496,47 @@ void X86TargetInfo::relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
|
|||
memcpy(Loc - 2, Inst, sizeof(Inst));
|
||||
}
|
||||
|
||||
// In some conditions, R_386_TLS_GOTIE relocation can be optimized to
|
||||
// R_386_TLS_LE so that it does not use GOT.
|
||||
// This function does that. Read "ELF Handling For Thread-Local Storage,
|
||||
// 5.1 IA-32 Linker Optimizations" (http://www.akkadia.org/drepper/tls.pdf)
|
||||
// In some conditions, relocations can be optimized to avoid using GOT.
|
||||
// This function does that for Initial Exec to Local Exec case.
|
||||
// Read "ELF Handling For Thread-Local Storage, 5.1
|
||||
// IA-32 Linker Optimizations" (http://www.akkadia.org/drepper/tls.pdf)
|
||||
// by Ulrich Drepper for details.
|
||||
void X86TargetInfo::relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
|
||||
void X86TargetInfo::relocateTlsIeToLe(unsigned Type, uint8_t *Loc,
|
||||
uint8_t *BufEnd, uint64_t P,
|
||||
uint64_t SA) const {
|
||||
// Ulrich's document section 6.2 says that @gotntpoff can be
|
||||
// used with MOVL or ADDL instructions.
|
||||
// "MOVL foo@GOTTPOFF(%RIP), %REG" is transformed to "MOVL $foo, %REG".
|
||||
// "ADDL foo@GOTNTPOFF(%RIP), %REG" is transformed to "LEAL foo(%REG), %REG"
|
||||
// Note: gold converts to ADDL instead of LEAL.
|
||||
// Ulrich's document section 6.2 says that @gotntpoff can
|
||||
// be used with MOVL or ADDL instructions.
|
||||
// @indntpoff is similar to @gotntpoff, but for use in
|
||||
// position dependent code.
|
||||
uint8_t *Inst = Loc - 2;
|
||||
uint8_t *RegSlot = Loc - 1;
|
||||
uint8_t *Op = Loc - 1;
|
||||
uint8_t Reg = (Loc[-1] >> 3) & 7;
|
||||
bool IsMov = *Inst == 0x8b;
|
||||
*Inst = IsMov ? 0xc7 : 0x8d;
|
||||
if (IsMov)
|
||||
*RegSlot = 0xc0 | ((*RegSlot >> 3) & 7);
|
||||
else
|
||||
*RegSlot = 0x80 | Reg | (Reg << 3);
|
||||
if (Type == R_386_TLS_IE) {
|
||||
// For R_386_TLS_IE relocation we perform the next transformations:
|
||||
// MOVL foo@INDNTPOFF,%EAX is transformed to MOVL $foo,%EAX
|
||||
// MOVL foo@INDNTPOFF,%REG is transformed to MOVL $foo,%REG
|
||||
// ADDL foo@INDNTPOFF,%REG is transformed to ADDL $foo,%REG
|
||||
// First one is special because when EAX is used the sequence is 5 bytes
|
||||
// long, otherwise it is 6 bytes.
|
||||
if (*Op == 0xa1) {
|
||||
*Op = 0xb8;
|
||||
} else {
|
||||
*Inst = IsMov ? 0xc7 : 0x81;
|
||||
*Op = 0xc0 | ((*Op >> 3) & 7);
|
||||
}
|
||||
} else {
|
||||
// R_386_TLS_GOTIE relocation can be optimized to
|
||||
// R_386_TLS_LE so that it does not use GOT.
|
||||
// "MOVL foo@GOTTPOFF(%RIP), %REG" is transformed to "MOVL $foo, %REG".
|
||||
// "ADDL foo@GOTNTPOFF(%RIP), %REG" is transformed to "LEAL foo(%REG), %REG"
|
||||
// Note: gold converts to ADDL instead of LEAL.
|
||||
*Inst = IsMov ? 0xc7 : 0x8d;
|
||||
if (IsMov)
|
||||
*Op = 0xc0 | ((*Op >> 3) & 7);
|
||||
else
|
||||
*Op = 0x80 | Reg | (Reg << 3);
|
||||
}
|
||||
relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA);
|
||||
}
|
||||
|
||||
|
@ -571,7 +609,7 @@ bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
|
|||
return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S);
|
||||
}
|
||||
|
||||
bool X86_64TargetInfo::isTlsDynReloc(unsigned Type) const {
|
||||
bool X86_64TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
|
||||
return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ public:
|
|||
unsigned getGotReloc() const { return GotReloc; }
|
||||
unsigned getPltReloc() const { return PltReloc; }
|
||||
unsigned getRelativeReloc() const { return RelativeReloc; }
|
||||
unsigned getTlsGotReloc() const { return TlsGotReloc; }
|
||||
bool isTlsLocalDynamicReloc(unsigned Type) const {
|
||||
return Type == TlsLocalDynamicReloc;
|
||||
}
|
||||
|
@ -42,8 +41,13 @@ public:
|
|||
unsigned getGotHeaderEntriesNum() const { return GotHeaderEntriesNum; }
|
||||
unsigned getGotPltHeaderEntriesNum() const { return GotPltHeaderEntriesNum; }
|
||||
virtual unsigned getDynReloc(unsigned Type) const { return Type; }
|
||||
virtual bool isTlsDynReloc(unsigned Type) const { return false; }
|
||||
virtual bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
|
||||
return false;
|
||||
}
|
||||
virtual unsigned getPltRefReloc(unsigned Type) const;
|
||||
virtual unsigned getTlsGotReloc(unsigned Type = -1) const {
|
||||
return TlsGotReloc;
|
||||
}
|
||||
virtual void writeGotHeaderEntries(uint8_t *Buf) const;
|
||||
virtual void writeGotPltHeaderEntries(uint8_t *Buf) const;
|
||||
virtual void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const = 0;
|
||||
|
@ -54,6 +58,7 @@ public:
|
|||
int32_t Index, unsigned RelOff) const = 0;
|
||||
virtual bool isRelRelative(uint32_t Type) const;
|
||||
virtual bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) const;
|
||||
virtual bool relocNeedsDynRelative(unsigned Type) const { return false; }
|
||||
virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
|
||||
virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0;
|
||||
virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
||||
|
|
|
@ -236,9 +236,16 @@ void Writer<ELFT>::scanRelocs(
|
|||
continue;
|
||||
}
|
||||
|
||||
if (Body && Body->isTls() && !Target->isTlsDynReloc(Type))
|
||||
if (Body && Body->isTls() && !Target->isTlsDynReloc(Type, *Body))
|
||||
continue;
|
||||
|
||||
if (Target->relocNeedsDynRelative(Type)) {
|
||||
RelType *Rel = new (Alloc) RelType;
|
||||
Rel->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL);
|
||||
Rel->r_offset = RI.r_offset;
|
||||
Out<ELFT>::RelaDyn->addReloc({&C, Rel});
|
||||
}
|
||||
|
||||
bool NeedsGot = false;
|
||||
bool NeedsPlt = false;
|
||||
if (Body) {
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
.type tlsshared0,@object
|
||||
.section .tbss,"awT",@nobits
|
||||
.globl tlsshared0
|
||||
.align 4
|
||||
tlsshared0:
|
||||
.long 0
|
||||
.size tlsshared0, 4
|
||||
|
||||
.type tlsshared1,@object
|
||||
.section .tbss,"awT",@nobits
|
||||
.globl tlsshared1
|
||||
.align 4
|
||||
tlsshared1:
|
||||
.long 0
|
||||
.size tlsshared1, 4
|
|
@ -0,0 +1,159 @@
|
|||
// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
|
||||
// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o
|
||||
// RUN: ld.lld -shared %tso.o -o %tso
|
||||
// RUN: ld.lld %t.o %tso -o %t1
|
||||
// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTREL %s
|
||||
// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
|
||||
// RUN: ld.lld -shared %t.o %tso -o %t1
|
||||
// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTRELSHARED %s
|
||||
// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s
|
||||
|
||||
// GOTREL: Section {
|
||||
// GOTREL: Index:
|
||||
// GOTREL: Name: .got
|
||||
// GOTREL-NEXT: Type: SHT_PROGBITS
|
||||
// GOTREL-NEXT: Flags [
|
||||
// GOTREL-NEXT: SHF_ALLOC
|
||||
// GOTREL-NEXT: SHF_WRITE
|
||||
// GOTREL-NEXT: ]
|
||||
// GOTREL-NEXT: Address: 0x12050
|
||||
// GOTREL-NEXT: Offset: 0x2050
|
||||
// GOTREL-NEXT: Size: 8
|
||||
// GOTREL-NEXT: Link: 0
|
||||
// GOTREL-NEXT: Info: 0
|
||||
// GOTREL-NEXT: AddressAlignment: 4
|
||||
// GOTREL-NEXT: EntrySize: 0
|
||||
// GOTREL-NEXT: }
|
||||
// GOTREL: Relocations [
|
||||
// GOTREL-NEXT: Section ({{.*}}) .rel.dyn {
|
||||
// GOTREL-NEXT: 0x12050 R_386_TLS_TPOFF tlsshared0 0x0
|
||||
// GOTREL-NEXT: 0x12054 R_386_TLS_TPOFF tlsshared1 0x0
|
||||
// GOTREL-NEXT: }
|
||||
// GOTREL-NEXT: ]
|
||||
|
||||
// DISASM: Disassembly of section .text:
|
||||
// DISASM-NEXT: _start:
|
||||
// 4294967288 = 0xFFFFFFF8
|
||||
// 4294967292 = 0xFFFFFFFC
|
||||
// 73808 = (.got)[0] = 0x12050
|
||||
// 73812 = (.got)[1] = 0x12054
|
||||
// DISASM-NEXT: 11000: c7 c1 f8 ff ff ff movl $4294967288, %ecx
|
||||
// DISASM-NEXT: 11006: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASM-NEXT: 11009: b8 f8 ff ff ff movl $4294967288, %eax
|
||||
// DISASM-NEXT: 1100e: 65 8b 00 movl %gs:(%eax), %eax
|
||||
// DISASM-NEXT: 11011: 81 c1 f8 ff ff ff addl $4294967288, %ecx
|
||||
// DISASM-NEXT: 11017: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASM-NEXT: 1101a: c7 c1 fc ff ff ff movl $4294967292, %ecx
|
||||
// DISASM-NEXT: 11020: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASM-NEXT: 11023: b8 fc ff ff ff movl $4294967292, %eax
|
||||
// DISASM-NEXT: 11028: 65 8b 00 movl %gs:(%eax), %eax
|
||||
// DISASM-NEXT: 1102b: 81 c1 fc ff ff ff addl $4294967292, %ecx
|
||||
// DISASM-NEXT: 11031: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASM-NEXT: 11034: 8b 0d 50 20 01 00 movl 73808, %ecx
|
||||
// DISASM-NEXT: 1103a: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASM-NEXT: 1103d: 03 0d 54 20 01 00 addl 73812, %ecx
|
||||
// DISASM-NEXT: 11043: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
|
||||
// GOTRELSHARED: Section {
|
||||
// GOTRELSHARED: Index: 8
|
||||
// GOTRELSHARED: Name: .got
|
||||
// GOTRELSHARED-NEXT: Type: SHT_PROGBITS
|
||||
// GOTRELSHARED-NEXT: Flags [
|
||||
// GOTRELSHARED-NEXT: SHF_ALLOC
|
||||
// GOTRELSHARED-NEXT: SHF_WRITE
|
||||
// GOTRELSHARED-NEXT: ]
|
||||
// GOTRELSHARED-NEXT: Address: 0x2050
|
||||
// GOTRELSHARED-NEXT: Offset: 0x2050
|
||||
// GOTRELSHARED-NEXT: Size: 16
|
||||
// GOTRELSHARED-NEXT: Link: 0
|
||||
// GOTRELSHARED-NEXT: Info: 0
|
||||
// GOTRELSHARED-NEXT: AddressAlignment: 4
|
||||
// GOTRELSHARED-NEXT: EntrySize: 0
|
||||
// GOTRELSHARED-NEXT: }
|
||||
// GOTRELSHARED: Relocations [
|
||||
// GOTRELSHARED-NEXT: Section ({{.*}}) .rel.dyn {
|
||||
// GOTRELSHARED-NEXT: 0x1002 R_386_RELATIVE - 0x0
|
||||
// GOTRELSHARED-NEXT: 0x2050 R_386_TLS_TPOFF tlslocal0 0x0
|
||||
// GOTRELSHARED-NEXT: 0x100A R_386_RELATIVE - 0x0
|
||||
// GOTRELSHARED-NEXT: 0x1013 R_386_RELATIVE - 0x0
|
||||
// GOTRELSHARED-NEXT: 0x101C R_386_RELATIVE - 0x0
|
||||
// GOTRELSHARED-NEXT: 0x2054 R_386_TLS_TPOFF tlslocal1 0x0
|
||||
// GOTRELSHARED-NEXT: 0x1024 R_386_RELATIVE - 0x0
|
||||
// GOTRELSHARED-NEXT: 0x102D R_386_RELATIVE - 0x0
|
||||
// GOTRELSHARED-NEXT: 0x1036 R_386_RELATIVE - 0x0
|
||||
// GOTRELSHARED-NEXT: 0x2058 R_386_TLS_TPOFF tlsshared0 0x0
|
||||
// GOTRELSHARED-NEXT: 0x103F R_386_RELATIVE - 0x0
|
||||
// GOTRELSHARED-NEXT: 0x205C R_386_TLS_TPOFF tlsshared1 0x0
|
||||
// GOTRELSHARED-NEXT: }
|
||||
// GOTRELSHARED-NEXT: ]
|
||||
|
||||
// DISASMSHARED: Disassembly of section .text:
|
||||
// DISASMSHARED-NEXT: _start:
|
||||
// (.got)[0] = 0x2050 = 8272
|
||||
// (.got)[1] = 0x2054 = 8276
|
||||
// (.got)[2] = 0x2058 = 8280
|
||||
// (.got)[3] = 0x205C = 8284
|
||||
// DISASMSHARED-NEXT: 1000: 8b 0d 50 20 00 00 movl 8272, %ecx
|
||||
// DISASMSHARED-NEXT: 1006: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASMSHARED-NEXT: 1009: a1 50 20 00 00 movl 8272, %eax
|
||||
// DISASMSHARED-NEXT: 100e: 65 8b 00 movl %gs:(%eax), %eax
|
||||
// DISASMSHARED-NEXT: 1011: 03 0d 50 20 00 00 addl 8272, %ecx
|
||||
// DISASMSHARED-NEXT: 1017: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASMSHARED-NEXT: 101a: 8b 0d 54 20 00 00 movl 8276, %ecx
|
||||
// DISASMSHARED-NEXT: 1020: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASMSHARED-NEXT: 1023: a1 54 20 00 00 movl 8276, %eax
|
||||
// DISASMSHARED-NEXT: 1028: 65 8b 00 movl %gs:(%eax), %eax
|
||||
// DISASMSHARED-NEXT: 102b: 03 0d 54 20 00 00 addl 8276, %ecx
|
||||
// DISASMSHARED-NEXT: 1031: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASMSHARED-NEXT: 1034: 8b 0d 58 20 00 00 movl 8280, %ecx
|
||||
// DISASMSHARED-NEXT: 103a: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
// DISASMSHARED-NEXT: 103d: 03 0d 5c 20 00 00 addl 8284, %ecx
|
||||
// DISASMSHARED-NEXT: 1043: 65 8b 01 movl %gs:(%ecx), %eax
|
||||
|
||||
.type tlslocal0,@object
|
||||
.section .tbss,"awT",@nobits
|
||||
.globl tlslocal0
|
||||
.align 4
|
||||
tlslocal0:
|
||||
.long 0
|
||||
.size tlslocal0, 4
|
||||
|
||||
.type tlslocal1,@object
|
||||
.section .tbss,"awT",@nobits
|
||||
.globl tlslocal1
|
||||
.align 4
|
||||
tlslocal1:
|
||||
.long 0
|
||||
.size tlslocal1, 4
|
||||
|
||||
.section .text
|
||||
.globl ___tls_get_addr
|
||||
.type ___tls_get_addr,@function
|
||||
___tls_get_addr:
|
||||
|
||||
.section .text
|
||||
.globl _start
|
||||
_start:
|
||||
movl tlslocal0@indntpoff,%ecx
|
||||
movl %gs:(%ecx),%eax
|
||||
|
||||
movl tlslocal0@indntpoff,%eax
|
||||
movl %gs:(%eax),%eax
|
||||
|
||||
addl tlslocal0@indntpoff,%ecx
|
||||
movl %gs:(%ecx),%eax
|
||||
|
||||
movl tlslocal1@indntpoff,%ecx
|
||||
movl %gs:(%ecx),%eax
|
||||
|
||||
movl tlslocal1@indntpoff,%eax
|
||||
movl %gs:(%eax),%eax
|
||||
|
||||
addl tlslocal1@indntpoff,%ecx
|
||||
movl %gs:(%ecx),%eax
|
||||
|
||||
movl tlsshared0@indntpoff,%ecx
|
||||
movl %gs:(%ecx),%eax
|
||||
|
||||
addl tlsshared1@indntpoff,%ecx
|
||||
movl %gs:(%ecx),%eax
|
Loading…
Reference in New Issue