about summary refs log tree commit diff
path: root/configure.ac
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2021-04-16 11:26:39 -0700
committerFangrui Song <maskray@google.com>2021-04-16 11:26:39 -0700
commitcd6ae7ea5431c2b8f16201fb0e2c413bf8d2df06 (patch)
tree68d5b5402097696b3e3898fad40a143720da0438 /configure.ac
parent1a8605b6cd257e8a74e29b5b71c057211f5fb847 (diff)
downloadglibc-cd6ae7ea5431c2b8f16201fb0e2c413bf8d2df06.tar.gz
glibc-cd6ae7ea5431c2b8f16201fb0e2c413bf8d2df06.tar.xz
glibc-cd6ae7ea5431c2b8f16201fb0e2c413bf8d2df06.zip
Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
So that text_set_element/data_set_element/bss_set_element defined
variables will be retained by the linker.

Note: 'used' and 'retain' are orthogonal: 'used' makes sure the variable
will not be optimized out; 'retain' prevents section garbage collection
if the linker support SHF_GNU_RETAIN.

GNU ld 2.37 and LLD 13 will support -z start-stop-gc which allow C
identifier name sections to be GCed even if there are live
__start_/__stop_ references.

Without the change, there are some static linking problems, e.g.
_IO_cleanup (libio/genops.c) may be discarded by ld --gc-sections, so
stdout is not flushed on exit.

Note: GCC may warning 'retain' attribute ignored while __has_attribute(retain)
is 1 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99587).

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Diffstat (limited to 'configure.ac')
-rw-r--r--configure.ac21
1 files changed, 21 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index fce967f2c2..cc47e56e82 100644
--- a/configure.ac
+++ b/configure.ac
@@ -707,6 +707,23 @@ fi
 rm -f conftest*])
 AC_SUBST(libc_cv_textrel_ifunc)
 
+# Check if CC supports attribute retain as it is used in attribute_used_retain macro.
+AC_CACHE_CHECK([for GNU attribute retain support],
+	       libc_cv_gnu_retain, [dnl
+cat > conftest.c <<EOF
+static int var  __attribute__ ((used, retain, section ("__libc_atexit")));
+EOF
+libc_cv_gnu_retain=no
+if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&AS_MESSAGE_LOG_FD \
+   2>&AS_MESSAGE_LOG_FD ; then
+  libc_cv_gnu_retain=yes
+fi
+rm -f conftest*])
+if test $libc_cv_gnu_retain = yes; then
+  AC_DEFINE(HAVE_GNU_RETAIN)
+fi
+LIBC_CONFIG_VAR([have-gnu-retain], [$libc_cv_gnu_retain])
+
 # Check if gcc warns about alias for function with incompatible types.
 AC_CACHE_CHECK([if compiler warns about alias for function with incompatible types],
 	       libc_cv_gcc_incompatible_alias, [dnl
@@ -1317,6 +1334,10 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack],
 		    [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no])
 AC_SUBST(libc_cv_z_execstack)
 
+LIBC_LINKER_FEATURE([-z start-stop-gc], [-Wl,-z,start-stop-gc],
+		    [libc_cv_z_start_stop_gc=yes], [libc_cv_z_start_stop_gc=no])
+LIBC_CONFIG_VAR([have-z-start-stop-gc], [$libc_cv_z_start_stop_gc])
+
 LIBC_LINKER_FEATURE([--no-dynamic-linker],
 		    [-Wl,--no-dynamic-linker],
 		    [libc_cv_no_dynamic_linker=yes],