From c2d6afb4a010a46e0fc73bb4619db9c3796a3077 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Fri, 24 Apr 2026 10:49:23 -0300 Subject: [PATCH] arm: Enable static-pie support (BZ 34098) 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 Reviewed-by: Yury Khrustalev Reviewed-by: Sam James --- 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..e2173fa1aa 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 now supported 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..0cfc1159a0 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 should 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..ab864b665b 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 should 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..3401daf89d 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 /* ifdef SHARED */ #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.47.3