[RFC PATCH v2] ld: Optionally nullify default PIE in all linker tests
Jens Remus
jremus@linux.ibm.com
Fri Mar 28 14:35:45 GMT 2025
Some distributions configure GCC with --enable-default-pie [1]. LLVM
defaults Clang to CLANG_DEFAULT_PIE_ON_LINUX=ON [2]. This causes
compiles to default to -fPIE and links to default to -pie, unless other
options are explicitly given. As a consequence several linker tests
are compiled and linked in unexpected ways and may even unexpectedly
fail or pass.
Add the configuration variable "NULLIFY_DEFAULT_PIE" to the linker test
suite to optionally nullify default PIE, by prepending $NOPIE_CFLAGS to
the compile flags and $NOPIE_LDFLAGS to the link flags for all linker
tests. These are then overridden by any deviating compiler flags
(e.g. -fPIC or -fPIE) and linker flags (e.g -pie or -shared) explicitly
specified by the tests. Possible values of NULLIFY_DEFAULT_PIE are:
0: Do not nullify default PIE. (default)
1: Unconditionally prefix $NOPIE_CLFAGS and $NOPIE_LDFLAGS.
auto: Prefix $NOPIE_CLFAGS and $NOPIE_LDFLAGS if compiler configured
to default to PIE.
NULLIFY_DEFAULT_PIE can for instance be specified via RUNTESTFLAGS:
$ make check RUNTESTFLAGS="NULLIFY_DEFAULT_PIE=1"
or in ~/.dejagnurc:
# Prefix $NOPIE_CLFAGS and $NOPIE_LDFLAGS if compiler defaults to PIE.
set nullify_default_pie "auto"
[1]: GCC Installation, step "Configuration", configuration option
"--enable-default-pie", https://gcc.gnu.org/install/configure.html
[2]: LLVM D120305 "[Driver] Default CLANG_DEFAULT_PIE_ON_LINUX to ON",
https://reviews.llvm.org/D120305
ld/
PR ld/21090
* NEWS: Mention new test suite configuration variable
NULLIFY_DEFAULT_PIE.
ld/testsuite/
PR ld/21090
* lib/ld-lib.exp (check_default_pie): New test whether compiler
configured to default to PIE.
(check_nullify_default_pie): New test whether default PIE is to
be nullified.
(default_ld_compile): Prepend NOPIE_CFLAGS to nullify default
-fPIE, if default PIE is to be nullified..
(default_ld_link): Prepend NOPIE_LDFLAGS to nullify default
-pie, if default PIE is to be nullified.
Bug: https://sourceware.org/PR21090
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
Notes (jremus):
Changes in V2:
- Introduce linker test suite option NULLIFY_DEFAULT_PIE=0|1|auto to
optionally nullify default PIE. Can be set via RUNTESTFLAGS or
~/.dejagnurc.
- Reword commit subject and message. Add GNU ChangeLog. Reference
PR ld/21090.
With my recent "ld: Pass $NOPIE_CFLAGS and $NOPIE_LDFLAGS to more tests"
patch series I manually nullified GCC/Clang configured with default PIE
in selected linker tests. The tests addressed with that series is far
from complete.
With this patch I propose to introduce a new linker test suite option
NULLIFY_DEFAULT_PIE=0|1|auto to optionally nullify GCC/Clang configured
to default to PIE.
Any feedback is very welcome!
Thanks and regards,
Jens
ld/NEWS | 11 +++++++
ld/testsuite/lib/ld-lib.exp | 58 +++++++++++++++++++++++++++++++++++++
2 files changed, 69 insertions(+)
diff --git a/ld/NEWS b/ld/NEWS
index 494bb83e49b3..b23fb02b13d7 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,16 @@
-*- text -*-
+* Add test suite configuration variable NULLIFY_DEFAULT_PIE to optionally
+ nullify GCC / Clang configured to default to PIE (compiling with -fPIE
+ and linking with -pie). The variable can have the following values:
+ 0: Do not nullify default PIE. (default)
+ 1: Unconditionally nullify default PIE.
+ auto: Nullify default PIE if compiler is configured to default to PIE.
+ The variable can be specified via RUNTESTFLAGS:
+ make check RUNTESTFLAGS="NULLIFY_DEFAULT_PIE=1"
+ or in ~/.dejagnurc:
+ set NULLIFY_DEFAULT_PIE "auto"
+
* Remove the linker -taso option for Alpha target, as Linux/Alpha kernel
support for 32-bit pointers has been removed.
diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp
index 96152718d6f2..ba6f9768516b 100644
--- a/ld/testsuite/lib/ld-lib.exp
+++ b/ld/testsuite/lib/ld-lib.exp
@@ -220,11 +220,17 @@ proc get_board_flags {} {
proc default_ld_link { ld target objects } {
global host_triplet
global exec_output
+ global check_nullify_default_pie
+ global NOPIE_LDFLAGS
set flags ""
if [is_endian_output_format $objects] then {
set flags [big_or_little_endian]
}
+ # Nullify default -pie, e.g. if GCC configured with --enable-default-pie.
+ if [check_nullify_default_pie] then {
+ set flags "$flags $NOPIE_LDFLAGS"
+ }
# When using GCC as the linker driver, we need to specify board cflags when
# linking because cflags may contain linker options. For example when
@@ -257,6 +263,8 @@ proc default_ld_compile { cc source object } {
global subdir
global host_triplet
global gcc_B_opt
+ global check_nullify_default_pie
+ global NOPIE_CFLAGS
set cc_prog $cc
if {[llength $cc_prog] > 1} then {
@@ -271,6 +279,10 @@ proc default_ld_compile { cc source object } {
remote_file host delete "$object"
set flags "$gcc_B_opt -I$srcdir/$subdir"
+ # Nullify default -fPIE, e.g. if GCC configured with --enable-default-pie.
+ if [check_nullify_default_pie] then {
+ append flags " $NOPIE_CFLAGS"
+ }
# If we are compiling with gcc, we want to add gcc_B_opt to flags.
# However, if $prog already has -B options, which might be the
@@ -1709,3 +1721,49 @@ proc skip_sframe_tests { } {
return 1
}
+
+# Returns true if the target compiler is configured with default PIE
+proc check_default_pie { } {
+ global default_pie_saved
+ global CC_FOR_TARGET
+
+ if {![info exists default_pie_saved]} {
+ # Check if gcc is configured with --enable-default-pie
+ set flags [get_board_flags]
+ set basename "tmpdir/check_default_pie[pid]"
+ set src ${basename}.c
+ set output ${basename}.out
+ set f [open $src "w"]
+ puts $f "#ifdef __PIE__"
+ puts $f "int main() { return 0; }"
+ puts $f "#else /* ! __PIE__ */"
+ puts $f "#error \"compiler is not configured with --enable-default-pie\""
+ puts $f "#endif /* ! __PIE__ */"
+ close $f
+ if [is_remote host] {
+ set src [remote_download host $src]
+ }
+ set default_pie_saved [run_host_noleak "$CC_FOR_TARGET" "$flags $src -o $output"]
+ remote_file host delete $src
+ remote_file host delete $output
+ file delete $src
+ }
+ return $default_pie_saved
+}
+
+# Returns true if default PIE should be nullified
+proc check_nullify_default_pie { } {
+ global nullify_default_pie_saved
+ global NULLIFY_DEFAULT_PIE
+
+ if {![info exists nullify_default_pie_saved]} {
+ if { [info exists NULLIFY_DEFAULT_PIE]
+ && ($NULLIFY_DEFAULT_PIE == 1
+ || $NULLIFY_DEFAULT_PIE == "auto" && [check_default_pie]) } {
+ set nullify_default_pie_saved 1
+ } else {
+ set nullify_default_pie_saved 0
+ }
+ }
+ return $nullify_default_pie_saved
+}
--
2.45.2
More information about the Binutils
mailing list