mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-30 08:40:07 +00:00
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>
(cherry picked from commit cd6ae7ea54
)
This commit is contained in:
parent
bc129fb15b
commit
add8e34cd7
@ -171,6 +171,9 @@
|
||||
/* Define if gcc supports attribute ifunc. */
|
||||
#undef HAVE_GCC_IFUNC
|
||||
|
||||
/* Define if CC supports attribute retain. */
|
||||
#undef HAVE_GNU_RETAIN
|
||||
|
||||
#define WANT_FLOAT128 0
|
||||
|
||||
/*
|
||||
|
59
configure
vendored
59
configure
vendored
@ -4061,6 +4061,31 @@ fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_indirect_function" >&5
|
||||
$as_echo "$libc_cv_gcc_indirect_function" >&6; }
|
||||
|
||||
# Check if CC supports attribute retain as it is used in attribute_used_retain macro.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU attribute retain support" >&5
|
||||
$as_echo_n "checking for GNU attribute retain support... " >&6; }
|
||||
if ${libc_cv_gnu_retain+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
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>&5 \
|
||||
2>&5 ; then
|
||||
libc_cv_gnu_retain=yes
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gnu_retain" >&5
|
||||
$as_echo "$libc_cv_gnu_retain" >&6; }
|
||||
if test $libc_cv_gnu_retain = yes; then
|
||||
$as_echo "#define HAVE_GNU_RETAIN 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
config_vars="$config_vars
|
||||
have-gnu-retain = $libc_cv_gnu_retain"
|
||||
|
||||
# Check if gcc warns about alias for function with incompatible types.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler warns about alias for function with incompatible types" >&5
|
||||
$as_echo_n "checking if compiler warns about alias for function with incompatible types... " >&6; }
|
||||
@ -5884,6 +5909,40 @@ fi
|
||||
$as_echo "$libc_linker_feature" >&6; }
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z start-stop-gc" >&5
|
||||
$as_echo_n "checking for linker that supports -z start-stop-gc... " >&6; }
|
||||
libc_linker_feature=no
|
||||
if test x"$gnu_ld" = x"yes"; then
|
||||
libc_linker_check=`$LD -v --help 2>/dev/null | grep "\-z start-stop-gc"`
|
||||
if test -n "$libc_linker_check"; then
|
||||
cat > conftest.c <<EOF
|
||||
int _start (void) { return 42; }
|
||||
EOF
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
|
||||
-Wl,-z,start-stop-gc -nostdlib -nostartfiles
|
||||
-fPIC -shared -o conftest.so conftest.c
|
||||
1>&5'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }
|
||||
then
|
||||
libc_linker_feature=yes
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
fi
|
||||
if test $libc_linker_feature = yes; then
|
||||
libc_cv_z_start_stop_gc=yes
|
||||
else
|
||||
libc_cv_z_start_stop_gc=no
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
|
||||
$as_echo "$libc_linker_feature" >&6; }
|
||||
config_vars="$config_vars
|
||||
have-z-start-stop-gc = $libc_cv_z_start_stop_gc"
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-dynamic-linker" >&5
|
||||
$as_echo_n "checking for linker that supports --no-dynamic-linker... " >&6; }
|
||||
libc_linker_feature=no
|
||||
|
21
configure.ac
21
configure.ac
@ -670,6 +670,23 @@ if ${CC-cc} -c conftest.c -o conftest.o 1>&AS_MESSAGE_LOG_FD \
|
||||
fi
|
||||
rm -f conftest*])
|
||||
|
||||
# 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
|
||||
@ -1333,6 +1350,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],
|
||||
|
@ -286,6 +286,12 @@ for linking")
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_GNU_RETAIN
|
||||
# define attribute_used_retain __attribute__ ((__used__, __retain__))
|
||||
#else
|
||||
# define attribute_used_retain __attribute__ ((__used__))
|
||||
#endif
|
||||
|
||||
/* Symbol set support macros. */
|
||||
|
||||
/* Make SYMBOL, which is in the text segment, an element of SET. */
|
||||
@ -301,12 +307,12 @@ for linking")
|
||||
/* When building a shared library, make the set section writable,
|
||||
because it will need to be relocated at run time anyway. */
|
||||
# define _elf_set_element(set, symbol) \
|
||||
static const void *__elf_set_##set##_element_##symbol##__ \
|
||||
__attribute__ ((used, section (#set))) = &(symbol)
|
||||
static const void *__elf_set_##set##_element_##symbol##__ \
|
||||
attribute_used_retain __attribute__ ((section (#set))) = &(symbol)
|
||||
#else
|
||||
# define _elf_set_element(set, symbol) \
|
||||
static const void *const __elf_set_##set##_element_##symbol##__ \
|
||||
__attribute__ ((used, section (#set))) = &(symbol)
|
||||
static const void *const __elf_set_##set##_element_##symbol##__ \
|
||||
attribute_used_retain __attribute__ ((section (#set))) = &(symbol)
|
||||
#endif
|
||||
|
||||
/* Define SET as a symbol set. This may be required (it is in a.out) to
|
||||
|
@ -177,6 +177,26 @@ ifeq (yes,$(build-shared))
|
||||
# library is enabled since they depend on tst-fopenloc.out.
|
||||
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
|
||||
endif
|
||||
|
||||
tests += tst-cleanup-default tst-cleanup-default-static
|
||||
tests-static += tst-cleanup-default-static
|
||||
tests-special += $(objpfx)tst-cleanup-default-cmp.out $(objpfx)tst-cleanup-default-static-cmp.out
|
||||
LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
|
||||
LDFLAGS-tst-cleanup-default-static = -Wl,--gc-sections
|
||||
|
||||
ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
|
||||
tests += tst-cleanup-start-stop-gc tst-cleanup-start-stop-gc-static \
|
||||
tst-cleanup-nostart-stop-gc tst-cleanup-nostart-stop-gc-static
|
||||
tests-static += tst-cleanup-start-stop-gc-static tst-cleanup-nostart-stop-gc-static
|
||||
tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
|
||||
$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out \
|
||||
$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out \
|
||||
$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out
|
||||
LDFLAGS-tst-cleanup-start-stop-gc := -Wl,--gc-sections,-z,start-stop-gc
|
||||
LDFLAGS-tst-cleanup-start-stop-gc-static := -Wl,--gc-sections,-z,start-stop-gc
|
||||
LDFLAGS-tst-cleanup-nostart-stop-gc := -Wl,--gc-sections,-z,nostart-stop-gc
|
||||
LDFLAGS-tst-cleanup-nostart-stop-gc-static := -Wl,--gc-sections,-z,nostart-stop-gc
|
||||
endif
|
||||
endif
|
||||
|
||||
include ../Rules
|
||||
@ -205,6 +225,14 @@ $(objpfx)tst-widetext.out: $(gen-locales)
|
||||
$(objpfx)tst_wprintf2.out: $(gen-locales)
|
||||
endif
|
||||
|
||||
define gen-tst-cleanup
|
||||
$(objpfx)tst-cleanup-$1-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-$1.out
|
||||
cmp $$^ > $$@; $$(evaluate-test)
|
||||
endef
|
||||
|
||||
$(foreach t,default default-static start-stop-gc start-stop-gc-static nostart-stop-gc nostart-stop-gc-static, \
|
||||
$(eval $(call gen-tst-cleanup,$(t))))
|
||||
|
||||
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
|
||||
$(common-objpfx)libio/ > $@; \
|
||||
|
1
libio/tst-cleanup-default-static.c
Normal file
1
libio/tst-cleanup-default-static.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup.c"
|
1
libio/tst-cleanup-default.c
Normal file
1
libio/tst-cleanup-default.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup.c"
|
1
libio/tst-cleanup-nostart-stop-gc-static.c
Normal file
1
libio/tst-cleanup-nostart-stop-gc-static.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup.c"
|
1
libio/tst-cleanup-nostart-stop-gc.c
Normal file
1
libio/tst-cleanup-nostart-stop-gc.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup.c"
|
1
libio/tst-cleanup-start-stop-gc-static.c
Normal file
1
libio/tst-cleanup-start-stop-gc-static.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup.c"
|
1
libio/tst-cleanup-start-stop-gc.c
Normal file
1
libio/tst-cleanup-start-stop-gc.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-cleanup.c"
|
34
libio/tst-cleanup.c
Normal file
34
libio/tst-cleanup.c
Normal file
@ -0,0 +1,34 @@
|
||||
/* Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Test that stdout is flushed after atexit callbacks were run, even if the
|
||||
* executable is linked with --gc-sections. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
hook (void)
|
||||
{
|
||||
puts ("hello");
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
atexit (hook);
|
||||
}
|
1
libio/tst-cleanup.exp
Normal file
1
libio/tst-cleanup.exp
Normal file
@ -0,0 +1 @@
|
||||
hello
|
Loading…
Reference in New Issue
Block a user