[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