Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -416,6 +416,9 @@ unsigned RelOff = I.second; uint64_t Got = B->getGotPltVA(); uint64_t Plt = this->getVA() + Off; + if (Config->EMachine == EM_ARM && B->isGnuIFunc() && !B->isPreemptible()) + // ARM IRELATIVE relocations are in Rel.Dyn + Got = B->getGotVA(); Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); Off += Target->PltEntrySize; } Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -685,7 +685,8 @@ // If the produced value is a constant, we just remember to write it // when outputting this section. We also have to do it if the format // uses Elf_Rel, since in that case the written value is the addend. - if (Constant || !RelTy::IsRela) + if (Constant || !RelTy::IsRela || + (Body.isGnuIFunc() && Config->EMachine == EM_ARM)) C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); } else { // We don't know anything about the finaly symbol. Just ask the dynamic @@ -726,10 +727,17 @@ else Rel = Target->PltRel; - Out::GotPlt->addEntry(Body); - Out::RelaPlt->addReloc({Rel, Out::GotPlt, - Body.getGotPltOffset(), !Preemptible, - &Body, 0}); + if (Config->EMachine == EM_ARM && Rel == Target->IRelativeRel) { + Out::Got->addEntry(Body); + Out::RelaDyn->addReloc({Rel, Out::Got, + Body.getGotOffset(), !Preemptible, + &Body, 0}); + } else { + Out::GotPlt->addEntry(Body); + Out::RelaPlt->addReloc({Rel, Out::GotPlt, + Body.getGotPltOffset(), + !Preemptible, &Body, 0}); + } continue; } Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -1613,9 +1613,13 @@ 0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8 }; memcpy(Buf, PltData, sizeof(PltData)); - uint64_t GotPlt = Out::GotPlt->getVA(); - uint64_t L1 = Out::Plt->getVA() + 8; - write32le(Buf + 16, GotPlt - L1 - 8); + if (Out::GotPlt->empty()) + write32le(Buf + 16, 0); + else { + uint64_t GotPlt = Out::GotPlt->getVA(); + uint64_t L1 = Out::Plt->getVA() + 8; + write32le(Buf + 16, GotPlt - L1 - 8); + } } void ARMTargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -578,15 +578,21 @@ // all IRELATIVE relocs on startup. For dynamic executables, we don't // need these symbols, since IRELATIVE relocs are resolved through GOT // and PLT. For details, see http://www.airs.com/blog/archives/403. +// On ARM the same symbols are used but the IRELATIVE relocations are in +// .rel.dyn template void Writer::addRelIpltSymbols() { - if (Out::DynSymTab || !Out::RelaPlt) + if (Out::DynSymTab || !Out::RelaPlt || + (!Out::RelaDyn && Config->EMachine == EM_ARM)) return; StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalSynthetic(S, Out::RelaPlt, 0); + addOptionalSynthetic( + S, (Config->EMachine == EM_ARM ? Out::RelaDyn : Out::RelaPlt), + 0); S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end"; - addOptionalSynthetic(S, Out::RelaPlt, - DefinedSynthetic::SectionEnd); + addOptionalSynthetic( + S, (Config->EMachine == EM_ARM ? Out::RelaDyn : Out::RelaPlt), + DefinedSynthetic::SectionEnd); } // The linker is expected to define some symbols depending on @@ -941,6 +947,10 @@ // Even during static linking it can contain R_[*]_IRELATIVE relocations. if (Out::RelaPlt && Out::RelaPlt->hasRelocs()) Add(Out::RelaPlt); + // ARM puts R_ARM_IRELATIVE relocations in rel.dyn. + if (Config->EMachine == EM_ARM && !Out::DynSymTab && + Out::RelaDyn && Out::RelaDyn->hasRelocs()) + Add(Out::RelaDyn); if (needsGot()) Add(Out::Got); Index: test/ELF/arm-gnu-ifunc.s =================================================================== --- test/ELF/arm-gnu-ifunc.s +++ test/ELF/arm-gnu-ifunc.s @@ -1,6 +1,6 @@ // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o // RUN: ld.lld -static %t.o -o %tout -// RUN: llvm-objdump -triple armv7a-none-linux-gnueabi -d %tout | FileCheck %s --check-prefix=DISASM +// RUN: llvm-objdump -triple armv7a-none-linux-gnueabi -s -d %tout | FileCheck %s --check-prefix=DISASM // RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s // REQUIRES: arm .syntax unified @@ -24,108 +24,70 @@ 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-NEXT: Symbol { -// CHECK-NEXT: Name: _start (38) -// CHECK-NEXT: Value: 0x11008 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Global -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other: -// CHECK-NEXT: Section: .text -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: bar -// CHECK-NEXT: Value: 0x11004 -// 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: Name: .rel.dyn +// 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 -// DISASM: Disassembly of section .text: +// CHECK: Relocations [ +// CHECK-NEXT: Section (1) .rel.dyn { +// CHECK-NEXT: 0x12000 R_ARM_IRELATIVE +// CHECK-NEXT: 0x12004 R_ARM_IRELATIVE + +// CHECK: Name: __rel_iplt_end +// CHECK-NEXT: Value: 0x10104 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other [ +// CHECK-NEXT: STV_HIDDEN +// CHECK: 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 + +// 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: Disassembly of section .plt: +// 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: f4 00 00 e3 movw r0, #244 +// DISASM-NEXT: 11014: 01 00 40 e3 movt r0, #1 +// r0 = 224 + 1 * 65536 = 100F4 = __rel_iplt_start +// DISASM-NEXT: 11018: 04 01 00 e3 movw r0, #260 +// DISASM-NEXT: 1101c: 01 00 40 e3 movt r0, #1 +// r0 = 260 + 1 * 65536 = 10104 = __rel_iplt_end +// DISASM: 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 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: 00 00 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] +// 11038 + 8 + fc0 = 12000 = GOT entry for foo +// DISASM-NEXT: 11040: c0 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] +// 11048 + 8 + fb4 = 12004 = GOT entry for bar +// DISASM-NEXT: 11050: b4 0f 00 00 + +// DISASM: Contents of section .got: +// DISASM-NEXT: 12000 00100100 04100100