bool NeedsGot = Body && Target->needsGot(Type, *Body);
bool CBP = canBePreempted(Body, NeedsGot);
+ if (IsRela) {
+ auto R = static_cast<const Elf_Rela &>(RI);
+ auto S = static_cast<Elf_Rela *>(P);
+ uintX_t A = NeedsGot ? 0 : R.r_addend;
+ if (CBP)
+ S->r_addend = A;
+ else if (Body)
+ S->r_addend = Body->getVA<ELFT>() + A;
+ else
+ S->r_addend = getLocalRelTarget(File, R, A);
+ }
+
// For a symbol with STT_GNU_IFUNC type, we always create a PLT and
// a GOT entry for the symbol, and emit an IRELATIVE reloc rather than
// the usual JUMP_SLOT reloc for the GOT entry. For the details, you
P->r_offset = Body->getGotVA<ELFT>();
else
P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA();
-
- if (!IsRela)
- continue;
-
- auto R = static_cast<const Elf_Rela &>(RI);
- auto S = static_cast<Elf_Rela *>(P);
- uintX_t A = NeedsGot ? 0 : R.r_addend;
- if (CBP)
- S->r_addend = A;
- else if (Body)
- S->r_addend = Body->getVA<ELFT>() + A;
- else
- S->r_addend = getLocalRelTarget(File, R, A);
}
}
--- /dev/null
+// 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 -r -t %tout | FileCheck %s
+// REQUIRES: x86
+
+.type foo STT_GNU_IFUNC
+.globl foo
+.type foo, @function
+foo:
+ ret
+
+.globl _start
+_start:
+ call foo
+
+// CHECK: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: R_X86_64_IRELATIVE - 0x[[ADDR:.*]]
+// CHECK-NEXT: }
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x[[ADDR]]
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: GNU_IFunc