LoongArch: Add static PIE support

If the compiler is new enough, enable static PIE support.  In the static
PIE version of _start (in rcrt1.o), use la.pcrel instead of la.got
because in a static PIE we cannot use GOT entries until the dynamic
relocations for GOT are resolved.
This commit is contained in:
Xi Ruoyao 2022-09-24 15:45:34 +08:00 committed by caiyinyu
parent 5eb21c62ce
commit 8b10727a9a
3 changed files with 95 additions and 3 deletions

View file

@ -3,3 +3,51 @@
$as_echo "#define HIDDEN_VAR_NEEDS_DYNAMIC_RELOC 1" >>confdefs.h $as_echo "#define HIDDEN_VAR_NEEDS_DYNAMIC_RELOC 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the toolchain is sufficient to build static PIE on LoongArch" >&5
$as_echo_n "checking if the toolchain is sufficient to build static PIE on LoongArch... " >&6; }
if ${libc_cv_static_pie_on_loongarch+:} false; then :
$as_echo_n "(cached) " >&6
else
cat > conftest.S << EOF
.global _start
.type _start, @function
_start:
li.w \$a7, 93
/* This ensures the assembler supports explicit reloc. */
pcalau12i \$a0, %pc_hi20(x)
ld.w \$a0, \$a0, %pc_lo12(x)
syscall 0
.data
x:
.word 0
/* This should produce an R_LARCH_RELATIVE in the static PIE. */
.dword _start
EOF
libc_cv_static_pie_on_loongarch=no
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest conftest.S'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; } \
&& { ac_try='LC_ALL=C $READELF -Wr conftest | grep -q R_LARCH_RELATIVE'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }
then
libc_cv_static_pie_on_loongarch=yes
fi
rm -rf conftest.*
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie_on_loongarch" >&5
$as_echo "$libc_cv_static_pie_on_loongarch" >&6; }
if test "$libc_cv_static_pie_on_loongarch" = yes; then
$as_echo "#define SUPPORT_STATIC_PIE 1" >>confdefs.h
fi

View file

@ -4,3 +4,39 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
dnl It is always possible to access static and hidden symbols in an dnl It is always possible to access static and hidden symbols in an
dnl position independent way. dnl position independent way.
AC_DEFINE(HIDDEN_VAR_NEEDS_DYNAMIC_RELOC) AC_DEFINE(HIDDEN_VAR_NEEDS_DYNAMIC_RELOC)
dnl Test if the toolchain is new enough for static PIE.
dnl We need a GAS supporting explicit reloc (older GAS produces stack-based
dnl reloc and triggers an internal error in the linker). And, we need GCC to
dnl pass the correct linker flags for static PIE. GCC >= 13 and GAS >= 2.40
dnl satisify the requirement, but a distro may backport static PIE support into
dnl earlier GCC or Binutils releases as well.
AC_CACHE_CHECK([if the toolchain is sufficient to build static PIE on LoongArch],
libc_cv_static_pie_on_loongarch, [
cat > conftest.S << EOF
.global _start
.type _start, @function
_start:
li.w \$a7, 93
/* This ensures the assembler supports explicit reloc. */
pcalau12i \$a0, %pc_hi20(x)
ld.w \$a0, \$a0, %pc_lo12(x)
syscall 0
.data
x:
.word 0
/* This should produce an R_LARCH_RELATIVE in the static PIE. */
.dword _start
EOF
libc_cv_static_pie_on_loongarch=no
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest conftest.S]) \
&& AC_TRY_COMMAND([LC_ALL=C $READELF -Wr conftest | grep -q R_LARCH_RELATIVE])
then
libc_cv_static_pie_on_loongarch=yes
fi
rm -rf conftest.*])
if test "$libc_cv_static_pie_on_loongarch" = yes; then
AC_DEFINE(SUPPORT_STATIC_PIE)
fi

View file

@ -60,9 +60,17 @@ ENTRY (ENTRY_POINT)
cfi_undefined (1) cfi_undefined (1)
or a5, a0, zero /* rtld_fini */ or a5, a0, zero /* rtld_fini */
#if defined(PIC) && !defined(SHARED)
/* For static PIE, the GOT cannot be used in _start because the GOT entries are
offsets instead of real addresses before __libc_start_main. */
# define LA la.pcrel
#else
/* We must get symbol main through GOT table, since main may not be local. /* We must get symbol main through GOT table, since main may not be local.
For instance: googletest defines main in dynamic library. */ For instance: googletest defines main in dynamic library. */
la.got a0, t0, main # define LA la.got
#endif
LA a0, t0, main
REG_L a1, sp, 0 REG_L a1, sp, 0
ADDI a2, sp, SZREG ADDI a2, sp, SZREG
@ -73,9 +81,9 @@ ENTRY (ENTRY_POINT)
move a4, zero /* used to be fini */ move a4, zero /* used to be fini */
or a6, sp, zero /* stack_end */ or a6, sp, zero /* stack_end */
la.got ra, t0, __libc_start_main LA ra, t0, __libc_start_main
jirl ra, ra, 0 jirl ra, ra, 0
la.got ra, t0, abort LA ra, t0, abort
jirl ra, ra, 0 jirl ra, ra, 0
END (ENTRY_POINT) END (ENTRY_POINT)