mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-08 17:11:33 +00:00
[ELF] - Implemented R_*_IRELATIVE relocations for x86, x64 targets.
This relocation is similar to R_*_RELATIVE except that the value used in this relocation is the program address returned by the function, which takes no arguments, at the address of the result of the corresponding R_*_RELATIVE relocation as specified in the processor-specific ABI. The purpose of this relocation to avoid name lookup for locally defined STT_GNU_IFUNC symbols at load-time. More info can be found in ifunc.txt from https://sites.google.com/site/x32abi/documents. Differential revision: http://reviews.llvm.org/D15235 llvm-svn: 256144
This commit is contained in:
parent
bfb7bf7429
commit
a07ff66112
@ -269,7 +269,9 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
|
||||
unsigned Sym = CanBePreempted ? Body->DynamicSymbolTableIndex : 0;
|
||||
unsigned Reloc;
|
||||
if (!CanBePreempted || IsDynRelative)
|
||||
if (!CanBePreempted && Body && isGnuIFunc<ELFT>(*Body))
|
||||
Reloc = Target->getIRelativeReloc();
|
||||
else if (!CanBePreempted || IsDynRelative)
|
||||
Reloc = Target->getRelativeReloc();
|
||||
else if (LazyReloc)
|
||||
Reloc = Target->getPltReloc();
|
||||
@ -320,7 +322,8 @@ template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
|
||||
}
|
||||
|
||||
template <class ELFT> void RelocationSection<ELFT>::finalize() {
|
||||
this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
|
||||
this->Header.sh_link = Static ? Out<ELFT>::SymTab->SectionIndex
|
||||
: Out<ELFT>::DynSymTab->SectionIndex;
|
||||
this->Header.sh_size = Relocs.size() * this->Header.sh_entsize;
|
||||
}
|
||||
|
||||
|
@ -232,6 +232,8 @@ public:
|
||||
bool hasRelocs() const { return !Relocs.empty(); }
|
||||
bool isRela() const { return IsRela; }
|
||||
|
||||
bool Static = false;
|
||||
|
||||
private:
|
||||
bool applyTlsDynamicReloc(SymbolBody *Body, uint32_t Type, Elf_Rel *P,
|
||||
Elf_Rel *N);
|
||||
|
@ -183,6 +183,11 @@ public:
|
||||
// The content for _gp symbol for MIPS target.
|
||||
static Elf_Sym MipsGp;
|
||||
|
||||
// __rel_iplt_start/__rel_iplt_end for signaling
|
||||
// where R_[*]_IRELATIVE relocations do live.
|
||||
static Elf_Sym RelaIpltStart;
|
||||
static Elf_Sym RelaIpltEnd;
|
||||
|
||||
DefinedAbsolute(StringRef N, const Elf_Sym &Sym)
|
||||
: Defined<ELFT>(Base::DefinedAbsoluteKind, N, Sym) {}
|
||||
|
||||
@ -200,6 +205,12 @@ typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::End;
|
||||
template <class ELFT>
|
||||
typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::MipsGp;
|
||||
|
||||
template <class ELFT>
|
||||
typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::RelaIpltStart;
|
||||
|
||||
template <class ELFT>
|
||||
typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::RelaIpltEnd;
|
||||
|
||||
template <class ELFT> class DefinedCommon : public Defined<ELFT> {
|
||||
typedef ELFSymbolBody<ELFT> Base;
|
||||
typedef typename Base::Elf_Sym Elf_Sym;
|
||||
|
@ -70,6 +70,17 @@ template <unsigned N> static void checkAlignment(uint64_t V, uint32_t Type) {
|
||||
error("Improper alignment for relocation " + S);
|
||||
}
|
||||
|
||||
template <class ELFT> bool isGnuIFunc(const SymbolBody &S) {
|
||||
if (auto *SS = dyn_cast<Defined<ELFT>>(&S))
|
||||
return SS->Sym.getType() == STT_GNU_IFUNC;
|
||||
return false;
|
||||
}
|
||||
|
||||
template bool isGnuIFunc<ELF32LE>(const SymbolBody &S);
|
||||
template bool isGnuIFunc<ELF32BE>(const SymbolBody &S);
|
||||
template bool isGnuIFunc<ELF64LE>(const SymbolBody &S);
|
||||
template bool isGnuIFunc<ELF64BE>(const SymbolBody &S);
|
||||
|
||||
namespace {
|
||||
class X86TargetInfo final : public TargetInfo {
|
||||
public:
|
||||
@ -258,6 +269,7 @@ X86TargetInfo::X86TargetInfo() {
|
||||
PCRelReloc = R_386_PC32;
|
||||
GotReloc = R_386_GLOB_DAT;
|
||||
PltReloc = R_386_JUMP_SLOT;
|
||||
IRelativeReloc = R_386_IRELATIVE;
|
||||
RelativeReloc = R_386_RELATIVE;
|
||||
TlsGotReloc = R_386_TLS_TPOFF;
|
||||
TlsGlobalDynamicReloc = R_386_TLS_GD;
|
||||
@ -357,7 +369,8 @@ bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
|
||||
}
|
||||
|
||||
bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
|
||||
return (Type == R_386_PLT32 && canBePreempted(&S, true)) ||
|
||||
return isGnuIFunc<ELF32LE>(S) ||
|
||||
(Type == R_386_PLT32 && canBePreempted(&S, true)) ||
|
||||
(Type == R_386_PC32 && S.isShared());
|
||||
}
|
||||
|
||||
@ -557,6 +570,7 @@ X86_64TargetInfo::X86_64TargetInfo() {
|
||||
GotReloc = R_X86_64_GLOB_DAT;
|
||||
PltReloc = R_X86_64_JUMP_SLOT;
|
||||
RelativeReloc = R_X86_64_RELATIVE;
|
||||
IRelativeReloc = R_X86_64_IRELATIVE;
|
||||
TlsGotReloc = R_X86_64_TPOFF64;
|
||||
TlsLocalDynamicReloc = R_X86_64_TLSLD;
|
||||
TlsGlobalDynamicReloc = R_X86_64_TLSGD;
|
||||
@ -633,6 +647,8 @@ unsigned X86_64TargetInfo::getPltRefReloc(unsigned Type) const {
|
||||
bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
|
||||
if (needsCopyRel(Type, S))
|
||||
return false;
|
||||
if (isGnuIFunc<ELF64LE>(S))
|
||||
return true;
|
||||
|
||||
switch (Type) {
|
||||
default:
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
unsigned getGotReloc() const { return GotReloc; }
|
||||
unsigned getPltReloc() const { return PltReloc; }
|
||||
unsigned getRelativeReloc() const { return RelativeReloc; }
|
||||
unsigned getIRelativeReloc() const { return IRelativeReloc; }
|
||||
bool isTlsLocalDynamicReloc(unsigned Type) const {
|
||||
return Type == TlsLocalDynamicReloc;
|
||||
}
|
||||
@ -88,6 +89,7 @@ protected:
|
||||
unsigned GotReloc;
|
||||
unsigned PltReloc;
|
||||
unsigned RelativeReloc;
|
||||
unsigned IRelativeReloc;
|
||||
unsigned TlsGotReloc = 0;
|
||||
unsigned TlsLocalDynamicReloc = 0;
|
||||
unsigned TlsGlobalDynamicReloc = 0;
|
||||
@ -105,6 +107,8 @@ uint64_t getPPC64TocBase();
|
||||
template <class ELFT>
|
||||
typename llvm::object::ELFFile<ELFT>::uintX_t getMipsGpAddr();
|
||||
|
||||
template <class ELFT> bool isGnuIFunc(const SymbolBody &S);
|
||||
|
||||
extern std::unique_ptr<TargetInfo> Target;
|
||||
TargetInfo *createTarget();
|
||||
}
|
||||
|
@ -277,6 +277,15 @@ void Writer<ELFT>::scanRelocs(
|
||||
}
|
||||
}
|
||||
|
||||
// An STT_GNU_IFUNC symbol always uses a PLT entry, and all references
|
||||
// to the symbol go through the PLT. This is true even for a local
|
||||
// symbol, although local symbols normally do not require PLT entries.
|
||||
if (Body && isGnuIFunc<ELFT>(*Body)) {
|
||||
Body->setUsedInDynamicReloc();
|
||||
Out<ELFT>::RelaPlt->addReloc({&C, &RI});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Config->EMachine == EM_MIPS && NeedsGot) {
|
||||
// MIPS ABI has special rules to process GOT entries
|
||||
// and doesn't require relocation entries for them.
|
||||
@ -578,6 +587,27 @@ static bool compareSections(OutputSectionBase<ELFT> *A,
|
||||
return std::distance(ItA, ItB) > 0;
|
||||
}
|
||||
|
||||
// A statically linked executable will have rel[a].plt section
|
||||
// to hold R_[*]_IRELATIVE relocations.
|
||||
// The multi-arch libc will use these symbols to locate
|
||||
// these relocations at program startup time.
|
||||
// If RelaPlt is empty then there is no reason to create this symbols.
|
||||
template <class ELFT>
|
||||
static void addIRelocMarkers(SymbolTable<ELFT> &Symtab, bool IsDynamic) {
|
||||
if (IsDynamic || !Out<ELFT>::RelaPlt || !Out<ELFT>::RelaPlt->hasRelocs())
|
||||
return;
|
||||
bool IsRela = shouldUseRela<ELFT>();
|
||||
auto AddMarker = [&](StringRef Name, typename Writer<ELFT>::Elf_Sym &Sym) {
|
||||
if (SymbolBody *B = Symtab.find(Name))
|
||||
if (B->isUndefined())
|
||||
Symtab.addAbsolute(Name, Sym);
|
||||
};
|
||||
AddMarker(IsRela ? "__rela_iplt_start" : "__rel_iplt_start",
|
||||
DefinedAbsolute<ELFT>::RelaIpltStart);
|
||||
AddMarker(IsRela ? "__rela_iplt_end" : "__rel_iplt_end",
|
||||
DefinedAbsolute<ELFT>::RelaIpltEnd);
|
||||
}
|
||||
|
||||
// Create output section objects and add them to OutputSections.
|
||||
template <class ELFT> void Writer<ELFT>::createSections() {
|
||||
// .interp needs to be on the first page in the output file.
|
||||
@ -720,6 +750,8 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
||||
}
|
||||
}
|
||||
|
||||
addIRelocMarkers<ELFT>(Symtab, isOutputDynamic());
|
||||
|
||||
std::vector<DefinedCommon<ELFT> *> CommonSymbols;
|
||||
std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
|
||||
for (auto &P : Symtab.getSymbols()) {
|
||||
@ -762,8 +794,6 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
||||
OutputSections.push_back(Out<ELFT>::DynStrTab);
|
||||
if (Out<ELFT>::RelaDyn->hasRelocs())
|
||||
OutputSections.push_back(Out<ELFT>::RelaDyn);
|
||||
if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs())
|
||||
OutputSections.push_back(Out<ELFT>::RelaPlt);
|
||||
// This is a MIPS specific section to hold a space within the data segment
|
||||
// of executable file which is pointed to by the DT_MIPS_RLD_MAP entry.
|
||||
// See "Dynamic section" in Chapter 5 in the following document:
|
||||
@ -777,6 +807,13 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
||||
}
|
||||
}
|
||||
|
||||
// We always need to add rel[a].plt to output if it has entries.
|
||||
// Even during static linking it can contain R_[*]_IRELATIVE relocations.
|
||||
if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
|
||||
OutputSections.push_back(Out<ELFT>::RelaPlt);
|
||||
Out<ELFT>::RelaPlt->Static = !isOutputDynamic();
|
||||
}
|
||||
|
||||
bool needsGot = !Out<ELFT>::Got->empty();
|
||||
// We add the .got section to the result for dynamic MIPS target because
|
||||
// its address and properties are mentioned in the .dynamic section.
|
||||
@ -997,6 +1034,15 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||
// point to the end of the data segment.
|
||||
DefinedAbsolute<ELFT>::End.st_value = VA;
|
||||
|
||||
// Update __rel_iplt_start/__rel_iplt_end to wrap the
|
||||
// rela.plt section.
|
||||
if (Out<ELFT>::RelaPlt) {
|
||||
uintX_t Start = Out<ELFT>::RelaPlt->getVA();
|
||||
DefinedAbsolute<ELFT>::RelaIpltStart.st_value = Start;
|
||||
DefinedAbsolute<ELFT>::RelaIpltEnd.st_value =
|
||||
Start + Out<ELFT>::RelaPlt->getSize();
|
||||
}
|
||||
|
||||
// Update MIPS _gp absolute symbol so that it points to the static data.
|
||||
if (Config->EMachine == EM_MIPS)
|
||||
DefinedAbsolute<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();
|
||||
|
130
lld/test/ELF/gnu-ifunc-i386.s
Normal file
130
lld/test/ELF/gnu-ifunc-i386.s
Normal file
@ -0,0 +1,130 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
|
||||
// RUN: ld.lld -static %t.o -o %tout
|
||||
// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
|
||||
// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s --check-prefix=CHECK
|
||||
// REQUIRES: x86
|
||||
|
||||
// CHECK: Sections [
|
||||
// CHECK: Section {
|
||||
// CHECK: Index: 1
|
||||
// CHECK-NEXT: Name: .rel.plt
|
||||
// CHECK-NEXT: Type: SHT_REL
|
||||
// CHECK-NEXT: Flags [
|
||||
// CHECK-NEXT: SHF_ALLOC
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: [[RELA:.*]]
|
||||
// CHECK-NEXT: Offset: 0xD4
|
||||
// CHECK-NEXT: Size: 16
|
||||
// CHECK-NEXT: Link: 5
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 4
|
||||
// CHECK-NEXT: EntrySize: 8
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: Relocations [
|
||||
// CHECK-NEXT: Section ({{.*}}) .rel.plt {
|
||||
// CHECK-NEXT: 0x1200C R_386_IRELATIVE
|
||||
// CHECK-NEXT: 0x12010 R_386_IRELATIVE
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ]
|
||||
|
||||
// CHECK: Symbols [
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name:
|
||||
// CHECK-NEXT: Value: 0x0
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Undefined
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: __rel_iplt_end
|
||||
// CHECK-NEXT: Value: 0x100E4
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Absolute
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: __rel_iplt_start
|
||||
// CHECK-NEXT: Value: [[RELA]]
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Absolute
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: _start
|
||||
// CHECK-NEXT: Value: 0x11002
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: bar
|
||||
// CHECK-NEXT: Value: 0x11001
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global
|
||||
// CHECK-NEXT: Type: GNU_IFunc
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: foo
|
||||
// CHECK-NEXT: Value: 0x11000
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global
|
||||
// CHECK-NEXT: Type: GNU_IFunc
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT:]
|
||||
|
||||
// DISASM: Disassembly of section .text:
|
||||
// DISASM-NEXT: foo:
|
||||
// DISASM-NEXT: 11000: c3 retl
|
||||
// DISASM: bar:
|
||||
// DISASM-NEXT: 11001: c3 retl
|
||||
// DISASM: _start:
|
||||
// DISASM-NEXT: 11002: e8 29 00 00 00 calll 41
|
||||
// DISASM-NEXT: 11007: e8 34 00 00 00 calll 52
|
||||
// DISASM-NEXT: 1100c: ba d4 00 01 00 movl $65748, %edx
|
||||
// DISASM-NEXT: 11011: ba e4 00 01 00 movl $65764, %edx
|
||||
// DISASM-NEXT: Disassembly of section .plt:
|
||||
// DISASM-NEXT: .plt:
|
||||
// DISASM-NEXT: 11020: ff 35 04 20 01 00 pushl 73732
|
||||
// DISASM-NEXT: 11026: ff 25 08 20 01 00 jmpl *73736
|
||||
// DISASM-NEXT: 1102c: 90 nop
|
||||
// DISASM-NEXT: 1102d: 90 nop
|
||||
// DISASM-NEXT: 1102e: 90 nop
|
||||
// DISASM-NEXT: 1102f: 90 nop
|
||||
// DISASM-NEXT: 11030: ff 25 0c 20 01 00 jmpl *73740
|
||||
// DISASM-NEXT: 11036: 68 00 00 00 00 pushl $0
|
||||
// DISASM-NEXT: 1103b: e9 e0 ff ff ff jmp -32 <.plt>
|
||||
// DISASM-NEXT: 11040: ff 25 10 20 01 00 jmpl *73744
|
||||
// DISASM-NEXT: 11046: 68 08 00 00 00 pushl $8
|
||||
// DISASM-NEXT: 1104b: e9 d0 ff ff ff jmp -48 <.plt>
|
||||
|
||||
.text
|
||||
.type foo STT_GNU_IFUNC
|
||||
.globl foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
|
||||
.type bar STT_GNU_IFUNC
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
ret
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
call foo
|
||||
call bar
|
||||
movl $__rel_iplt_start,%edx
|
||||
movl $__rel_iplt_end,%edx
|
29
lld/test/ELF/gnu-ifunc-nosym-i386.s
Normal file
29
lld/test/ELF/gnu-ifunc-nosym-i386.s
Normal file
@ -0,0 +1,29 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
|
||||
// RUN: ld.lld -static %t.o -o %tout
|
||||
// RUN: llvm-readobj -symbols %tout | FileCheck %s
|
||||
// REQUIRES: x86
|
||||
|
||||
// Check that no __rel_iplt_end/__rel_iplt_start
|
||||
// appear in symtab if there is no references to them.
|
||||
// CHECK: Symbols [
|
||||
// CHECK-NEXT-NOT: __rel_iplt_end
|
||||
// CHECK-NEXT-NOT: __rel_iplt_start
|
||||
// CHECK: ]
|
||||
|
||||
.text
|
||||
.type foo STT_GNU_IFUNC
|
||||
.globl foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
|
||||
.type bar STT_GNU_IFUNC
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
ret
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
call foo
|
||||
call bar
|
29
lld/test/ELF/gnu-ifunc-nosym.s
Normal file
29
lld/test/ELF/gnu-ifunc-nosym.s
Normal file
@ -0,0 +1,29 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
// RUN: ld.lld -static %t.o -o %tout
|
||||
// RUN: llvm-readobj -symbols %tout | FileCheck %s
|
||||
// REQUIRES: x86
|
||||
|
||||
// Check that no __rela_iplt_end/__rela_iplt_start
|
||||
// appear in symtab if there is no references to them.
|
||||
// CHECK: Symbols [
|
||||
// CHECK-NEXT-NOT: __rela_iplt_end
|
||||
// CHECK-NEXT-NOT: __rela_iplt_start
|
||||
// CHECK: ]
|
||||
|
||||
.text
|
||||
.type foo STT_GNU_IFUNC
|
||||
.globl foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
|
||||
.type bar STT_GNU_IFUNC
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
ret
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
call foo
|
||||
call bar
|
126
lld/test/ELF/gnu-ifunc.s
Normal file
126
lld/test/ELF/gnu-ifunc.s
Normal file
@ -0,0 +1,126 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
// RUN: ld.lld -static %t.o -o %tout
|
||||
// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
|
||||
// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s --check-prefix=CHECK
|
||||
// REQUIRES: x86
|
||||
|
||||
// CHECK: Sections [
|
||||
// CHECK: Section {
|
||||
// CHECK: Index: 1
|
||||
// CHECK-NEXT: Name: .rela.plt
|
||||
// CHECK-NEXT: Type: SHT_RELA
|
||||
// CHECK-NEXT: Flags [
|
||||
// CHECK-NEXT: SHF_ALLOC
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: Address: [[RELA:.*]]
|
||||
// CHECK-NEXT: Offset: 0x158
|
||||
// CHECK-NEXT: Size: 48
|
||||
// CHECK-NEXT: Link: 5
|
||||
// CHECK-NEXT: Info: 0
|
||||
// CHECK-NEXT: AddressAlignment: 8
|
||||
// CHECK-NEXT: EntrySize: 24
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: Relocations [
|
||||
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
|
||||
// CHECK-NEXT: 0x12018 R_X86_64_IRELATIVE
|
||||
// CHECK-NEXT: 0x12020 R_X86_64_IRELATIVE
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK: Symbols [
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name:
|
||||
// CHECK-NEXT: Value: 0x0
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Undefined
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: __rela_iplt_end
|
||||
// CHECK-NEXT: Value: 0x10188
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Absolute
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: __rela_iplt_start
|
||||
// CHECK-NEXT: Value: [[RELA]]
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Local
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: Absolute
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: _start
|
||||
// CHECK-NEXT: Value: 0x11002
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global
|
||||
// CHECK-NEXT: Type: None
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: bar
|
||||
// CHECK-NEXT: Value: 0x11001
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global
|
||||
// CHECK-NEXT: Type: GNU_IFunc
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: Symbol {
|
||||
// CHECK-NEXT: Name: foo
|
||||
// CHECK-NEXT: Value: 0x11000
|
||||
// CHECK-NEXT: Size: 0
|
||||
// CHECK-NEXT: Binding: Global
|
||||
// CHECK-NEXT: Type: GNU_IFunc
|
||||
// CHECK-NEXT: Other: 0
|
||||
// CHECK-NEXT: Section: .text
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ]
|
||||
|
||||
// DISASM: Disassembly of section .text:
|
||||
// DISASM-NEXT: foo:
|
||||
// DISASM-NEXT: 11000: c3 retq
|
||||
// DISASM: bar:
|
||||
// DISASM-NEXT: 11001: c3 retq
|
||||
// DISASM: _start:
|
||||
// DISASM-NEXT: 11002: e8 29 00 00 00 callq 41
|
||||
// DISASM-NEXT: 11007: e8 34 00 00 00 callq 52
|
||||
// DISASM-NEXT: 1100c: ba 58 01 01 00 movl $65880, %edx
|
||||
// DISASM-NEXT: 11011: ba 88 01 01 00 movl $65928, %edx
|
||||
// DISASM-NEXT: Disassembly of section .plt:
|
||||
// DISASM-NEXT: .plt:
|
||||
// DISASM-NEXT: 11020: ff 35 e2 0f 00 00 pushq 4066(%rip)
|
||||
// DISASM-NEXT: 11026: ff 25 e4 0f 00 00 jmpq *4068(%rip)
|
||||
// DISASM-NEXT: 1102c: 0f 1f 40 00 nopl (%rax)
|
||||
// DISASM-NEXT: 11030: ff 25 e2 0f 00 00 jmpq *4066(%rip)
|
||||
// DISASM-NEXT: 11036: 68 00 00 00 00 pushq $0
|
||||
// DISASM-NEXT: 1103b: e9 e0 ff ff ff jmp -32
|
||||
// DISASM-NEXT: 11040: ff 25 da 0f 00 00 jmpq *4058(%rip)
|
||||
// DISASM-NEXT: 11046: 68 01 00 00 00 pushq $1
|
||||
// DISASM-NEXT: 1104b: e9 d0 ff ff ff jmp -48
|
||||
|
||||
.text
|
||||
.type foo STT_GNU_IFUNC
|
||||
.globl foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
ret
|
||||
|
||||
.type bar STT_GNU_IFUNC
|
||||
.globl bar
|
||||
.type bar, @function
|
||||
bar:
|
||||
ret
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
call foo
|
||||
call bar
|
||||
movl $__rela_iplt_start,%edx
|
||||
movl $__rela_iplt_end,%edx
|
Loading…
Reference in New Issue
Block a user