[PATCH v2] alpha: enable gnu-indirect-function support for alpha-linux
Matt Turner <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
Enable __attribute__((ifunc)) for alpha*-*-linux*, which sets
HAVE_GNU_INDIRECT_FUNCTION=1 and makes targetm.has_ifunc_p() return
true.
No Alpha backend changes are needed -- the generic ifunc machinery in
varasm.cc handles emission, and alpha/elf.h already provides the
required ASM_OUTPUT_TYPE_DIRECTIVE and ASM_OUTPUT_DEF macros.
Rather than defaulting default_gnu_indirect_function to yes in
config.gcc, this follows the riscv*-*-linux* precedent and gates the
default on a toolchain feature test. A plain assembler test would not
be meaningful: %gnu_indirect_function is handled by generic ELF code in
gas and has been accepted for every target for many years. The real
dependency is on the linker emitting R_ALPHA_IRELATIVE, so the test
assembles, links and inspects the relocations with readelf. Without it
the link silently succeeds while producing an ordinary R_ALPHA_JMP_SLOT.
The existing riscv test is generalized to select the expected relocation
name per target so both share one code path. Alpha needs its own test
source because alpha gas reserves .set for setting assembler modes, so
the alias is spelled with '=', matching the target's ASM_OUTPUT_DEF.
Runtime support additionally requires a glibc dynamic linker that
handles the new relocation.
gcc/ChangeLog:
* configure.ac (gcc_cv_irelative_reloc): New variable, set for
riscv*-*-linux* and alpha*-*-linux*. Perform the linker
IRELATIVE check once, driven by it.
* configure: Regenerate.
---
Changes in v2:
- Gate the default on a linker feature test instead of unconditionally
adding alpha*-* to default_gnu_indirect_function in config.gcc, per
Jeff's question about depending on an unreleased binutils.
- Generalize the existing riscv*-*-linux* IRELATIVE check so both
targets share one code path.
Tested by running the generated configure fragment against both an
alpha-linux-gnu binutils with the pending IFUNC support and the stock
2.47 release; it reports yes and no respectively. With stock 2.47 the
assembler accepts %gnu_indirect_function and emits an STT_GNU_IFUNC
symbol, and the link then succeeds while dropping the relocation
entirely, so an assembler-only test would not catch this.
gcc/configure | 56 ++++++++++++++++++++++++++++++++++++------------
gcc/configure.ac | 52 +++++++++++++++++++++++++++++++++-----------
2 files changed, 82 insertions(+), 26 deletions(-)
diff --git a/gcc/configure b/gcc/configure
index eea63c9721c..f8501781474 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -26608,10 +26608,10 @@ else
fi
+gcc_cv_irelative_reloc=
case "${target}" in
riscv*-*-linux*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker ifunc IRELATIVE support" >&5
-$as_echo_n "checking linker ifunc IRELATIVE support... " >&6; }
+ gcc_cv_irelative_reloc=R_RISCV_IRELATIVE
cat > conftest.s <<EOF
.text
.type foo_resolver, @function
@@ -26630,21 +26630,49 @@ bar:
ret
.size bar, .-bar
EOF
- if test x"$gcc_cv_as" != x \
- && test x"$gcc_cv_ld" != x \
- && test x"$gcc_cv_readelf" != x \
- && $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
- && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
- && $gcc_cv_readelf --relocs --wide conftest \
- | grep R_RISCV_IRELATIVE > /dev/null 2>&1; then
- enable_gnu_indirect_function=yes
- fi
- rm -f conftest conftest.o conftest.s
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gnu_indirect_function" >&5
-$as_echo "$enable_gnu_indirect_function" >&6; }
+ ;;
+ alpha*-*-linux*)
+ # Alpha gas reserves .set for setting assembler modes, so the alias is
+ # spelled with '=' instead, matching the target's ASM_OUTPUT_DEF.
+ gcc_cv_irelative_reloc=R_ALPHA_IRELATIVE
+ cat > conftest.s <<EOF
+ .text
+ .type foo_resolver, @function
+foo_resolver:
+ ret
+ .size foo_resolver, .-foo_resolver
+
+ .globl foo
+ .type foo, %gnu_indirect_function
+ foo = foo_resolver
+
+ .globl bar
+ .type bar, @function
+bar:
+ jsr \$26, foo
+ ret
+ .size bar, .-bar
+EOF
;;
esac
+if test x"$gcc_cv_irelative_reloc" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker ifunc IRELATIVE support" >&5
+$as_echo_n "checking linker ifunc IRELATIVE support... " >&6; }
+ if test x"$gcc_cv_as" != x \
+ && test x"$gcc_cv_ld" != x \
+ && test x"$gcc_cv_readelf" != x \
+ && $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_readelf --relocs --wide conftest \
+ | grep $gcc_cv_irelative_reloc > /dev/null 2>&1; then
+ enable_gnu_indirect_function=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gnu_indirect_function" >&5
+$as_echo "$enable_gnu_indirect_function" >&6; }
+fi
+
gif=`if test x$enable_gnu_indirect_function = xyes; then echo 1; else echo 0; fi`
cat >>confdefs.h <<_ACEOF
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 58576227136..1773706e70a 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3223,9 +3223,10 @@ Valid choices are 'yes' and 'no'.]) ;;
esac],
[enable_gnu_indirect_function="$default_gnu_indirect_function"])
+gcc_cv_irelative_reloc=
case "${target}" in
riscv*-*-linux*)
- AC_MSG_CHECKING(linker ifunc IRELATIVE support)
+ gcc_cv_irelative_reloc=R_RISCV_IRELATIVE
cat > conftest.s <<EOF
.text
.type foo_resolver, @function
@@ -3244,20 +3245,47 @@ bar:
ret
.size bar, .-bar
EOF
- if test x"$gcc_cv_as" != x \
- && test x"$gcc_cv_ld" != x \
- && test x"$gcc_cv_readelf" != x \
- && $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
- && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
- && $gcc_cv_readelf --relocs --wide conftest \
- | grep R_RISCV_IRELATIVE > /dev/null 2>&1; then
- enable_gnu_indirect_function=yes
- fi
- rm -f conftest conftest.o conftest.s
- AC_MSG_RESULT($enable_gnu_indirect_function)
+ ;;
+ alpha*-*-linux*)
+ # Alpha gas reserves .set for setting assembler modes, so the alias is
+ # spelled with '=' instead, matching the target's ASM_OUTPUT_DEF.
+ gcc_cv_irelative_reloc=R_ALPHA_IRELATIVE
+ cat > conftest.s <<EOF
+ .text
+ .type foo_resolver, @function
+foo_resolver:
+ ret
+ .size foo_resolver, .-foo_resolver
+
+ .globl foo
+ .type foo, %gnu_indirect_function
+ foo = foo_resolver
+
+ .globl bar
+ .type bar, @function
+bar:
+ jsr \$26, foo
+ ret
+ .size bar, .-bar
+EOF
;;
esac
+if test x"$gcc_cv_irelative_reloc" != x; then
+ AC_MSG_CHECKING(linker ifunc IRELATIVE support)
+ if test x"$gcc_cv_as" != x \
+ && test x"$gcc_cv_ld" != x \
+ && test x"$gcc_cv_readelf" != x \
+ && $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_readelf --relocs --wide conftest \
+ | grep $gcc_cv_irelative_reloc > /dev/null 2>&1; then
+ enable_gnu_indirect_function=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ AC_MSG_RESULT($enable_gnu_indirect_function)
+fi
+
gif=`if test x$enable_gnu_indirect_function = xyes; then echo 1; else echo 0; fi`
AC_DEFINE_UNQUOTED(HAVE_GNU_INDIRECT_FUNCTION, $gif,
[Define if your system supports gnu indirect functions.])
--
2.54.0