1
1
mirror of https://github.com/rui314/mold.git synced 2024-11-10 10:57:55 +03:00

[ELF] Do not create a PLT entry for IFUNC if -fno-plt

This commit is contained in:
Rui Ueyama 2022-10-02 14:23:19 +08:00
parent 424f43772a
commit 1709ad5996
9 changed files with 93 additions and 15 deletions

View File

@ -434,7 +434,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
}
if (sym.is_ifunc())
sym.flags |= (NEEDS_GOT | NEEDS_PLT);
sym.flags |= NEEDS_GOT;
switch (rel.r_type) {
case R_ARM_ABS32:
@ -447,7 +447,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
case R_ARM_CALL:
case R_ARM_JUMP24:
case R_ARM_THM_JUMP24:
if (sym.is_imported)
if (sym.is_imported || sym.is_ifunc())
sym.flags |= NEEDS_PLT;
break;
case R_ARM_GOT_PREL:

View File

@ -430,7 +430,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
}
if (sym.is_ifunc())
sym.flags |= (NEEDS_GOT | NEEDS_PLT);
sym.flags |= NEEDS_GOT;
switch (rel.r_type) {
case R_AARCH64_ABS64:
@ -443,7 +443,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
break;
case R_AARCH64_CALL26:
case R_AARCH64_JUMP26:
if (sym.is_imported)
if (sym.is_imported || sym.is_ifunc())
sym.flags |= NEEDS_PLT;
break;
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:

View File

@ -441,7 +441,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
}
if (sym.is_ifunc())
sym.flags |= (NEEDS_GOT | NEEDS_PLT);
sym.flags |= NEEDS_GOT;
switch (rel.r_type) {
case R_386_8:
@ -462,7 +462,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
sym.flags |= NEEDS_GOT;
break;
case R_386_PLT32:
if (sym.is_imported)
if (sym.is_imported || sym.is_ifunc())
sym.flags |= NEEDS_PLT;
break;
case R_386_TLS_GOTIE:

View File

@ -241,6 +241,18 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
case R_PPC64_REL16_LO:
*(ul16 *)loc = S + A - P;
break;
case R_PPC64_PLT16_HA:
*(ul16 *)loc = ha(G + GOT - ctx.TOC->value);
break;
case R_PPC64_PLT16_HI:
*(ul16 *)loc = hi(G + GOT - ctx.TOC->value);
break;
case R_PPC64_PLT16_LO:
*(ul16 *)loc = lo(G + GOT - ctx.TOC->value);
break;
case R_PPC64_PLT16_LO_DS:
*(ul16 *)loc |= (G + GOT - ctx.TOC->value) & 0xfffc;
break;
case R_PPC64_GOT_TPREL16_HA:
*(ul16 *)loc = ha(sym.get_gottp_addr(ctx) - ctx.TOC->value);
break;
@ -267,6 +279,8 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
case R_PPC64_GOT_TPREL16_LO_DS:
*(ul16 *)loc |= (sym.get_gottp_addr(ctx) - ctx.TOC->value) & 0xfffc;
break;
case R_PPC64_PLTSEQ:
case R_PPC64_PLTCALL:
case R_PPC64_TLS:
case R_PPC64_TLSGD:
case R_PPC64_TLSLD:
@ -360,7 +374,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
}
if (sym.is_ifunc())
sym.flags |= (NEEDS_GOT | NEEDS_PLT);
sym.flags |= NEEDS_GOT;
switch (rel.r_type) {
case R_PPC64_ADDR64:
@ -370,9 +384,12 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
sym.flags |= NEEDS_GOTTP;
break;
case R_PPC64_REL24:
if (sym.is_imported)
if (sym.is_imported || sym.is_ifunc())
sym.flags |= NEEDS_PLT;
break;
case R_PPC64_PLT16_HA:
sym.flags |= NEEDS_GOT;
break;
case R_PPC64_GOT_TLSGD16_HA:
sym.flags |= NEEDS_TLSGD;
break;
@ -386,6 +403,11 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
case R_PPC64_TOC16_DS:
case R_PPC64_REL16_HA:
case R_PPC64_REL16_LO:
case R_PPC64_PLT16_HI:
case R_PPC64_PLT16_LO:
case R_PPC64_PLT16_LO_DS:
case R_PPC64_PLTSEQ:
case R_PPC64_PLTCALL:
case R_PPC64_TPREL16_HA:
case R_PPC64_TPREL16_LO:
case R_PPC64_GOT_TPREL16_LO_DS:

View File

@ -703,7 +703,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
}
if (sym.is_ifunc())
sym.flags |= (NEEDS_GOT | NEEDS_PLT);
sym.flags |= NEEDS_GOT;
switch (rel.r_type) {
case R_RISCV_32:
@ -722,7 +722,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
break;
case R_RISCV_CALL:
case R_RISCV_CALL_PLT:
if (sym.is_imported)
if (sym.is_imported || sym.is_ifunc())
sym.flags |= NEEDS_PLT;
break;
case R_RISCV_GOT_HI20:

View File

@ -483,7 +483,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
}
if (sym.is_ifunc())
sym.flags |= (NEEDS_GOT | NEEDS_PLT);
sym.flags |= NEEDS_GOT;
switch (rel.r_type) {
case R_SPARC_64:
@ -519,13 +519,14 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
break;
case R_SPARC_PLT32:
case R_SPARC_WPLT30:
case R_SPARC_WDISP30:
case R_SPARC_HIPLT22:
case R_SPARC_LOPLT10:
case R_SPARC_PCPLT32:
case R_SPARC_PCPLT22:
case R_SPARC_PCPLT10:
case R_SPARC_PLT64:
if (sym.is_imported)
if (sym.is_imported || sym.is_ifunc())
sym.flags |= NEEDS_PLT;
break;
case R_SPARC_GOT13:
@ -548,7 +549,6 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
case R_SPARC_WDISP16:
case R_SPARC_WDISP19:
case R_SPARC_WDISP22:
case R_SPARC_WDISP30:
case R_SPARC_PC_HH22:
scan_pcrel_rel(ctx, sym, rel);
break;

View File

@ -633,7 +633,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
}
if (sym.is_ifunc())
sym.flags |= (NEEDS_GOT | NEEDS_PLT);
sym.flags |= NEEDS_GOT;
switch (rel.r_type) {
case R_X86_64_8:
@ -681,7 +681,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
}
case R_X86_64_PLT32:
case R_X86_64_PLTOFF64:
if (sym.is_imported)
if (sym.is_imported || sym.is_ifunc())
sym.flags |= NEEDS_PLT;
break;
case R_X86_64_TLSGD: {

View File

@ -1118,6 +1118,9 @@ static constexpr u32 R_PPC64_GLOB_DAT = 20;
static constexpr u32 R_PPC64_JMP_SLOT = 21;
static constexpr u32 R_PPC64_RELATIVE = 22;
static constexpr u32 R_PPC64_REL32 = 26;
static constexpr u32 R_PPC64_PLT16_LO = 29;
static constexpr u32 R_PPC64_PLT16_HI = 30;
static constexpr u32 R_PPC64_PLT16_HA = 31;
static constexpr u32 R_PPC64_ADDR64 = 38;
static constexpr u32 R_PPC64_ADDR16_HIGHER = 39;
static constexpr u32 R_PPC64_ADDR16_HIGHERA = 40;
@ -1133,6 +1136,7 @@ static constexpr u32 R_PPC64_ADDR16_DS = 56;
static constexpr u32 R_PPC64_ADDR16_LO_DS = 57;
static constexpr u32 R_PPC64_GOT16_DS = 58;
static constexpr u32 R_PPC64_GOT16_LO_DS = 59;
static constexpr u32 R_PPC64_PLT16_LO_DS = 60;
static constexpr u32 R_PPC64_TOC16_DS = 63;
static constexpr u32 R_PPC64_TOC16_LO_DS = 64;
static constexpr u32 R_PPC64_TLS = 67;
@ -1184,6 +1188,8 @@ static constexpr u32 R_PPC64_TPREL16_HIGHA = 113;
static constexpr u32 R_PPC64_DTPREL16_HIGH = 114;
static constexpr u32 R_PPC64_DTPREL16_HIGHA = 115;
static constexpr u32 R_PPC64_REL24_NOTOC = 116;
static constexpr u32 R_PPC64_PLTSEQ = 119;
static constexpr u32 R_PPC64_PLTCALL = 120;
static constexpr u32 R_PPC64_PCREL_OPT = 123;
static constexpr u32 R_PPC64_PCREL34 = 132;
static constexpr u32 R_PPC64_GOT_PCREL34 = 133;
@ -1224,6 +1230,9 @@ inline std::string rel_to_string<PPC64V2>(u32 r_type) {
case R_PPC64_JMP_SLOT: return "R_PPC64_JMP_SLOT";
case R_PPC64_RELATIVE: return "R_PPC64_RELATIVE";
case R_PPC64_REL32: return "R_PPC64_REL32";
case R_PPC64_PLT16_LO: return "R_PPC64_PLT16_LO";
case R_PPC64_PLT16_HI: return "R_PPC64_PLT16_HI";
case R_PPC64_PLT16_HA: return "R_PPC64_PLT16_HA";
case R_PPC64_ADDR64: return "R_PPC64_ADDR64";
case R_PPC64_ADDR16_HIGHER: return "R_PPC64_ADDR16_HIGHER";
case R_PPC64_ADDR16_HIGHERA: return "R_PPC64_ADDR16_HIGHERA";
@ -1239,6 +1248,7 @@ inline std::string rel_to_string<PPC64V2>(u32 r_type) {
case R_PPC64_ADDR16_LO_DS: return "R_PPC64_ADDR16_LO_DS";
case R_PPC64_GOT16_DS: return "R_PPC64_GOT16_DS";
case R_PPC64_GOT16_LO_DS: return "R_PPC64_GOT16_LO_DS";
case R_PPC64_PLT16_LO_DS: return "R_PPC64_PLT16_LO_DS";
case R_PPC64_TOC16_DS: return "R_PPC64_TOC16_DS";
case R_PPC64_TOC16_LO_DS: return "R_PPC64_TOC16_LO_DS";
case R_PPC64_TLS: return "R_PPC64_TLS";
@ -1290,6 +1300,8 @@ inline std::string rel_to_string<PPC64V2>(u32 r_type) {
case R_PPC64_DTPREL16_HIGH: return "R_PPC64_DTPREL16_HIGH";
case R_PPC64_DTPREL16_HIGHA: return "R_PPC64_DTPREL16_HIGHA";
case R_PPC64_REL24_NOTOC: return "R_PPC64_REL24_NOTOC";
case R_PPC64_PLTSEQ: return "R_PPC64_PLTSEQ";
case R_PPC64_PLTCALL: return "R_PPC64_PLTCALL";
case R_PPC64_PCREL_OPT: return "R_PPC64_PCREL_OPT";
case R_PPC64_PCREL34: return "R_PPC64_PCREL34";
case R_PPC64_GOT_PCREL34: return "R_PPC64_GOT_PCREL34";

44
test/elf/ifunc-noplt.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash
export LC_ALL=C
set -e
CC="${TEST_CC:-cc}"
CXX="${TEST_CXX:-c++}"
GCC="${TEST_GCC:-gcc}"
GXX="${TEST_GXX:-g++}"
MACHINE="${MACHINE:-$(uname -m)}"
testname=$(basename "$0" .sh)
echo -n "Testing $testname ... "
t=out/test/elf/$MACHINE/$testname
mkdir -p $t
# IFUNC is not supported on RISC-V yet
[ $MACHINE = riscv64 -o $MACHINE = riscv32 ] && { echo skipped; exit; }
# Skip if libc is musl because musl does not support GNU FUNC
ldd --help 2>&1 | grep -q musl && { echo skipped; exit; }
cat <<EOF | $CC -fPIC -o $t/a.o -c -xc - -fno-plt
#include <stdio.h>
__attribute__((ifunc("resolve_foo")))
void foo(void);
void hello(void) {
printf("Hello world\n");
}
typedef void Fn();
Fn *resolve_foo(void) {
return hello;
}
int main() {
foo();
}
EOF
$CC -B. -o $t/exe $t/a.o
$QEMU $t/exe | grep -q 'Hello world'
echo OK