Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -719,18 +719,20 @@ if (needsPlt(Expr)) { if (Body.isInPlt()) continue; - In::Plt->addEntry(Body); - uint32_t Rel; - if (Body.isGnuIFunc() && !Preemptible) - Rel = Target->IRelativeRel; - else - Rel = Target->PltRel; - - In::GotPlt->addEntry(Body); - In::RelaPlt->addReloc({Rel, In::GotPlt, - Body.getGotPltOffset(), !Preemptible, - &Body, 0}); + if (Body.isGnuIFunc() && !Preemptible) { + In::Iplt->addEntry(Body); + In::IgotPlt->addEntry(Body); + In::RelaIplt->addReloc({Target->IRelativeRel, In::IgotPlt, + Body.getGotPltOffset(), + !Preemptible, &Body, 0}); + } else { + In::Plt->addEntry(Body); + In::GotPlt->addEntry(Body); + In::RelaPlt->addReloc({Target->PltRel, In::GotPlt, + Body.getGotPltOffset(), !Preemptible, + &Body, 0}); + } continue; } Index: lld/trunk/ELF/Symbols.h =================================================================== --- lld/trunk/ELF/Symbols.h +++ lld/trunk/ELF/Symbols.h @@ -117,6 +117,12 @@ // True if this symbol is referenced by 32-bit GOT relocations. unsigned Is32BitMipsGot : 1; + // True if this symbol is in the Iplt sub-section of the Plt. + unsigned IsInIplt : 1; + + // True if this symbol is in the Igot sub-section of the .got.plt or .got. + unsigned IsInIgot : 1; + // The following fields have the same meaning as the ELF symbol attributes. uint8_t Type; // symbol type uint8_t StOther; // st_other field value Index: lld/trunk/ELF/Symbols.cpp =================================================================== --- lld/trunk/ELF/Symbols.cpp +++ lld/trunk/ELF/Symbols.cpp @@ -95,8 +95,8 @@ SymbolBody::SymbolBody(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type) : SymbolKind(K), NeedsCopyOrPltAddr(false), IsLocal(IsLocal), - IsInGlobalMipsGot(false), Is32BitMipsGot(false), Type(Type), - StOther(StOther), Name(Name) {} + IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false), + IsInIgot(false), Type(Type), StOther(StOther), Name(Name) {} // Returns true if a symbol can be replaced at load-time by a symbol // with the same name defined in other ELF executable or DSO. @@ -151,6 +151,8 @@ } template typename ELFT::uint SymbolBody::getGotPltVA() const { + if (this->IsInIgot) + return In::IgotPlt->getVA() + getGotPltOffset(); return In::GotPlt->getVA() + getGotPltOffset(); } @@ -159,6 +161,8 @@ } template typename ELFT::uint SymbolBody::getPltVA() const { + if (this->IsInIplt) + return In::Iplt->getVA() + PltIndex * Target->PltEntrySize; return In::Plt->getVA() + Target->PltHeaderSize + PltIndex * Target->PltEntrySize; } Index: lld/trunk/ELF/SyntheticSections.h =================================================================== --- lld/trunk/ELF/SyntheticSections.h +++ lld/trunk/ELF/SyntheticSections.h @@ -206,6 +206,25 @@ std::vector Entries; }; +// The IgotPltSection is a Got associated with the IpltSection for GNU Ifunc +// Symbols that will be relocated by Target->IRelativeRel. +// On most Targets the IgotPltSection will immediately follow the GotPltSection +// on ARM the IgotPltSection will immediately follow the GotSection. +template +class IgotPltSection final : public SyntheticSection { + typedef typename ELFT::uint uintX_t; + +public: + IgotPltSection(); + void addEntry(SymbolBody &Sym); + size_t getSize() const override; + void writeTo(uint8_t *Buf) override; + bool empty() const override { return Entries.empty(); } + +private: + std::vector Entries; +}; + template class StringTableSection final : public SyntheticSection { public: @@ -431,6 +450,21 @@ std::vector> Entries; }; +// The IpltSection is a variant of Plt for recording entries for GNU Ifunc +// symbols that will be subject to a Target->IRelativeRel +// The IpltSection immediately follows the Plt section in the Output Section +template class IpltSection final : public SyntheticSection { +public: + IpltSection(); + void writeTo(uint8_t *Buf) override; + size_t getSize() const override; + void addEntry(SymbolBody &Sym); + bool empty() const override { return Entries.empty(); } + +private: + std::vector> Entries; +}; + template class GdbIndexSection final : public SyntheticSection { typedef typename ELFT::uint uintX_t; @@ -644,12 +678,15 @@ static GotSection *Got; static MipsGotSection *MipsGot; static GotPltSection *GotPlt; + static IgotPltSection *IgotPlt; static HashTableSection *HashTab; static InputSection *Interp; static MipsRldMapSection *MipsRldMap; static PltSection *Plt; + static IpltSection *Iplt; static RelocationSection *RelaDyn; static RelocationSection *RelaPlt; + static RelocationSection *RelaIplt; static StringTableSection *ShStrTab; static StringTableSection *StrTab; static SymbolTableSection *SymTab; @@ -669,12 +706,15 @@ template GotSection *In::Got; template MipsGotSection *In::MipsGot; template GotPltSection *In::GotPlt; +template IgotPltSection *In::IgotPlt; template HashTableSection *In::HashTab; template InputSection *In::Interp; template MipsRldMapSection *In::MipsRldMap; template PltSection *In::Plt; +template IpltSection *In::Iplt; template RelocationSection *In::RelaDyn; template RelocationSection *In::RelaPlt; +template RelocationSection *In::RelaIplt; template StringTableSection *In::ShStrTab; template StringTableSection *In::StrTab; template SymbolTableSection *In::SymTab; Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -707,6 +707,36 @@ } } +// On ARM the IgotPltSection is part of the GotSection, on other Targets it is +// part of the .got.plt +template +IgotPltSection::IgotPltSection() + : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, + Target->GotPltEntrySize, + Config->EMachine == EM_ARM ? ".got" : ".got.plt") { +} + +template void IgotPltSection::addEntry(SymbolBody &Sym) { + Sym.IsInIgot = true; + Sym.GotPltIndex = Entries.size(); + Entries.push_back(&Sym); +} + +template size_t IgotPltSection::getSize() const { + return Entries.size() * Target->GotPltEntrySize; +} + +template void IgotPltSection::writeTo(uint8_t *Buf) { + for (const SymbolBody *B : Entries) { + if (Config->EMachine == EM_ARM) + // On ARM we are actually part of the Got and not GotPlt. + write32le(Buf, B->getVA()); + else + Target->writeGotPlt(Buf, *B); + Buf += sizeof(uintX_t); + } +} + template StringTableSection::StringTableSection(StringRef Name, bool Dynamic) : SyntheticSection(Dynamic ? (uintX_t)SHF_ALLOC : 0, SHT_STRTAB, 1, @@ -805,11 +835,10 @@ return; // Already finalized. this->Link = In::DynStrTab->OutSec->SectionIndex; - - if (!In::RelaDyn->empty()) { + if (In::RelaDyn->OutSec->Size > 0) { bool IsRela = Config->Rela; add({IsRela ? DT_RELA : DT_REL, In::RelaDyn}); - add({IsRela ? DT_RELASZ : DT_RELSZ, In::RelaDyn->getSize()}); + add({IsRela ? DT_RELASZ : DT_RELSZ, In::RelaDyn->OutSec->Size}); add({IsRela ? DT_RELAENT : DT_RELENT, uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))}); @@ -822,9 +851,9 @@ add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels}); } } - if (!In::RelaPlt->empty()) { + if (In::RelaPlt->OutSec->Size > 0) { add({DT_JMPREL, In::RelaPlt}); - add({DT_PLTRELSZ, In::RelaPlt->getSize()}); + add({DT_PLTRELSZ, In::RelaPlt->OutSec->Size}); add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT, In::GotPlt}); add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)}); @@ -1401,6 +1430,36 @@ } template +IpltSection::IpltSection() + : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, + ".plt") {} + +template void IpltSection::writeTo(uint8_t *Buf) { + // The IRelative relocations do not support lazy binding so no header is + // needed + size_t Off = 0; + for (auto &I : Entries) { + const SymbolBody *B = I.first; + unsigned RelOff = I.second + In::Plt->getSize(); + uint64_t Got = B->getGotPltVA(); + uint64_t Plt = this->getVA() + Off; + Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); + Off += Target->PltEntrySize; + } +} + +template void IpltSection::addEntry(SymbolBody &Sym) { + Sym.PltIndex = Entries.size(); + Sym.IsInIplt = true; + unsigned RelOff = In::RelaIplt->getRelocOffset(); + Entries.push_back(std::make_pair(&Sym, RelOff)); +} + +template size_t IpltSection::getSize() const { + return Entries.size() * Target->PltEntrySize; +} + +template GdbIndexSection::GdbIndexSection() : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index") {} @@ -1750,6 +1809,11 @@ template class elf::GotPltSection; template class elf::GotPltSection; +template class elf::IgotPltSection; +template class elf::IgotPltSection; +template class elf::IgotPltSection; +template class elf::IgotPltSection; + template class elf::StringTableSection; template class elf::StringTableSection; template class elf::StringTableSection; @@ -1785,6 +1849,11 @@ template class elf::PltSection; template class elf::PltSection; +template class elf::IpltSection; +template class elf::IpltSection; +template class elf::IpltSection; +template class elf::IpltSection; + template class elf::GdbIndexSection; template class elf::GdbIndexSection; template class elf::GdbIndexSection; Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -356,6 +356,8 @@ In::GotPlt = make>(); Symtab::X->Sections.push_back(In::GotPlt); + In::IgotPlt = make>(); + Symtab::X->Sections.push_back(In::IgotPlt); if (Config->GdbIndex) { In::GdbIndex = make>(); @@ -368,8 +370,17 @@ Config->Rela ? ".rela.plt" : ".rel.plt", false /*Sort*/); Symtab::X->Sections.push_back(In::RelaPlt); + // The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure + // that the IRelative relocations are processed last by the dynamic loader + In::RelaIplt = make>( + (Config->EMachine == EM_ARM) ? ".rel.dyn" : In::RelaPlt->Name, + false /*Sort*/); + Symtab::X->Sections.push_back(In::RelaIplt); + In::Plt = make>(); Symtab::X->Sections.push_back(In::Plt); + In::Iplt = make>(); + Symtab::X->Sections.push_back(In::Iplt); if (Config->EhFrameHdr) { In::EhFrameHdr = make>(); @@ -651,10 +662,10 @@ if (In::DynSymTab) return; StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalRegular(S, In::RelaPlt, 0); + addOptionalRegular(S, In::RelaIplt, 0); S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end"; - addOptionalRegular(S, In::RelaPlt, -1); + addOptionalRegular(S, In::RelaIplt, -1); } // The linker is expected to define some symbols depending on @@ -1036,11 +1047,13 @@ // symbol table section (DynSymTab) must be the first one. finalizeSynthetic( {In::DynSymTab, In::GnuHashTab, In::HashTab, - In::SymTab, In::ShStrTab, In::StrTab, In::VerDef, - In::DynStrTab, In::GdbIndex, In::Got, - In::MipsGot, In::GotPlt, In::RelaDyn, - In::RelaPlt, In::Plt, In::EhFrameHdr, In::VerSym, - In::VerNeed, In::Dynamic}); + In::SymTab, In::ShStrTab, In::StrTab, + In::VerDef, In::DynStrTab, In::GdbIndex, + In::Got, In::MipsGot, In::IgotPlt, + In::GotPlt, In::RelaDyn, In::RelaIplt, + In::RelaPlt, In::Plt, In::Iplt, + In::Plt, In::EhFrameHdr, In::VerSym, + In::VerNeed, In::Dynamic}); } template void Writer::addPredefinedSections() { Index: lld/trunk/test/ELF/Inputs/arm-shared.s =================================================================== --- lld/trunk/test/ELF/Inputs/arm-shared.s +++ lld/trunk/test/ELF/Inputs/arm-shared.s @@ -0,0 +1,8 @@ +.syntax unified +.global bar2 +.type bar2, %function +bar2: + +.global zed2 +.type zed2, %function +zed2: Index: lld/trunk/test/ELF/Inputs/shared2-x86-64.s =================================================================== --- lld/trunk/test/ELF/Inputs/shared2-x86-64.s +++ lld/trunk/test/ELF/Inputs/shared2-x86-64.s @@ -0,0 +1,9 @@ +.global bar2 +.type bar2, @function +bar2: + ret + +.global zed2 +.type zed2, @function +zed2: + ret Index: lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s =================================================================== --- lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s +++ lld/trunk/test/ELF/aarch64-gnu-ifunc-plt.s @@ -0,0 +1,85 @@ +// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %S/Inputs/shared2.s -o %t1.o +// RUN: ld.lld %t1.o --shared -o %t.so +// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o +// RUN: ld.lld %t.so %t.o -o %tout +// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM +// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT +// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s +// REQUIRES: aarch64 + +// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt +// CHECK: Relocations [ +// CHECK-NEXT: Section (4) .rela.plt { +// CHECK: 0x40018 R_AARCH64_JUMP_SLOT bar2 0x0 +// CHECK-NEXT: 0x40020 R_AARCH64_JUMP_SLOT zed2 0x0 +// CHECK-NEXT: 0x40028 R_AARCH64_IRELATIVE - 0x20000 +// CHECK-NEXT: 0x40030 R_AARCH64_IRELATIVE - 0x20004 +// CHECK-NEXT: } +// CHECK-NEXT: ] + +// Check that .got.plt entries point back to PLT header +// GOTPLT: Contents of section .got.plt: +// GOTPLT-NEXT: 40000 00000000 00000000 00000000 00000000 +// GOTPLT-NEXT: 40010 00000000 00000000 20000200 00000000 +// GOTPLT-NEXT: 40020 20000200 00000000 20000200 00000000 +// GOTPLT-NEXT: 40030 20000200 00000000 + +// Check that the PLTRELSZ tag includes the IRELATIVE relocations +// CHECK: DynamicSection [ +// CHECK: 0x0000000000000002 PLTRELSZ 96 (bytes) + +// Check that a PLT header is written and the ifunc entries appear last +// DISASM: Disassembly of section .text: +// DISASM-NEXT: foo: +// DISASM-NEXT: 20000: c0 03 5f d6 ret +// DISASM: bar: +// DISASM-NEXT: 20004: c0 03 5f d6 ret +// DISASM: _start: +// DISASM-NEXT: 20008: 16 00 00 94 bl #88 +// DISASM-NEXT: 2000c: 19 00 00 94 bl #100 +// DISASM-NEXT: 20010: 0c 00 00 94 bl #48 +// DISASM-NEXT: 20014: 0f 00 00 94 bl #60 +// DISASM-NEXT: Disassembly of section .plt: +// DISASM-NEXT: .plt: +// DISASM-NEXT: 20020: f0 7b bf a9 stp x16, x30, [sp, #-16]! +// DISASM-NEXT: 20024: 10 01 00 90 adrp x16, #131072 +// DISASM-NEXT: 20028: 11 0a 40 f9 ldr x17, [x16, #16] +// DISASM-NEXT: 2002c: 10 42 00 91 add x16, x16, #16 +// DISASM-NEXT: 20030: 20 02 1f d6 br x17 +// DISASM-NEXT: 20034: 1f 20 03 d5 nop +// DISASM-NEXT: 20038: 1f 20 03 d5 nop +// DISASM-NEXT: 2003c: 1f 20 03 d5 nop +// DISASM-NEXT: 20040: 10 01 00 90 adrp x16, #131072 +// DISASM-NEXT: 20044: 11 0e 40 f9 ldr x17, [x16, #24] +// DISASM-NEXT: 20048: 10 62 00 91 add x16, x16, #24 +// DISASM-NEXT: 2004c: 20 02 1f d6 br x17 +// DISASM-NEXT: 20050: 10 01 00 90 adrp x16, #131072 +// DISASM-NEXT: 20054: 11 12 40 f9 ldr x17, [x16, #32] +// DISASM-NEXT: 20058: 10 82 00 91 add x16, x16, #32 +// DISASM-NEXT: 2005c: 20 02 1f d6 br x17 +// DISASM-NEXT: 20060: 10 01 00 90 adrp x16, #131072 +// DISASM-NEXT: 20064: 11 16 40 f9 ldr x17, [x16, #40] +// DISASM-NEXT: 20068: 10 a2 00 91 add x16, x16, #40 +// DISASM-NEXT: 2006c: 20 02 1f d6 br x17 +// DISASM-NEXT: 20070: 10 01 00 90 adrp x16, #131072 +// DISASM-NEXT: 20074: 11 1a 40 f9 ldr x17, [x16, #48] +// DISASM-NEXT: 20078: 10 c2 00 91 add x16, x16, #48 +// DISASM-NEXT: 2007c: 20 02 1f d6 br x17 + +.text +.type foo STT_GNU_IFUNC +.globl foo +foo: + ret + +.type bar STT_GNU_IFUNC +.globl bar +bar: + ret + +.globl _start +_start: + bl foo + bl bar + bl bar2 + bl zed2 Index: lld/trunk/test/ELF/aarch64-gnu-ifunc.s =================================================================== --- lld/trunk/test/ELF/aarch64-gnu-ifunc.s +++ lld/trunk/test/ELF/aarch64-gnu-ifunc.s @@ -22,8 +22,8 @@ // CHECK-NEXT: } // CHECK: Relocations [ // CHECK-NEXT: Section ({{.*}}) .rela.plt { -// CHECK-NEXT: 0x30018 R_AARCH64_IRELATIVE -// CHECK-NEXT: 0x30020 R_AARCH64_IRELATIVE +// CHECK-NEXT: 0x30000 R_AARCH64_IRELATIVE +// CHECK-NEXT: 0x30008 R_AARCH64_IRELATIVE // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK: Symbols [ @@ -98,34 +98,27 @@ // 344 = 0x158 // 392 = 0x188 -// DISASM: Disassembly of section .text: + +// DISASM: Disassembly of section .text: // DISASM-NEXT: foo: // DISASM-NEXT: 20000: c0 03 5f d6 ret -// DISASM: bar: +// DISASM: bar: // DISASM-NEXT: 20004: c0 03 5f d6 ret // DISASM: _start: -// DISASM-NEXT: 20008: 0e 00 00 94 bl #56 -// DISASM-NEXT: 2000c: 11 00 00 94 bl #68 -// DISASM-NEXT: 20010: 42 60 05 91 add x2, x2, #344 -// DISASM-NEXT: 20014: 42 20 06 91 add x2, x2, #392 +// DISASM-NEXT: 20008: 06 00 00 94 bl #24 +// DISASM-NEXT: 2000c: 09 00 00 94 bl #36 +// DISASM-NEXT: 20010: 42 60 05 91 add x2, x2, #344 +// DISASM-NEXT: 20014: 42 20 06 91 add x2, x2, #392 // DISASM-NEXT: Disassembly of section .plt: // DISASM-NEXT: .plt: -// DISASM-NEXT: 20020: f0 7b bf a9 stp x16, x30, [sp, #-16]! -// DISASM-NEXT: 20024: 90 00 00 90 adrp x16, #65536 -// DISASM-NEXT: 20028: 11 0a 40 f9 ldr x17, [x16, #16] -// DISASM-NEXT: 2002c: 10 42 00 91 add x16, x16, #16 -// DISASM-NEXT: 20030: 20 02 1f d6 br x17 -// DISASM-NEXT: 20034: 1f 20 03 d5 nop -// DISASM-NEXT: 20038: 1f 20 03 d5 nop -// DISASM-NEXT: 2003c: 1f 20 03 d5 nop -// DISASM-NEXT: 20040: 90 00 00 90 adrp x16, #65536 -// DISASM-NEXT: 20044: 11 0e 40 f9 ldr x17, [x16, #24] -// DISASM-NEXT: 20048: 10 62 00 91 add x16, x16, #24 -// DISASM-NEXT: 2004c: 20 02 1f d6 br x17 -// DISASM-NEXT: 20050: 90 00 00 90 adrp x16, #65536 -// DISASM-NEXT: 20054: 11 12 40 f9 ldr x17, [x16, #32] -// DISASM-NEXT: 20058: 10 82 00 91 add x16, x16, #32 -// DISASM-NEXT: 2005c: 20 02 1f d6 br x17 +// DISASM-NEXT: 20020: 90 00 00 90 adrp x16, #65536 +// DISASM-NEXT: 20024: 11 02 40 f9 ldr x17, [x16] +// DISASM-NEXT: 20028: 10 02 00 91 add x16, x16, #0 +// DISASM-NEXT: 2002c: 20 02 1f d6 br x17 +// DISASM-NEXT: 20030: 90 00 00 90 adrp x16, #65536 +// DISASM-NEXT: 20034: 11 06 40 f9 ldr x17, [x16, #8] +// DISASM-NEXT: 20038: 10 22 00 91 add x16, x16, #8 +// DISASM-NEXT: 2003c: 20 02 1f d6 br x17 .text .type foo STT_GNU_IFUNC Index: lld/trunk/test/ELF/arm-gnu-ifunc-plt.s =================================================================== --- lld/trunk/test/ELF/arm-gnu-ifunc-plt.s +++ lld/trunk/test/ELF/arm-gnu-ifunc-plt.s @@ -0,0 +1,93 @@ +// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %S/Inputs/arm-shared.s -o %t1.o +// RUN: ld.lld %t1.o --shared -o %t.so +// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t.o +// RUN: ld.lld %t.so %t.o -o %tout +// RUN: llvm-objdump -triple=armv7a-linux-gnueabihf -d %tout | FileCheck %s --check-prefix=DISASM +// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT +// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s +// REQUIRES: arm + +// Check that the IRELATIVE relocations are last in the .got +// CHECK: Relocations [ +// CHECK-NEXT: Section (4) .rel.dyn { +// CHECK-NEXT: 0x12078 R_ARM_GLOB_DAT bar2 0x0 +// CHECK-NEXT: 0x1207C R_ARM_GLOB_DAT zed2 0x0 +// CHECK-NEXT: 0x12080 R_ARM_IRELATIVE - 0x0 +// CHECK-NEXT: 0x12084 R_ARM_IRELATIVE - 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: Section (5) .rel.plt { +// CHECK-NEXT: 0x1300C R_ARM_JUMP_SLOT bar2 0x0 +// CHECK-NEXT: 0x13010 R_ARM_JUMP_SLOT zed2 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: ] + +// Check that the GOT entries refer back to the ifunc resolver +// GOTPLT: Contents of section .got: +// GOTPLT-NEXT: 12078 00000000 00000000 00100100 04100100 +// GOTPLT-NEXT: Contents of section .got.plt: +// GOTPLT-NEXT: 13000 00000000 00000000 00000000 20100100 +// GOTPLT-NEXT: 13010 20100100 + +// DISASM: Disassembly of section .text: +// DISASM-NEXT: foo: +// DISASM-NEXT: 11000: 1e ff 2f e1 bx lr +// DISASM: bar: +// DISASM-NEXT: 11004: 1e ff 2f e1 bx lr +// DISASM: _start: +// DISASM-NEXT: 11008: 14 00 00 eb bl #80 +// DISASM-NEXT: 1100c: 17 00 00 eb bl #92 +// DISASM: 11010: 00 00 00 00 .word 0x00000000 +// DISASM-NEXT: 11014: 04 00 00 00 .word 0x00000004 +// DISASM: 11018: 05 00 00 eb bl #20 +// DISASM-NEXT: 1101c: 08 00 00 eb bl #32 +// DISASM-NEXT: Disassembly of section .plt: +// DISASM-NEXT: .plt: +// DISASM-NEXT: 11020: 04 e0 2d e5 str lr, [sp, #-4]! +// DISASM-NEXT: 11024: 04 e0 9f e5 ldr lr, [pc, #4] +// DISASM-NEXT: 11028: 0e e0 8f e0 add lr, pc, lr +// DISASM-NEXT: 1102c: 08 f0 be e5 ldr pc, [lr, #8]! +// DISASM-NEXT: 11030: d0 1f 00 00 +// DISASM-NEXT: 11034: 04 c0 9f e5 ldr r12, [pc, #4] +// DISASM-NEXT: 11038: 0f c0 8c e0 add r12, r12, pc +// DISASM-NEXT: 1103c: 00 f0 9c e5 ldr pc, [r12] +// DISASM-NEXT: 11040: cc 1f 00 00 +// DISASM-NEXT: 11044: 04 c0 9f e5 ldr r12, [pc, #4] +// DISASM-NEXT: 11048: 0f c0 8c e0 add r12, r12, pc +// DISASM-NEXT: 1104c: 00 f0 9c e5 ldr pc, [r12] +// DISASM-NEXT: 11050: c0 1f 00 00 +// Alignment to 16 byte boundary not strictly necessary on ARM, but harmless +// DISASM-NEXT: 11054: 00 00 00 00 andeq r0, r0, r0 +// DISASM-NEXT: 11058: 00 00 00 00 andeq r0, r0, r0 +// DISASM-NEXT: 1105c: 00 00 00 00 andeq r0, r0, r0 +// DISASM-NEXT: 11060: 04 c0 9f e5 ldr r12, [pc, #4] +// DISASM-NEXT: 11064: 0f c0 8c e0 add r12, r12, pc +// DISASM-NEXT: 11068: 00 f0 9c e5 ldr pc, [r12] +// DISASM-NEXT: 1106c: 14 10 00 00 +// DISASM-NEXT: 11070: 04 c0 9f e5 ldr r12, [pc, #4] +// DISASM-NEXT: 11074: 0f c0 8c e0 add r12, r12, pc +// DISASM-NEXT: 11078: 00 f0 9c e5 ldr pc, [r12] +// DISASM-NEXT: 1107c: 08 10 00 00 + + +.syntax unified +.text +.type foo STT_GNU_IFUNC +.globl foo +foo: + bx lr + +.type bar STT_GNU_IFUNC +.globl bar +bar: + bx lr + +.globl _start +_start: + bl foo + bl bar + // Create entries in the .got and .rel.dyn so that we don't just have + // IRELATIVE + .word bar2(got) + .word zed2(got) + bl bar2 + bl zed2 Index: lld/trunk/test/ELF/arm-gnu-ifunc.s =================================================================== --- lld/trunk/test/ELF/arm-gnu-ifunc.s +++ lld/trunk/test/ELF/arm-gnu-ifunc.s @@ -24,51 +24,63 @@ movw r0,:lower16:__rel_iplt_end movt r0,:upper16:__rel_iplt_end -// 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: [[REL:.*]] -// CHECK-NEXT: Offset: -// CHECK-NEXT: Size: 16 -// CHECK-NEXT: Link: -// CHECK-NEXT: Info: -// CHECK-NEXT: AddressAlignment: 4 -// CHECK-NEXT: EntrySize: 8 -// CHECK-NEXT: } -// CHECK: Relocations [ -// CHECK-NEXT: Section (1) .rel.plt { -// CHECK-NEXT: 0x1200C R_ARM_IRELATIVE -// CHECK-NEXT: 0x12010 R_ARM_IRELATIVE -// CHECK-NEXT: } -// CHECK-NEXT:] -// CHECK: Symbols [ -// CHECK: Symbol { -// CHECK: Name: __rel_iplt_end -// CHECK-NEXT: Value: 0x100E4 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Local -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other [ -// CHECK-NEXT: STV_HIDDEN -// CHECK-NEXT: ] -// CHECK-NEXT: Section: .rel.plt -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: __rel_iplt_start -// CHECK-NEXT: Value: 0x100D4 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Local -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other [ -// CHECK-NEXT: STV_HIDDEN -// CHECK-NEXT: ] -// CHECK-NEXT: Section: .rel.plt -// CHECK-NEXT: } +// CHECK: Sections [ +// CHECK: Section { +// CHECK: Section { +// CHECK: Name: .rel.dyn +// CHECK-NEXT: Type: SHT_REL +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x100F4 +// CHECK-NEXT: Offset: 0xF4 +// CHECK-NEXT: Size: 16 +// CHECK: Name: .plt +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_EXECINSTR +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x11020 +// CHECK-NEXT: Offset: 0x1020 +// CHECK-NEXT: Size: 32 +// CHECK: Name: .got +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x12000 +// CHECK-NEXT: Offset: 0x2000 +// CHECK-NEXT: Size: 8 +// CHECK: Relocations [ +// CHECK-NEXT: Section (1) .rel.dyn { +// CHECK-NEXT: 0x12000 R_ARM_IRELATIVE +// CHECK-NEXT: 0x12004 R_ARM_IRELATIVE +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK: Symbol { +// CHECK: Name: __rel_iplt_end (6) +// CHECK-NEXT: Value: 0x10104 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other [ +// CHECK-NEXT: STV_HIDDEN +// CHECK-NEXT: ] +// CHECK-NEXT: Section: .rel.dyn +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: __rel_iplt_start +// CHECK-NEXT: Value: 0x100F4 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other [ +// CHECK-NEXT: STV_HIDDEN +// CHECK-NEXT: ] +// CHECK-NEXT: Section: .rel.dyn +// CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: _start // CHECK-NEXT: Value: 0x11008 @@ -97,35 +109,29 @@ // CHECK-NEXT: Section: .text // CHECK-NEXT: } -// DISASM: Disassembly of section .text: +// DISASM: Disassembly of section .text: // DISASM-NEXT: foo: -// DISASM-NEXT: 11000: 1e ff 2f e1 bx lr -// DISASM: bar: -// DISASM-NEXT: 11004: 1e ff 2f e1 bx lr -// DISASM: _start: -// DISASM-NEXT: 11008: 09 00 00 eb bl #36 -// DISASM-NEXT: 1100c: 0c 00 00 eb bl #48 -// DISASM-NEXT: 11010: d4 00 00 e3 movw r0, #212 -// DISASM-NEXT: 11014: 01 00 40 e3 movt r0, #1 -// r0 = 212 + 1 * 65536 = 100D4 = __rel_iplt_start -// DISASM-NEXT: 11018: e4 00 00 e3 movw r0, #228 -// DISASM-NEXT: 1101c: 01 00 40 e3 movt r0, #1 -// r1 = 228 + 1 * 65536 = 100E4 = __rel_iplt_end +// DISASM-NEXT: 11000: 1e ff 2f e1 bx lr +// DISASM: bar: +// DISASM-NEXT: 11004: 1e ff 2f e1 bx lr +// DISASM: _start: +// DISASM-NEXT: 11008: 04 00 00 eb bl #16 +// DISASM-NEXT: 1100c: 07 00 00 eb bl #28 +// 1 * 65536 + 244 = 0x100f4 __rel_iplt_start +// DISASM-NEXT: 11010: f4 00 00 e3 movw r0, #244 +// DISASM-NEXT: 11014: 01 00 40 e3 movt r0, #1 +// 1 * 65536 + 260 = 0x10104 __rel_iplt_end +// DISASM-NEXT: 11018: 04 01 00 e3 movw r0, #260 +// DISASM-NEXT: 1101c: 01 00 40 e3 movt r0, #1 // DISASM-NEXT: Disassembly of section .plt: // DISASM-NEXT: .plt: -// DISASM-NEXT: 11020: 04 e0 2d e5 str lr, [sp, #-4]! -// DISASM-NEXT: 11024: 04 e0 9f e5 ldr lr, [pc, #4] -// DISASM-NEXT: 11028: 0e e0 8f e0 add lr, pc, lr -// DISASM-NEXT: 1102c: 08 f0 be e5 ldr pc, [lr, #8]! -// 0x0fd0 + 0x11028 + 0x8 = 0x12000 -// DISASM-NEXT: 11030: d0 0f 00 00 -// DISASM-NEXT: 11034: 04 c0 9f e5 ldr r12, [pc, #4] -// DISASM-NEXT: 11038: 0f c0 8c e0 add r12, r12, pc -// DISASM-NEXT: 1103c: 00 f0 9c e5 ldr pc, [r12] -// 0x0fcc + 0x11038 + 0x8 = 0x1200C -// DISASM-NEXT: 11040: cc 0f 00 00 -// DISASM-NEXT: 11044: 04 c0 9f e5 ldr r12, [pc, #4] -// DISASM-NEXT: 11048: 0f c0 8c e0 add r12, r12, pc -// DISASM-NEXT: 1104c: 00 f0 9c e5 ldr pc, [r12] -// 0x0fc0 + 0x11048 + 0x8 = 0x12010 -// DISASM-NEXT: 11050: c0 0f 00 00 +// DISASM-NEXT: 11020: 04 c0 9f e5 ldr r12, [pc, #4] +// DISASM-NEXT: 11024: 0f c0 8c e0 add r12, r12, pc +// 11024 + 8 + fd4 = 0x12000 +// DISASM-NEXT: 11028: 00 f0 9c e5 ldr pc, [r12] +// DISASM-NEXT: 1102c: d4 0f 00 00 +// DISASM-NEXT: 11030: 04 c0 9f e5 ldr r12, [pc, #4] +// DISASM-NEXT: 11034: 0f c0 8c e0 add r12, r12, pc +// 11034 + 8 + fc8 = 0x12004 +// DISASM-NEXT: 11038: 00 f0 9c e5 ldr pc, [r12] +// DISASM-NEXT: 1103c: c8 0f 00 00 Index: lld/trunk/test/ELF/gnu-ifunc-i386.s =================================================================== --- lld/trunk/test/ELF/gnu-ifunc-i386.s +++ lld/trunk/test/ELF/gnu-ifunc-i386.s @@ -22,8 +22,8 @@ // CHECK-NEXT: } // CHECK: Relocations [ // CHECK-NEXT: Section ({{.*}}) .rel.plt { -// CHECK-NEXT: 0x1200C R_386_IRELATIVE -// CHECK-NEXT: 0x12010 R_386_IRELATIVE +// CHECK-NEXT: 0x12000 R_386_IRELATIVE +// CHECK-NEXT: 0x12004 R_386_IRELATIVE // CHECK-NEXT: } // CHECK-NEXT: ] @@ -88,30 +88,24 @@ // CHECK-NEXT: } // CHECK-NEXT:] -// DISASM: Disassembly of section .text: +// DISASM: Disassembly of section .text: // DISASM-NEXT: foo: -// DISASM-NEXT: 11000: c3 retl -// DISASM: bar: -// DISASM-NEXT: 11001: c3 retl +// 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: 11002: e8 19 00 00 00 calll 25 +// DISASM-NEXT: 11007: e8 24 00 00 00 calll 36 // 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> +// DISASM-NEXT: 11020: ff 25 00 20 01 00 jmpl *73728 +// DISASM-NEXT: 11026: 68 10 00 00 00 pushl $16 +// DISASM-NEXT: 1102b: e9 e0 ff ff ff jmp -32 <_start+0xE> +// DISASM-NEXT: 11030: ff 25 04 20 01 00 jmpl *73732 +// DISASM-NEXT: 11036: 68 18 00 00 00 pushl $24 +// DISASM-NEXT: 1103b: e9 d0 ff ff ff jmp -48 <_start+0xE> .text .type foo STT_GNU_IFUNC Index: lld/trunk/test/ELF/gnu-ifunc-plt.s =================================================================== --- lld/trunk/test/ELF/gnu-ifunc-plt.s +++ lld/trunk/test/ELF/gnu-ifunc-plt.s @@ -0,0 +1,74 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/shared2-x86-64.s -o %t1.o +// RUN: ld.lld %t1.o --shared -o %t.so +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: ld.lld %t.so %t.o -o %tout +// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM +// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT +// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s +// REQUIRES: x86 + +// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt +// CHECK: Relocations [ +// CHECK-NEXT: Section (4) .rela.plt { +// CHECK-NEXT: 0x203018 R_X86_64_JUMP_SLOT bar2 0x0 +// CHECK-NEXT: 0x203020 R_X86_64_JUMP_SLOT zed2 0x0 +// CHECK-NEXT: 0x203028 R_X86_64_IRELATIVE - 0x201000 +// CHECK-NEXT: 0x203030 R_X86_64_IRELATIVE - 0x201001 + +// Check that .got.plt entries point back to PLT header +// GOTPLT: Contents of section .got.plt: +// GOTPLT-NEXT: 203000 00202000 00000000 00000000 00000000 . ............. +// GOTPLT-NEXT: 203010 00000000 00000000 36102000 00000000 ........6. ..... +// GOTPLT-NEXT: 203020 46102000 00000000 56102000 00000000 F. .....V. ..... +// GOTPLT-NEXT: 203030 66102000 00000000 + +// Check that the PLTRELSZ tag includes the IRELATIVE relocations +// CHECK: DynamicSection [ +// CHECK: 0x0000000000000002 PLTRELSZ 96 (bytes) + +// Check that a PLT header is written and the ifunc entries appear last +// DISASM: Disassembly of section .text: +// DISASM-NEXT: foo: +// DISASM-NEXT: 201000: c3 retq +// DISASM: bar: +// DISASM-NEXT: 201001: c3 retq +// DISASM: _start: +// DISASM-NEXT: 201002: e8 49 00 00 00 callq 73 +// DISASM-NEXT: 201007: e8 54 00 00 00 callq 84 +// DISASM-NEXT: 20100c: e8 1f 00 00 00 callq 31 +// DISASM-NEXT: 201011: e8 2a 00 00 00 callq 42 +// DISASM-NEXT: Disassembly of section .plt: +// DISASM-NEXT: .plt: +// DISASM-NEXT: 201020: ff 35 e2 1f 00 00 pushq 8162(%rip) +// DISASM-NEXT: 201026: ff 25 e4 1f 00 00 jmpq *8164(%rip) +// DISASM-NEXT: 20102c: 0f 1f 40 00 nopl (%rax) +// DISASM-NEXT: 201030: ff 25 e2 1f 00 00 jmpq *8162(%rip) +// DISASM-NEXT: 201036: 68 00 00 00 00 pushq $0 +// DISASM-NEXT: 20103b: e9 e0 ff ff ff jmp -32 <.plt> +// DISASM-NEXT: 201040: ff 25 da 1f 00 00 jmpq *8154(%rip) +// DISASM-NEXT: 201046: 68 01 00 00 00 pushq $1 +// DISASM-NEXT: 20104b: e9 d0 ff ff ff jmp -48 <.plt> +// DISASM-NEXT: 201050: ff 25 d2 1f 00 00 jmpq *8146(%rip) +// DISASM-NEXT: 201056: 68 00 00 00 00 pushq $0 +// DISASM-NEXT: 20105b: e9 e0 ff ff ff jmp -32 <.plt+0x20> +// DISASM-NEXT: 201060: ff 25 ca 1f 00 00 jmpq *8138(%rip) +// DISASM-NEXT: 201066: 68 01 00 00 00 pushq $1 +// DISASM-NEXT: 20106b: e9 d0 ff ff ff jmp -48 <.plt+0x20> + +.text +.type foo STT_GNU_IFUNC +.globl foo +foo: + ret + +.type bar STT_GNU_IFUNC +.globl bar +bar: + ret + +.globl _start +_start: + call foo + call bar + call bar2 + call zed2 Index: lld/trunk/test/ELF/gnu-ifunc-shared.s =================================================================== --- lld/trunk/test/ELF/gnu-ifunc-shared.s +++ lld/trunk/test/ELF/gnu-ifunc-shared.s @@ -0,0 +1,66 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: ld.lld --shared -o %t.so %t.o +// RUN: llvm-objdump -d %t.so | FileCheck %s --check-prefix=DISASM +// RUN: llvm-readobj -r %t.so | FileCheck %s + +// Check that an IRELATIVE relocation is used for a non-preemptible ifunc +// handler and a JUMP_SLOT is used for a preemptible ifunc +// DISASM: Disassembly of section .text: +// DISASM-NEXT: fct: +// DISASM-NEXT: 1000: c3 retq +// DISASM: fct2: +// DISASM-NEXT: 1001: c3 retq +// DISASM: f1: +// DISASM-NEXT: 1002: e8 49 00 00 00 callq 73 +// DISASM-NEXT: 1007: e8 24 00 00 00 callq 36 +// DISASM-NEXT: 100c: e8 2f 00 00 00 callq 47 +// DISASM-NEXT: 1011: c3 retq +// DISASM: f2: +// DISASM-NEXT: 1012: c3 retq +// DISASM-NEXT: Disassembly of section .plt: +// DISASM-NEXT: .plt: +// DISASM-NEXT: 1020: ff 35 e2 1f 00 00 pushq 8162(%rip) +// DISASM-NEXT: 1026: ff 25 e4 1f 00 00 jmpq *8164(%rip) +// DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax) +// DISASM-NEXT: 1030: ff 25 e2 1f 00 00 jmpq *8162(%rip) +// DISASM-NEXT: 1036: 68 00 00 00 00 pushq $0 +// DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt> +// DISASM-NEXT: 1040: ff 25 da 1f 00 00 jmpq *8154(%rip) +// DISASM-NEXT: 1046: 68 01 00 00 00 pushq $1 +// DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt> +// DISASM-NEXT: 1050: ff 25 d2 1f 00 00 jmpq *8146(%rip) +// DISASM-NEXT: 1056: 68 00 00 00 00 pushq $0 +// DISASM-NEXT: 105b: e9 e0 ff ff ff jmp -32 <.plt+0x20> + +// CHECK: Relocations [ +// CHECK-NEXT: Section (4) .rela.plt { +// CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT fct2 0x0 +// CHECK-NEXT: 0x3020 R_X86_64_JUMP_SLOT f2 0x0 +// CHECK-NEXT: 0x3028 R_X86_64_IRELATIVE - 0x1000 + + // Hidden expect IRELATIVE + .globl fct + .hidden fct + .type fct, STT_GNU_IFUNC +fct: + ret + + // Not hidden expect JUMP_SLOT + .globl fct2 + .type fct2, STT_GNU_IFUNC +fct2: + ret + + .globl f1 + .type f1, @function +f1: + call fct + call fct2 + call f2@PLT + ret + + .globl f2 + .type f2, @function +f2: + ret Index: lld/trunk/test/ELF/gnu-ifunc.s =================================================================== --- lld/trunk/test/ELF/gnu-ifunc.s +++ lld/trunk/test/ELF/gnu-ifunc.s @@ -22,8 +22,8 @@ // CHECK-NEXT: } // CHECK: Relocations [ // CHECK-NEXT: Section ({{.*}}) .rela.plt { -// CHECK-NEXT: 0x202018 R_X86_64_IRELATIVE -// CHECK-NEXT: 0x202020 R_X86_64_IRELATIVE +// CHECK-NEXT: 0x202000 R_X86_64_IRELATIVE +// CHECK-NEXT: 0x202008 R_X86_64_IRELATIVE // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK: Symbols [ @@ -87,28 +87,25 @@ // CHECK-NEXT: } // CHECK-NEXT: ] -// DISASM: Disassembly of section .text: +// DISASM: Disassembly of section .text: // DISASM-NEXT: foo: -// DISASM-NEXT: 201000: {{.*}} retq +// DISASM-NEXT: 201000: {{.*}} retq // DISASM: bar: -// DISASM-NEXT: 201001: {{.*}} retq +// DISASM-NEXT: 201001: {{.*}} retq // DISASM: _start: -// DISASM-NEXT: 201002: {{.*}} callq 41 -// DISASM-NEXT: 201007: {{.*}} callq 52 -// DISASM-NEXT: 20100c: {{.*}} movl $2097496, %edx -// DISASM-NEXT: 201011: {{.*}} movl $2097544, %edx -// DISASM-NEXT: 201016: {{.*}} movl $2097545, %edx +// DISASM-NEXT: 201002: {{.*}} callq 25 +// DISASM-NEXT: 201007: {{.*}} callq 36 +// DISASM-NEXT: 20100c: {{.*}} movl $2097496, %edx +// DISASM-NEXT: 201011: {{.*}} movl $2097544, %edx +// DISASM-NEXT: 201016: {{.*}} movl $2097545, %edx // DISASM-NEXT: Disassembly of section .plt: // DISASM-NEXT: .plt: -// DISASM-NEXT: 201020: {{.*}} pushq 4066(%rip) -// DISASM-NEXT: 201026: {{.*}} jmpq *4068(%rip) -// DISASM-NEXT: 20102c: {{.*}} nopl (%rax) -// DISASM-NEXT: 201030: {{.*}} jmpq *4066(%rip) -// DISASM-NEXT: 201036: {{.*}} pushq $0 -// DISASM-NEXT: 20103b: {{.*}} jmp -32 -// DISASM-NEXT: 201040: {{.*}} jmpq *4058(%rip) -// DISASM-NEXT: 201046: {{.*}} pushq $1 -// DISASM-NEXT: 20104b: {{.*}} jmp -48 +// DISASM-NEXT: 201020: {{.*}} jmpq *4058(%rip) +// DISASM-NEXT: 201026: {{.*}} pushq $0 +// DISASM-NEXT: 20102b: {{.*}} jmp -32 <_start+0xE> +// DISASM-NEXT: 201030: {{.*}} jmpq *4050(%rip) +// DISASM-NEXT: 201036: {{.*}} pushq $1 +// DISASM-NEXT: 20103b: {{.*}} jmp -48 <_start+0xE> .text .type foo STT_GNU_IFUNC