[PATCH] arm: Enable static-pie support (BZ 34098)
Adhemerval Zanella
adhemerval.zanella@linaro.org
Fri Apr 24 13:49:23 GMT 2026
It requires proper gcc support [1], and without proper compiler support
the arm configure disable static-pie support.
The start.S requires some adjustment to avoid loading main from
the GOT.
Checked on arm-linux-gnueabihf with and without the gcc patch applied.
[1] https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598610.html
---
NEWS | 3 +++
sysdeps/arm/configure | 52 ++++++++++++++++++++++++++++++++++++++++
sysdeps/arm/configure.ac | 29 ++++++++++++++++++++++
sysdeps/arm/start.S | 16 +++++++++++++
4 files changed, 100 insertions(+)
diff --git a/NEWS b/NEWS
index eac9322161..6a45bb06ff 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,9 @@ Major new features:
* New locale added: hrx_BR (Hunsrik language spoken in Brazil).
+* Static PIE is ow support for arm-*-linux-gnueabi. It requires toolchain
+ support to correctly set the expected linker options.
+
Deprecated and removed features, and other changes affecting compatibility:
* Although malloc and related functions currently return pointers
diff --git a/sysdeps/arm/configure b/sysdeps/arm/configure
index 935e022c74..b964c3917a 100644
--- a/sysdeps/arm/configure
+++ b/sysdeps/arm/configure
@@ -1,6 +1,58 @@
# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
# Local configure fragment for sysdeps/arm.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler support static PIE" >&5
+printf %s "checking if compiler support static PIE... " >&6; }
+if test ${libc_cv_static_pie_on_arm+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+cat > conftest.S <<\EOF
+.text
+.global _start
+.type _start,#function
+_start:
+
+.data
+.align 2
+ptr:
+ /* This shoul produce an R_ARM_RELATIVE. */
+ .word _start
+EOF
+
+ libc_cv_static_pie_on_arm=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=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; } \
+ && { ac_try='LC_ALL=C $READELF -Wr conftest | grep -q R_ARM_RELATIVE'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; } \
+ && ! { ac_try='LC_ALL=C $READELF -Wl conftest | grep -q INTERP'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ then
+ libc_cv_static_pie_on_arm=yes
+ fi
+ rm -rf conftest* ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie_on_arm" >&5
+printf "%s\n" "$libc_cv_static_pie_on_arm" >&6; }
+if test "$libc_cv_static_pie_on_arm" = yes; then
+ printf "%s\n" "#define SUPPORT_STATIC_PIE 1" >>confdefs.h
+
+fi
+
# We check to see if the compiler and flags are
# selecting the hard-float ABI and if they are then
# we set libc_cv_arm_pcs_vfp to yes which causes
diff --git a/sysdeps/arm/configure.ac b/sysdeps/arm/configure.ac
index cd00ddc9d9..0c4f0f0de8 100644
--- a/sysdeps/arm/configure.ac
+++ b/sysdeps/arm/configure.ac
@@ -1,6 +1,35 @@
GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
# Local configure fragment for sysdeps/arm.
+dnl Test if the foolchain supports static PIE, the -static-pie should not only
+dnl be accepted, but also generate a ET_DYN without a INTERP entry.
+AC_CACHE_CHECK([if compiler support static PIE],
+libc_cv_static_pie_on_arm, [
+cat > conftest.S <<\EOF
+.text
+.global _start
+.type _start,#function
+_start:
+
+.data
+.align 2
+ptr:
+ /* This shoul produce an R_ARM_RELATIVE. */
+ .word _start
+EOF
+
+ libc_cv_static_pie_on_arm=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_ARM_RELATIVE]) \
+ && ! AC_TRY_COMMAND([LC_ALL=C $READELF -Wl conftest | grep -q INTERP])
+ then
+ libc_cv_static_pie_on_arm=yes
+ fi
+ rm -rf conftest* ])
+if test "$libc_cv_static_pie_on_arm" = yes; then
+ AC_DEFINE(SUPPORT_STATIC_PIE)
+fi
+
# We check to see if the compiler and flags are
# selecting the hard-float ABI and if they are then
# we set libc_cv_arm_pcs_vfp to yes which causes
diff --git a/sysdeps/arm/start.S b/sysdeps/arm/start.S
index a7e62b3934..68e032ef4d 100644
--- a/sysdeps/arm/start.S
+++ b/sysdeps/arm/start.S
@@ -90,6 +90,7 @@ _start:
push { a1 }
#ifdef PIC
+# ifdef SHARED
ldr sl, .L_GOT
adr a4, .L_GOT
add sl, sl, a4
@@ -103,6 +104,16 @@ _start:
/* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
/* Let the libc call main and exit with its return code. */
bl __libc_start_main(PLT)
+# else
+ ldr a1, .L_main_rel /* Load the relative offset of main. */
+ adr a4, .L_main_rel /* Load the actual runtime address of the label. */
+ add a1, a4, a1 /* Add them together to get the absolute address. */
+
+ mov a4, #0 /* Used to be init. */
+ push { a4 } /* Used to be fini. */
+
+ bl __libc_start_main
+# endif
#else
mov a4, #0 /* Used to init. */
@@ -119,9 +130,14 @@ _start:
#ifdef PIC
.align 2
+# ifdef SHARED
.L_GOT:
.word _GLOBAL_OFFSET_TABLE_ - .L_GOT
.word main(GOT)
+# else
+.L_main_rel:
+ .word main - .L_main_rel
+# endif
#endif
.cantunwind
--
2.43.0
More information about the Libc-alpha
mailing list