* [PATCH] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
@ 2021-03-15 1:10 Fangrui Song
2021-03-15 7:28 ` Florian Weimer
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-03-15 1:10 UTC (permalink / raw)
To: libc-alpha; +Cc: Fangrui Song
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.36 and LLD 13 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: `#if defined (__has_attribute) && __has_attribute (retain)`
does not work in GCC assembly mode:
error: missing binary operator before token "("
---
include/libc-symbols.h | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index c83e550b03..291a8d8f08 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -373,16 +373,32 @@ for linking")
/* These are all done the same way in ELF.
There is a new section created for each set. */
-#ifdef SHARED
+#ifdef __has_attribute
+#if __has_attribute (retain)
+# ifdef SHARED
/* 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) \
+# define _elf_set_element(set, symbol) \
static const void *__elf_set_##set##_element_##symbol##__ \
- __attribute__ ((used, section (#set))) = &(symbol)
+ __attribute__ ((used, retain, section (#set))) = &(symbol)
+# else
+# define _elf_set_element(set, symbol) \
+ static const void *const __elf_set_##set##_element_##symbol##__ \
+ __attribute__ ((used, retain, section (#set))) = &(symbol)
+# endif
#else
-# define _elf_set_element(set, symbol) \
+# ifdef SHARED
+/* 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)
+# else
+# define _elf_set_element(set, symbol) \
static const void *const __elf_set_##set##_element_##symbol##__ \
__attribute__ ((used, section (#set))) = &(symbol)
+# endif
+#endif
#endif
/* Define SET as a symbol set. This may be required (it is in a.out) to
--
2.31.0.rc2.261.g7f71774620-goog
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-15 1:10 [PATCH] Set the retain attribute on _elf_set_element if CC supports [BZ #27492] Fangrui Song
@ 2021-03-15 7:28 ` Florian Weimer
2021-03-15 7:45 ` Fāng-ruì Sòng
0 siblings, 1 reply; 40+ messages in thread
From: Florian Weimer @ 2021-03-15 7:28 UTC (permalink / raw)
To: Fangrui Song via Libc-alpha; +Cc: Fangrui Song
* Fangrui Song via Libc-alpha:
> 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.
This needs recent-ish GCC 11, see commit 6347f4a0904fce17e ("Add retain
attribute to place symbols in SHF_GNU_RETAIN section).
> +#ifdef __has_attribute
> +#if __has_attribute (retain)
> +# ifdef SHARED
Indentation is off there.
It's probably simpler to define a new macro, like
ELEMENT_SECTION_ATTRIBUTES, and use that unconditionally, perhaps like
this?
#ifndef __ASSEMBLER__
# if defined (__has_attribute) && __has_attribute (retain)
# define ELEMENT_SECTION_ATTRIBUTES used, retain
# else
# define ELEMENT_SECTION_ATTRIBUTES used
# endif
#endif
Have you checked that __has_attribute (retain) is only true on GCC if
the underlying linker has retain support and the attribute does not
produce a warning?
Thanks,
Florian
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-15 7:28 ` Florian Weimer
@ 2021-03-15 7:45 ` Fāng-ruì Sòng
2021-03-15 8:13 ` Florian Weimer
0 siblings, 1 reply; 40+ messages in thread
From: Fāng-ruì Sòng @ 2021-03-15 7:45 UTC (permalink / raw)
To: Florian Weimer; +Cc: Fangrui Song via Libc-alpha
On Mon, Mar 15, 2021 at 12:28 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * Fangrui Song via Libc-alpha:
>
> > 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.
>
> This needs recent-ish GCC 11, see commit 6347f4a0904fce17e ("Add retain
> attribute to place symbols in SHF_GNU_RETAIN section).
>
> > +#ifdef __has_attribute
> > +#if __has_attribute (retain)
> > +# ifdef SHARED
>
> Indentation is off there.
OK. I can increase the level of indentation...
> It's probably simpler to define a new macro, like
> ELEMENT_SECTION_ATTRIBUTES, and use that unconditionally, perhaps like
> this?
>
> #ifndef __ASSEMBLER__
> # if defined (__has_attribute) && __has_attribute (retain)
> # define ELEMENT_SECTION_ATTRIBUTES used, retain
> # else
> # define ELEMENT_SECTION_ATTRIBUTES used
> # endif
> #endif
`#ifdef __has_attribute` should be fine without #ifndef __ASSEMBLER__ ?
> Have you checked that __has_attribute (retain) is only true on GCC if
> the underlying linker has retain support and the attribute does not
> produce a warning?
There is a GCC bug. I've reported
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99587
>
> Thanks,
> Florian
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-15 7:45 ` Fāng-ruì Sòng
@ 2021-03-15 8:13 ` Florian Weimer
2021-03-22 4:00 ` [PATCH v2] " Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: Florian Weimer @ 2021-03-15 8:13 UTC (permalink / raw)
To: Fāng-ruì Sòng; +Cc: Fangrui Song via Libc-alpha
* Fāng-ruì Sòng:
>> It's probably simpler to define a new macro, like
>> ELEMENT_SECTION_ATTRIBUTES, and use that unconditionally, perhaps like
>> this?
>>
>> #ifndef __ASSEMBLER__
>> # if defined (__has_attribute) && __has_attribute (retain)
>> # define ELEMENT_SECTION_ATTRIBUTES used, retain
>> # else
>> # define ELEMENT_SECTION_ATTRIBUTES used
>> # endif
>> #endif
>
> `#ifdef __has_attribute` should be fine without #ifndef __ASSEMBLER__ ?
ELEMENT_SECTION_ATTRIBUTES is not useful to the assembler, and checking
for __ASSEMBLER__ on the outer level makes it simpler to define the
no-retain case.
>> Have you checked that __has_attribute (retain) is only true on GCC if
>> the underlying linker has retain support and the attribute does not
>> produce a warning?
>
> There is a GCC bug. I've reported
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99587
If this isn't fixed in GCC, we'll need a configure check because we want
to keep building with -Werror=attributes.
Thank,s
Florian
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v2] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-15 8:13 ` Florian Weimer
@ 2021-03-22 4:00 ` Fangrui Song
2021-03-22 4:24 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-03-22 4:00 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: Fangrui Song
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).
---
config.h.in | 3 +++
configure | 23 +++++++++++++++++++++++
configure.ac | 16 ++++++++++++++++
include/libc-symbols.h | 30 +++++++++++++++++++++---------
4 files changed, 63 insertions(+), 9 deletions(-)
diff --git a/config.h.in b/config.h.in
index f21bf04e47..cc875e90f9 100644
--- a/config.h.in
+++ b/config.h.in
@@ -187,6 +187,9 @@
/* Define if gcc supports attribute ifunc. */
#undef HAVE_GCC_IFUNC
+/* Define if gcc supports attribute retain. */
+#undef HAVE_GCC_RETAIN
+
/* Define if the linker defines __ehdr_start. */
#undef HAVE_EHDR_START
diff --git a/configure b/configure
index 37cef37413..28494de748 100755
--- a/configure
+++ b/configure
@@ -4105,6 +4105,29 @@ fi
$as_echo "$libc_cv_textrel_ifunc" >&6; }
+# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
+$as_echo_n "checking for gcc attribute retain support... " >&6; }
+if ${libc_cv_gcc_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_gcc_retain=no
+if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
+ 2>&5 ; then
+ libc_cv_gcc_retain=yes
+fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
+$as_echo "$libc_cv_gcc_retain" >&6; }
+if test $libc_cv_gcc_retain = yes; then
+ $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
+
+fi
+
# 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; }
diff --git a/configure.ac b/configure.ac
index 16b15b6f90..94ad713820 100644
--- a/configure.ac
+++ b/configure.ac
@@ -707,6 +707,22 @@ fi
rm -f conftest*])
AC_SUBST(libc_cv_textrel_ifunc)
+# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
+AC_CACHE_CHECK([for gcc attribute retain support],
+ libc_cv_gcc_retain, [dnl
+cat > conftest.c <<EOF
+static int var __attribute__ ((used, retain, section ("__libc_atexit")));
+EOF
+libc_cv_gcc_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_gcc_retain=yes
+fi
+rm -f conftest*])
+if test $libc_cv_gcc_retain = yes; then
+ AC_DEFINE(HAVE_GCC_RETAIN)
+fi
+
# 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
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index c83e550b03..f8eafcf1f3 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -373,17 +373,29 @@ for linking")
/* These are all done the same way in ELF.
There is a new section created for each set. */
-#ifdef SHARED
+#ifdef HAVE_GCC_RETAIN
+# ifdef SHARED
/* 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)
+ 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, retain, section (#set))) = &(symbol)
+# else
+# define _elf_set_element(set, symbol) \
+ static const void *const __elf_set_##set##_element_##symbol##__ \
+ __attribute__ ((used, retain, section (#set))) = &(symbol)
+# endif
#else
-# define _elf_set_element(set, symbol) \
- static const void *const __elf_set_##set##_element_##symbol##__ \
- __attribute__ ((used, section (#set))) = &(symbol)
-#endif
+# ifdef SHARED
+# define _elf_set_element(set, symbol) \
+ static const void *__elf_set_##set##_element_##symbol##__ \
+ __attribute__ ((used, section (#set))) = &(symbol)
+# else
+# define _elf_set_element(set, symbol) \
+ static const void *const __elf_set_##set##_element_##symbol##__ \
+ __attribute__ ((used, section (#set))) = &(symbol)
+# endif
+#endif /* HAVE_GCC_RETAIN */
/* Define SET as a symbol set. This may be required (it is in a.out) to
be able to use the set's contents. */
--
2.31.0.rc2.261.g7f71774620-goog
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v2] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-22 4:00 ` [PATCH v2] " Fangrui Song
@ 2021-03-22 4:24 ` H.J. Lu
2021-03-22 4:40 ` Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-03-22 4:24 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Sun, Mar 21, 2021 at 9:01 PM Fangrui Song via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> 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).
> ---
> config.h.in | 3 +++
> configure | 23 +++++++++++++++++++++++
> configure.ac | 16 ++++++++++++++++
> include/libc-symbols.h | 30 +++++++++++++++++++++---------
> 4 files changed, 63 insertions(+), 9 deletions(-)
>
> diff --git a/config.h.in b/config.h.in
> index f21bf04e47..cc875e90f9 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -187,6 +187,9 @@
> /* Define if gcc supports attribute ifunc. */
> #undef HAVE_GCC_IFUNC
>
> +/* Define if gcc supports attribute retain. */
> +#undef HAVE_GCC_RETAIN
> +
> /* Define if the linker defines __ehdr_start. */
> #undef HAVE_EHDR_START
>
> diff --git a/configure b/configure
> index 37cef37413..28494de748 100755
> --- a/configure
> +++ b/configure
> @@ -4105,6 +4105,29 @@ fi
> $as_echo "$libc_cv_textrel_ifunc" >&6; }
>
>
> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> +if ${libc_cv_gcc_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_gcc_retain=no
> +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> + 2>&5 ; then
> + libc_cv_gcc_retain=yes
> +fi
> +rm -f conftest*
> +fi
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> +$as_echo "$libc_cv_gcc_retain" >&6; }
> +if test $libc_cv_gcc_retain = yes; then
> + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> +
> +fi
> +
> # 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; }
> diff --git a/configure.ac b/configure.ac
> index 16b15b6f90..94ad713820 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -707,6 +707,22 @@ fi
> rm -f conftest*])
> AC_SUBST(libc_cv_textrel_ifunc)
>
> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> +AC_CACHE_CHECK([for gcc attribute retain support],
> + libc_cv_gcc_retain, [dnl
> +cat > conftest.c <<EOF
> +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> +EOF
> +libc_cv_gcc_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_gcc_retain=yes
> +fi
> +rm -f conftest*])
> +if test $libc_cv_gcc_retain = yes; then
> + AC_DEFINE(HAVE_GCC_RETAIN)
> +fi
> +
> # 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
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index c83e550b03..f8eafcf1f3 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -373,17 +373,29 @@ for linking")
>
> /* These are all done the same way in ELF.
> There is a new section created for each set. */
> -#ifdef SHARED
> +#ifdef HAVE_GCC_RETAIN
> +# ifdef SHARED
> /* 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)
You should define __attribute_used_and_retain__ instead.
> + 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, retain, section (#set))) = &(symbol)
> +# else
> +# define _elf_set_element(set, symbol) \
> + static const void *const __elf_set_##set##_element_##symbol##__ \
> + __attribute__ ((used, retain, section (#set))) = &(symbol)
> +# endif
> #else
> -# define _elf_set_element(set, symbol) \
> - static const void *const __elf_set_##set##_element_##symbol##__ \
> - __attribute__ ((used, section (#set))) = &(symbol)
> -#endif
> +# ifdef SHARED
> +# define _elf_set_element(set, symbol) \
> + static const void *__elf_set_##set##_element_##symbol##__ \
> + __attribute__ ((used, section (#set))) = &(symbol)
> +# else
> +# define _elf_set_element(set, symbol) \
> + static const void *const __elf_set_##set##_element_##symbol##__ \
> + __attribute__ ((used, section (#set))) = &(symbol)
> +# endif
> +#endif /* HAVE_GCC_RETAIN */
>
> /* Define SET as a symbol set. This may be required (it is in a.out) to
> be able to use the set's contents. */
> --
> 2.31.0.rc2.261.g7f71774620-goog
>
libc.a is an installed file. Does this work with older linkers?
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v2] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-22 4:24 ` H.J. Lu
@ 2021-03-22 4:40 ` Fangrui Song
2021-03-22 20:28 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-03-22 4:40 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-03-21, H.J. Lu wrote:
>On Sun, Mar 21, 2021 at 9:01 PM Fangrui Song via Libc-alpha
><libc-alpha@sourceware.org> wrote:
>>
>> 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).
>> ---
>> config.h.in | 3 +++
>> configure | 23 +++++++++++++++++++++++
>> configure.ac | 16 ++++++++++++++++
>> include/libc-symbols.h | 30 +++++++++++++++++++++---------
>> 4 files changed, 63 insertions(+), 9 deletions(-)
>>
>> diff --git a/config.h.in b/config.h.in
>> index f21bf04e47..cc875e90f9 100644
>> --- a/config.h.in
>> +++ b/config.h.in
>> @@ -187,6 +187,9 @@
>> /* Define if gcc supports attribute ifunc. */
>> #undef HAVE_GCC_IFUNC
>>
>> +/* Define if gcc supports attribute retain. */
>> +#undef HAVE_GCC_RETAIN
>> +
>> /* Define if the linker defines __ehdr_start. */
>> #undef HAVE_EHDR_START
>>
>> diff --git a/configure b/configure
>> index 37cef37413..28494de748 100755
>> --- a/configure
>> +++ b/configure
>> @@ -4105,6 +4105,29 @@ fi
>> $as_echo "$libc_cv_textrel_ifunc" >&6; }
>>
>>
>> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
>> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
>> +$as_echo_n "checking for gcc attribute retain support... " >&6; }
>> +if ${libc_cv_gcc_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_gcc_retain=no
>> +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
>> + 2>&5 ; then
>> + libc_cv_gcc_retain=yes
>> +fi
>> +rm -f conftest*
>> +fi
>> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
>> +$as_echo "$libc_cv_gcc_retain" >&6; }
>> +if test $libc_cv_gcc_retain = yes; then
>> + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
>> +
>> +fi
>> +
>> # 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; }
>> diff --git a/configure.ac b/configure.ac
>> index 16b15b6f90..94ad713820 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -707,6 +707,22 @@ fi
>> rm -f conftest*])
>> AC_SUBST(libc_cv_textrel_ifunc)
>>
>> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
>> +AC_CACHE_CHECK([for gcc attribute retain support],
>> + libc_cv_gcc_retain, [dnl
>> +cat > conftest.c <<EOF
>> +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
>> +EOF
>> +libc_cv_gcc_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_gcc_retain=yes
>> +fi
>> +rm -f conftest*])
>> +if test $libc_cv_gcc_retain = yes; then
>> + AC_DEFINE(HAVE_GCC_RETAIN)
>> +fi
>> +
>> # 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
>> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> index c83e550b03..f8eafcf1f3 100644
>> --- a/include/libc-symbols.h
>> +++ b/include/libc-symbols.h
>> @@ -373,17 +373,29 @@ for linking")
>>
>> /* These are all done the same way in ELF.
>> There is a new section created for each set. */
>> -#ifdef SHARED
>> +#ifdef HAVE_GCC_RETAIN
>> +# ifdef SHARED
>> /* 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)
>
>You should define __attribute_used_and_retain__ instead.
>
>> + 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, retain, section (#set))) = &(symbol)
>> +# else
>> +# define _elf_set_element(set, symbol) \
>> + static const void *const __elf_set_##set##_element_##symbol##__ \
>> + __attribute__ ((used, retain, section (#set))) = &(symbol)
>> +# endif
>> #else
>> -# define _elf_set_element(set, symbol) \
>> - static const void *const __elf_set_##set##_element_##symbol##__ \
>> - __attribute__ ((used, section (#set))) = &(symbol)
>> -#endif
>> +# ifdef SHARED
>> +# define _elf_set_element(set, symbol) \
>> + static const void *__elf_set_##set##_element_##symbol##__ \
>> + __attribute__ ((used, section (#set))) = &(symbol)
>> +# else
>> +# define _elf_set_element(set, symbol) \
>> + static const void *const __elf_set_##set##_element_##symbol##__ \
>> + __attribute__ ((used, section (#set))) = &(symbol)
>> +# endif
>> +#endif /* HAVE_GCC_RETAIN */
>>
>> /* Define SET as a symbol set. This may be required (it is in a.out) to
>> be able to use the set's contents. */
>> --
>> 2.31.0.rc2.261.g7f71774620-goog
>>
>
>libc.a is an installed file. Does this work with older linkers?
>
>--
>H.J.
How about
/* These are all done the same way in ELF.
There is a new section created for each set. */
#ifdef HAVE_GCC_RETAIN
# define attribute_used_retain_section(sec) \
__attribute__ ((used, retain, section (sec)))
#else
# define attribute_used_retain_section(sec) \
__attribute__ ((used, section (sec)))
#endif
#ifdef SHARED
/* 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_retain_section(#set) = &(symbol)
#else
# define _elf_set_element(set, symbol) \
static const void *const __elf_set_##set##_element_##symbol##__ \
attribute_used_retain_section(#set) = &(symbol)
#endif
? Yes, older linkers just ignore unknown section flags. That is the ELF spirit.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v2] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-22 4:40 ` Fangrui Song
@ 2021-03-22 20:28 ` H.J. Lu
2021-03-23 4:14 ` Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-03-22 20:28 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Sun, Mar 21, 2021 at 9:40 PM Fangrui Song <maskray@google.com> wrote:
>
> On 2021-03-21, H.J. Lu wrote:
> >On Sun, Mar 21, 2021 at 9:01 PM Fangrui Song via Libc-alpha
> ><libc-alpha@sourceware.org> wrote:
> >>
> >> 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).
> >> ---
> >> config.h.in | 3 +++
> >> configure | 23 +++++++++++++++++++++++
> >> configure.ac | 16 ++++++++++++++++
> >> include/libc-symbols.h | 30 +++++++++++++++++++++---------
> >> 4 files changed, 63 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/config.h.in b/config.h.in
> >> index f21bf04e47..cc875e90f9 100644
> >> --- a/config.h.in
> >> +++ b/config.h.in
> >> @@ -187,6 +187,9 @@
> >> /* Define if gcc supports attribute ifunc. */
> >> #undef HAVE_GCC_IFUNC
> >>
> >> +/* Define if gcc supports attribute retain. */
> >> +#undef HAVE_GCC_RETAIN
> >> +
> >> /* Define if the linker defines __ehdr_start. */
> >> #undef HAVE_EHDR_START
> >>
> >> diff --git a/configure b/configure
> >> index 37cef37413..28494de748 100755
> >> --- a/configure
> >> +++ b/configure
> >> @@ -4105,6 +4105,29 @@ fi
> >> $as_echo "$libc_cv_textrel_ifunc" >&6; }
> >>
> >>
> >> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> >> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> >> +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> >> +if ${libc_cv_gcc_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_gcc_retain=no
> >> +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> >> + 2>&5 ; then
> >> + libc_cv_gcc_retain=yes
> >> +fi
> >> +rm -f conftest*
> >> +fi
> >> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> >> +$as_echo "$libc_cv_gcc_retain" >&6; }
> >> +if test $libc_cv_gcc_retain = yes; then
> >> + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> >> +
> >> +fi
> >> +
> >> # 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; }
> >> diff --git a/configure.ac b/configure.ac
> >> index 16b15b6f90..94ad713820 100644
> >> --- a/configure.ac
> >> +++ b/configure.ac
> >> @@ -707,6 +707,22 @@ fi
> >> rm -f conftest*])
> >> AC_SUBST(libc_cv_textrel_ifunc)
> >>
> >> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> >> +AC_CACHE_CHECK([for gcc attribute retain support],
> >> + libc_cv_gcc_retain, [dnl
> >> +cat > conftest.c <<EOF
> >> +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> >> +EOF
> >> +libc_cv_gcc_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_gcc_retain=yes
> >> +fi
> >> +rm -f conftest*])
> >> +if test $libc_cv_gcc_retain = yes; then
> >> + AC_DEFINE(HAVE_GCC_RETAIN)
> >> +fi
> >> +
> >> # 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
> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> index c83e550b03..f8eafcf1f3 100644
> >> --- a/include/libc-symbols.h
> >> +++ b/include/libc-symbols.h
> >> @@ -373,17 +373,29 @@ for linking")
> >>
> >> /* These are all done the same way in ELF.
> >> There is a new section created for each set. */
> >> -#ifdef SHARED
> >> +#ifdef HAVE_GCC_RETAIN
> >> +# ifdef SHARED
> >> /* 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)
> >
> >You should define __attribute_used_and_retain__ instead.
> >
> >> + 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, retain, section (#set))) = &(symbol)
> >> +# else
> >> +# define _elf_set_element(set, symbol) \
> >> + static const void *const __elf_set_##set##_element_##symbol##__ \
> >> + __attribute__ ((used, retain, section (#set))) = &(symbol)
> >> +# endif
> >> #else
> >> -# define _elf_set_element(set, symbol) \
> >> - static const void *const __elf_set_##set##_element_##symbol##__ \
> >> - __attribute__ ((used, section (#set))) = &(symbol)
> >> -#endif
> >> +# ifdef SHARED
> >> +# define _elf_set_element(set, symbol) \
> >> + static const void *__elf_set_##set##_element_##symbol##__ \
> >> + __attribute__ ((used, section (#set))) = &(symbol)
> >> +# else
> >> +# define _elf_set_element(set, symbol) \
> >> + static const void *const __elf_set_##set##_element_##symbol##__ \
> >> + __attribute__ ((used, section (#set))) = &(symbol)
> >> +# endif
> >> +#endif /* HAVE_GCC_RETAIN */
> >>
> >> /* Define SET as a symbol set. This may be required (it is in a.out) to
> >> be able to use the set's contents. */
> >> --
> >> 2.31.0.rc2.261.g7f71774620-goog
> >>
> >
> >libc.a is an installed file. Does this work with older linkers?
> >
> >--
> >H.J.
>
> How about
>
> /* These are all done the same way in ELF.
> There is a new section created for each set. */
> #ifdef HAVE_GCC_RETAIN
> # define attribute_used_retain_section(sec) \
> __attribute__ ((used, retain, section (sec)))
> #else
__attribute_used_and_retain__ is more flex and can be used
without section.
> # define attribute_used_retain_section(sec) \
> __attribute__ ((used, section (sec)))
> #endif
> #ifdef SHARED
> /* 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_retain_section(#set) = &(symbol)
> #else
> # define _elf_set_element(set, symbol) \
> static const void *const __elf_set_##set##_element_##symbol##__ \
> attribute_used_retain_section(#set) = &(symbol)
> #endif
> ? Yes, older linkers just ignore unknown section flags. That is the ELF spirit.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v2] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-22 20:28 ` H.J. Lu
@ 2021-03-23 4:14 ` Fangrui Song
2021-03-29 23:11 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-03-23 4:14 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-03-22, H.J. Lu wrote:
>On Sun, Mar 21, 2021 at 9:40 PM Fangrui Song <maskray@google.com> wrote:
>>
>> On 2021-03-21, H.J. Lu wrote:
>> >On Sun, Mar 21, 2021 at 9:01 PM Fangrui Song via Libc-alpha
>> ><libc-alpha@sourceware.org> wrote:
>> >>
>> >> 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).
>> >> ---
>> >> config.h.in | 3 +++
>> >> configure | 23 +++++++++++++++++++++++
>> >> configure.ac | 16 ++++++++++++++++
>> >> include/libc-symbols.h | 30 +++++++++++++++++++++---------
>> >> 4 files changed, 63 insertions(+), 9 deletions(-)
>> >>
>> >> diff --git a/config.h.in b/config.h.in
>> >> index f21bf04e47..cc875e90f9 100644
>> >> --- a/config.h.in
>> >> +++ b/config.h.in
>> >> @@ -187,6 +187,9 @@
>> >> /* Define if gcc supports attribute ifunc. */
>> >> #undef HAVE_GCC_IFUNC
>> >>
>> >> +/* Define if gcc supports attribute retain. */
>> >> +#undef HAVE_GCC_RETAIN
>> >> +
>> >> /* Define if the linker defines __ehdr_start. */
>> >> #undef HAVE_EHDR_START
>> >>
>> >> diff --git a/configure b/configure
>> >> index 37cef37413..28494de748 100755
>> >> --- a/configure
>> >> +++ b/configure
>> >> @@ -4105,6 +4105,29 @@ fi
>> >> $as_echo "$libc_cv_textrel_ifunc" >&6; }
>> >>
>> >>
>> >> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
>> >> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
>> >> +$as_echo_n "checking for gcc attribute retain support... " >&6; }
>> >> +if ${libc_cv_gcc_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_gcc_retain=no
>> >> +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
>> >> + 2>&5 ; then
>> >> + libc_cv_gcc_retain=yes
>> >> +fi
>> >> +rm -f conftest*
>> >> +fi
>> >> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
>> >> +$as_echo "$libc_cv_gcc_retain" >&6; }
>> >> +if test $libc_cv_gcc_retain = yes; then
>> >> + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
>> >> +
>> >> +fi
>> >> +
>> >> # 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; }
>> >> diff --git a/configure.ac b/configure.ac
>> >> index 16b15b6f90..94ad713820 100644
>> >> --- a/configure.ac
>> >> +++ b/configure.ac
>> >> @@ -707,6 +707,22 @@ fi
>> >> rm -f conftest*])
>> >> AC_SUBST(libc_cv_textrel_ifunc)
>> >>
>> >> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
>> >> +AC_CACHE_CHECK([for gcc attribute retain support],
>> >> + libc_cv_gcc_retain, [dnl
>> >> +cat > conftest.c <<EOF
>> >> +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
>> >> +EOF
>> >> +libc_cv_gcc_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_gcc_retain=yes
>> >> +fi
>> >> +rm -f conftest*])
>> >> +if test $libc_cv_gcc_retain = yes; then
>> >> + AC_DEFINE(HAVE_GCC_RETAIN)
>> >> +fi
>> >> +
>> >> # 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
>> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> index c83e550b03..f8eafcf1f3 100644
>> >> --- a/include/libc-symbols.h
>> >> +++ b/include/libc-symbols.h
>> >> @@ -373,17 +373,29 @@ for linking")
>> >>
>> >> /* These are all done the same way in ELF.
>> >> There is a new section created for each set. */
>> >> -#ifdef SHARED
>> >> +#ifdef HAVE_GCC_RETAIN
>> >> +# ifdef SHARED
>> >> /* 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)
>> >
>> >You should define __attribute_used_and_retain__ instead.
>> >
>> >> + 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, retain, section (#set))) = &(symbol)
>> >> +# else
>> >> +# define _elf_set_element(set, symbol) \
>> >> + static const void *const __elf_set_##set##_element_##symbol##__ \
>> >> + __attribute__ ((used, retain, section (#set))) = &(symbol)
>> >> +# endif
>> >> #else
>> >> -# define _elf_set_element(set, symbol) \
>> >> - static const void *const __elf_set_##set##_element_##symbol##__ \
>> >> - __attribute__ ((used, section (#set))) = &(symbol)
>> >> -#endif
>> >> +# ifdef SHARED
>> >> +# define _elf_set_element(set, symbol) \
>> >> + static const void *__elf_set_##set##_element_##symbol##__ \
>> >> + __attribute__ ((used, section (#set))) = &(symbol)
>> >> +# else
>> >> +# define _elf_set_element(set, symbol) \
>> >> + static const void *const __elf_set_##set##_element_##symbol##__ \
>> >> + __attribute__ ((used, section (#set))) = &(symbol)
>> >> +# endif
>> >> +#endif /* HAVE_GCC_RETAIN */
>> >>
>> >> /* Define SET as a symbol set. This may be required (it is in a.out) to
>> >> be able to use the set's contents. */
>> >> --
>> >> 2.31.0.rc2.261.g7f71774620-goog
>> >>
>> >
>> >libc.a is an installed file. Does this work with older linkers?
>> >
>> >--
>> >H.J.
>>
>> How about
>>
>> /* These are all done the same way in ELF.
>> There is a new section created for each set. */
>> #ifdef HAVE_GCC_RETAIN
>> # define attribute_used_retain_section(sec) \
>> __attribute__ ((used, retain, section (sec)))
>> #else
>
>__attribute_used_and_retain__ is more flex and can be used
>without section.
>
>> # define attribute_used_retain_section(sec) \
>> __attribute__ ((used, section (sec)))
>> #endif
>> #ifdef SHARED
>> /* 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_retain_section(#set) = &(symbol)
>> #else
>> # define _elf_set_element(set, symbol) \
>> static const void *const __elf_set_##set##_element_##symbol##__ \
>> attribute_used_retain_section(#set) = &(symbol)
>> #endif
>> ? Yes, older linkers just ignore unknown section flags. That is the ELF spirit.
>
>
>
>--
>H.J.
+#ifdef HAVE_GCC_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. */
@@ -377,12 +383,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
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v2] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-23 4:14 ` Fangrui Song
@ 2021-03-29 23:11 ` H.J. Lu
2021-03-29 23:24 ` [PATCH v3] " Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-03-29 23:11 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Mon, Mar 22, 2021 at 9:15 PM Fangrui Song <maskray@google.com> wrote:
>
>
> On 2021-03-22, H.J. Lu wrote:
> >On Sun, Mar 21, 2021 at 9:40 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2021-03-21, H.J. Lu wrote:
> >> >On Sun, Mar 21, 2021 at 9:01 PM Fangrui Song via Libc-alpha
> >> ><libc-alpha@sourceware.org> wrote:
> >> >>
> >> >> 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).
> >> >> ---
> >> >> config.h.in | 3 +++
> >> >> configure | 23 +++++++++++++++++++++++
> >> >> configure.ac | 16 ++++++++++++++++
> >> >> include/libc-symbols.h | 30 +++++++++++++++++++++---------
> >> >> 4 files changed, 63 insertions(+), 9 deletions(-)
> >> >>
> >> >> diff --git a/config.h.in b/config.h.in
> >> >> index f21bf04e47..cc875e90f9 100644
> >> >> --- a/config.h.in
> >> >> +++ b/config.h.in
> >> >> @@ -187,6 +187,9 @@
> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> #undef HAVE_GCC_IFUNC
> >> >>
> >> >> +/* Define if gcc supports attribute retain. */
> >> >> +#undef HAVE_GCC_RETAIN
> >> >> +
> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> #undef HAVE_EHDR_START
> >> >>
> >> >> diff --git a/configure b/configure
> >> >> index 37cef37413..28494de748 100755
> >> >> --- a/configure
> >> >> +++ b/configure
> >> >> @@ -4105,6 +4105,29 @@ fi
> >> >> $as_echo "$libc_cv_textrel_ifunc" >&6; }
> >> >>
> >> >>
> >> >> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> >> >> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> >> >> +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> >> >> +if ${libc_cv_gcc_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_gcc_retain=no
> >> >> +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> >> >> + 2>&5 ; then
> >> >> + libc_cv_gcc_retain=yes
> >> >> +fi
> >> >> +rm -f conftest*
> >> >> +fi
> >> >> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> >> >> +$as_echo "$libc_cv_gcc_retain" >&6; }
> >> >> +if test $libc_cv_gcc_retain = yes; then
> >> >> + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> >> >> +
> >> >> +fi
> >> >> +
> >> >> # 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; }
> >> >> diff --git a/configure.ac b/configure.ac
> >> >> index 16b15b6f90..94ad713820 100644
> >> >> --- a/configure.ac
> >> >> +++ b/configure.ac
> >> >> @@ -707,6 +707,22 @@ fi
> >> >> rm -f conftest*])
> >> >> AC_SUBST(libc_cv_textrel_ifunc)
> >> >>
> >> >> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> >> >> +AC_CACHE_CHECK([for gcc attribute retain support],
> >> >> + libc_cv_gcc_retain, [dnl
> >> >> +cat > conftest.c <<EOF
> >> >> +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> >> >> +EOF
> >> >> +libc_cv_gcc_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_gcc_retain=yes
> >> >> +fi
> >> >> +rm -f conftest*])
> >> >> +if test $libc_cv_gcc_retain = yes; then
> >> >> + AC_DEFINE(HAVE_GCC_RETAIN)
> >> >> +fi
> >> >> +
> >> >> # 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
> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> index c83e550b03..f8eafcf1f3 100644
> >> >> --- a/include/libc-symbols.h
> >> >> +++ b/include/libc-symbols.h
> >> >> @@ -373,17 +373,29 @@ for linking")
> >> >>
> >> >> /* These are all done the same way in ELF.
> >> >> There is a new section created for each set. */
> >> >> -#ifdef SHARED
> >> >> +#ifdef HAVE_GCC_RETAIN
> >> >> +# ifdef SHARED
> >> >> /* 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)
> >> >
> >> >You should define __attribute_used_and_retain__ instead.
> >> >
> >> >> + 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, retain, section (#set))) = &(symbol)
> >> >> +# else
> >> >> +# define _elf_set_element(set, symbol) \
> >> >> + static const void *const __elf_set_##set##_element_##symbol##__ \
> >> >> + __attribute__ ((used, retain, section (#set))) = &(symbol)
> >> >> +# endif
> >> >> #else
> >> >> -# define _elf_set_element(set, symbol) \
> >> >> - static const void *const __elf_set_##set##_element_##symbol##__ \
> >> >> - __attribute__ ((used, section (#set))) = &(symbol)
> >> >> -#endif
> >> >> +# ifdef SHARED
> >> >> +# define _elf_set_element(set, symbol) \
> >> >> + static const void *__elf_set_##set##_element_##symbol##__ \
> >> >> + __attribute__ ((used, section (#set))) = &(symbol)
> >> >> +# else
> >> >> +# define _elf_set_element(set, symbol) \
> >> >> + static const void *const __elf_set_##set##_element_##symbol##__ \
> >> >> + __attribute__ ((used, section (#set))) = &(symbol)
> >> >> +# endif
> >> >> +#endif /* HAVE_GCC_RETAIN */
> >> >>
> >> >> /* Define SET as a symbol set. This may be required (it is in a.out) to
> >> >> be able to use the set's contents. */
> >> >> --
> >> >> 2.31.0.rc2.261.g7f71774620-goog
> >> >>
> >> >
> >> >libc.a is an installed file. Does this work with older linkers?
> >> >
> >> >--
> >> >H.J.
> >>
> >> How about
> >>
> >> /* These are all done the same way in ELF.
> >> There is a new section created for each set. */
> >> #ifdef HAVE_GCC_RETAIN
> >> # define attribute_used_retain_section(sec) \
> >> __attribute__ ((used, retain, section (sec)))
> >> #else
> >
> >__attribute_used_and_retain__ is more flex and can be used
> >without section.
> >
> >> # define attribute_used_retain_section(sec) \
> >> __attribute__ ((used, section (sec)))
> >> #endif
> >> #ifdef SHARED
> >> /* 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_retain_section(#set) = &(symbol)
> >> #else
> >> # define _elf_set_element(set, symbol) \
> >> static const void *const __elf_set_##set##_element_##symbol##__ \
> >> attribute_used_retain_section(#set) = &(symbol)
> >> #endif
> >> ? Yes, older linkers just ignore unknown section flags. That is the ELF spirit.
> >
> >
> >
> >--
> >H.J.
>
> +#ifdef HAVE_GCC_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. */
> @@ -377,12 +383,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
>
Please submit a v2 patch.
Thanks.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v3] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-29 23:11 ` H.J. Lu
@ 2021-03-29 23:24 ` Fangrui Song
2021-03-30 18:17 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-03-29 23:24 UTC (permalink / raw)
To: libc-alpha, Florian Weimer, H . J . Lu ; +Cc: Fangrui Song
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).
---
Changes in v1 -> v2:
* Define attribute_used_retain_section
Changes in v2 -> v3:
* Use attribute_used_retain instead attribute_used_retain_section
---
config.h.in | 3 +++
configure | 23 +++++++++++++++++++++++
configure.ac | 16 ++++++++++++++++
include/libc-symbols.h | 14 ++++++++++----
4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/config.h.in b/config.h.in
index ca1547ae67..95af1ef229 100644
--- a/config.h.in
+++ b/config.h.in
@@ -187,6 +187,9 @@
/* Define if gcc supports attribute ifunc. */
#undef HAVE_GCC_IFUNC
+/* Define if gcc supports attribute retain. */
+#undef HAVE_GCC_RETAIN
+
/* Define if the linker defines __ehdr_start. */
#undef HAVE_EHDR_START
diff --git a/configure b/configure
index fcf43bf7de..6a6b8ac264 100755
--- a/configure
+++ b/configure
@@ -4105,6 +4105,29 @@ fi
$as_echo "$libc_cv_textrel_ifunc" >&6; }
+# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
+$as_echo_n "checking for gcc attribute retain support... " >&6; }
+if ${libc_cv_gcc_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_gcc_retain=no
+if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
+ 2>&5 ; then
+ libc_cv_gcc_retain=yes
+fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
+$as_echo "$libc_cv_gcc_retain" >&6; }
+if test $libc_cv_gcc_retain = yes; then
+ $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
+
+fi
+
# 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; }
diff --git a/configure.ac b/configure.ac
index fce967f2c2..031b8c3fb3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -707,6 +707,22 @@ fi
rm -f conftest*])
AC_SUBST(libc_cv_textrel_ifunc)
+# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
+AC_CACHE_CHECK([for gcc attribute retain support],
+ libc_cv_gcc_retain, [dnl
+cat > conftest.c <<EOF
+static int var __attribute__ ((used, retain, section ("__libc_atexit")));
+EOF
+libc_cv_gcc_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_gcc_retain=yes
+fi
+rm -f conftest*])
+if test $libc_cv_gcc_retain = yes; then
+ AC_DEFINE(HAVE_GCC_RETAIN)
+fi
+
# 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
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index 546fc26a7b..b311c90f0c 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -352,6 +352,12 @@ for linking")
\f
*/
+#ifdef HAVE_GCC_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. */
@@ -367,12 +373,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
--
2.31.0.291.g576ba9dcdaf-goog
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-29 23:24 ` [PATCH v3] " Fangrui Song
@ 2021-03-30 18:17 ` H.J. Lu
2021-03-30 19:17 ` Fāng-ruì Sòng
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-03-30 18:17 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Mon, Mar 29, 2021 at 4:24 PM Fangrui Song <maskray@google.com> wrote:
>
> 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).
> ---
> Changes in v1 -> v2:
> * Define attribute_used_retain_section
> Changes in v2 -> v3:
> * Use attribute_used_retain instead attribute_used_retain_section
> ---
> config.h.in | 3 +++
> configure | 23 +++++++++++++++++++++++
> configure.ac | 16 ++++++++++++++++
> include/libc-symbols.h | 14 ++++++++++----
> 4 files changed, 52 insertions(+), 4 deletions(-)
>
> diff --git a/config.h.in b/config.h.in
> index ca1547ae67..95af1ef229 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -187,6 +187,9 @@
> /* Define if gcc supports attribute ifunc. */
> #undef HAVE_GCC_IFUNC
>
> +/* Define if gcc supports attribute retain. */
> +#undef HAVE_GCC_RETAIN
> +
> /* Define if the linker defines __ehdr_start. */
> #undef HAVE_EHDR_START
>
> diff --git a/configure b/configure
> index fcf43bf7de..6a6b8ac264 100755
> --- a/configure
> +++ b/configure
> @@ -4105,6 +4105,29 @@ fi
> $as_echo "$libc_cv_textrel_ifunc" >&6; }
>
>
> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> +if ${libc_cv_gcc_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_gcc_retain=no
> +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> + 2>&5 ; then
> + libc_cv_gcc_retain=yes
> +fi
> +rm -f conftest*
> +fi
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> +$as_echo "$libc_cv_gcc_retain" >&6; }
> +if test $libc_cv_gcc_retain = yes; then
> + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> +
> +fi
> +
> # 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; }
> diff --git a/configure.ac b/configure.ac
> index fce967f2c2..031b8c3fb3 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -707,6 +707,22 @@ fi
> rm -f conftest*])
> AC_SUBST(libc_cv_textrel_ifunc)
>
> +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> +AC_CACHE_CHECK([for gcc attribute retain support],
> + libc_cv_gcc_retain, [dnl
> +cat > conftest.c <<EOF
> +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> +EOF
> +libc_cv_gcc_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_gcc_retain=yes
> +fi
> +rm -f conftest*])
> +if test $libc_cv_gcc_retain = yes; then
> + AC_DEFINE(HAVE_GCC_RETAIN)
> +fi
> +
> # 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
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index 546fc26a7b..b311c90f0c 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -352,6 +352,12 @@ for linking")
>
> */
>
> +#ifdef HAVE_GCC_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. */
> @@ -367,12 +373,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
> --
> 2.31.0.291.g576ba9dcdaf-goog
>
Need gc-sections tests for linkers with and without -z start-stop-gc.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-30 18:17 ` H.J. Lu
@ 2021-03-30 19:17 ` Fāng-ruì Sòng
2021-03-30 19:30 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fāng-ruì Sòng @ 2021-03-30 19:17 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On Tue, Mar 30, 2021 at 11:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Mar 29, 2021 at 4:24 PM Fangrui Song <maskray@google.com> wrote:
> >
> > 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).
> > ---
> > Changes in v1 -> v2:
> > * Define attribute_used_retain_section
> > Changes in v2 -> v3:
> > * Use attribute_used_retain instead attribute_used_retain_section
> > ---
> > config.h.in | 3 +++
> > configure | 23 +++++++++++++++++++++++
> > configure.ac | 16 ++++++++++++++++
> > include/libc-symbols.h | 14 ++++++++++----
> > 4 files changed, 52 insertions(+), 4 deletions(-)
> >
> > diff --git a/config.h.in b/config.h.in
> > index ca1547ae67..95af1ef229 100644
> > --- a/config.h.in
> > +++ b/config.h.in
> > @@ -187,6 +187,9 @@
> > /* Define if gcc supports attribute ifunc. */
> > #undef HAVE_GCC_IFUNC
> >
> > +/* Define if gcc supports attribute retain. */
> > +#undef HAVE_GCC_RETAIN
> > +
> > /* Define if the linker defines __ehdr_start. */
> > #undef HAVE_EHDR_START
> >
> > diff --git a/configure b/configure
> > index fcf43bf7de..6a6b8ac264 100755
> > --- a/configure
> > +++ b/configure
> > @@ -4105,6 +4105,29 @@ fi
> > $as_echo "$libc_cv_textrel_ifunc" >&6; }
> >
> >
> > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> > +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> > +if ${libc_cv_gcc_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_gcc_retain=no
> > +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> > + 2>&5 ; then
> > + libc_cv_gcc_retain=yes
> > +fi
> > +rm -f conftest*
> > +fi
> > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> > +$as_echo "$libc_cv_gcc_retain" >&6; }
> > +if test $libc_cv_gcc_retain = yes; then
> > + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> > +
> > +fi
> > +
> > # 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; }
> > diff --git a/configure.ac b/configure.ac
> > index fce967f2c2..031b8c3fb3 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -707,6 +707,22 @@ fi
> > rm -f conftest*])
> > AC_SUBST(libc_cv_textrel_ifunc)
> >
> > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> > +AC_CACHE_CHECK([for gcc attribute retain support],
> > + libc_cv_gcc_retain, [dnl
> > +cat > conftest.c <<EOF
> > +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> > +EOF
> > +libc_cv_gcc_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_gcc_retain=yes
> > +fi
> > +rm -f conftest*])
> > +if test $libc_cv_gcc_retain = yes; then
> > + AC_DEFINE(HAVE_GCC_RETAIN)
> > +fi
> > +
> > # 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
> > diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> > index 546fc26a7b..b311c90f0c 100644
> > --- a/include/libc-symbols.h
> > +++ b/include/libc-symbols.h
> > @@ -352,6 +352,12 @@ for linking")
> >
> > */
> >
> > +#ifdef HAVE_GCC_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. */
> > @@ -367,12 +373,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
> > --
> > 2.31.0.291.g576ba9dcdaf-goog
> >
>
> Need gc-sections tests for linkers with and without -z start-stop-gc.
>
> --
> H.J.
I don't know how to add such a test... It needs to check flush at ext
time but I cannot find a template in libio/tst-* ...
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-30 19:17 ` Fāng-ruì Sòng
@ 2021-03-30 19:30 ` H.J. Lu
2021-03-31 4:34 ` Fāng-ruì Sòng
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-03-30 19:30 UTC (permalink / raw)
To: Fāng-ruì Sòng; +Cc: GNU C Library, Florian Weimer
On Tue, Mar 30, 2021 at 12:17 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>
> On Tue, Mar 30, 2021 at 11:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Mon, Mar 29, 2021 at 4:24 PM Fangrui Song <maskray@google.com> wrote:
> > >
> > > 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).
> > > ---
> > > Changes in v1 -> v2:
> > > * Define attribute_used_retain_section
> > > Changes in v2 -> v3:
> > > * Use attribute_used_retain instead attribute_used_retain_section
> > > ---
> > > config.h.in | 3 +++
> > > configure | 23 +++++++++++++++++++++++
> > > configure.ac | 16 ++++++++++++++++
> > > include/libc-symbols.h | 14 ++++++++++----
> > > 4 files changed, 52 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/config.h.in b/config.h.in
> > > index ca1547ae67..95af1ef229 100644
> > > --- a/config.h.in
> > > +++ b/config.h.in
> > > @@ -187,6 +187,9 @@
> > > /* Define if gcc supports attribute ifunc. */
> > > #undef HAVE_GCC_IFUNC
> > >
> > > +/* Define if gcc supports attribute retain. */
> > > +#undef HAVE_GCC_RETAIN
> > > +
> > > /* Define if the linker defines __ehdr_start. */
> > > #undef HAVE_EHDR_START
> > >
> > > diff --git a/configure b/configure
> > > index fcf43bf7de..6a6b8ac264 100755
> > > --- a/configure
> > > +++ b/configure
> > > @@ -4105,6 +4105,29 @@ fi
> > > $as_echo "$libc_cv_textrel_ifunc" >&6; }
> > >
> > >
> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> > > +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> > > +if ${libc_cv_gcc_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_gcc_retain=no
> > > +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> > > + 2>&5 ; then
> > > + libc_cv_gcc_retain=yes
> > > +fi
> > > +rm -f conftest*
> > > +fi
> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> > > +$as_echo "$libc_cv_gcc_retain" >&6; }
> > > +if test $libc_cv_gcc_retain = yes; then
> > > + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> > > +
> > > +fi
> > > +
> > > # 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; }
> > > diff --git a/configure.ac b/configure.ac
> > > index fce967f2c2..031b8c3fb3 100644
> > > --- a/configure.ac
> > > +++ b/configure.ac
> > > @@ -707,6 +707,22 @@ fi
> > > rm -f conftest*])
> > > AC_SUBST(libc_cv_textrel_ifunc)
> > >
> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> > > +AC_CACHE_CHECK([for gcc attribute retain support],
> > > + libc_cv_gcc_retain, [dnl
> > > +cat > conftest.c <<EOF
> > > +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> > > +EOF
> > > +libc_cv_gcc_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_gcc_retain=yes
> > > +fi
> > > +rm -f conftest*])
> > > +if test $libc_cv_gcc_retain = yes; then
> > > + AC_DEFINE(HAVE_GCC_RETAIN)
> > > +fi
> > > +
> > > # 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
> > > diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> > > index 546fc26a7b..b311c90f0c 100644
> > > --- a/include/libc-symbols.h
> > > +++ b/include/libc-symbols.h
> > > @@ -352,6 +352,12 @@ for linking")
> > >
> > > */
> > >
> > > +#ifdef HAVE_GCC_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. */
> > > @@ -367,12 +373,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
> > > --
> > > 2.31.0.291.g576ba9dcdaf-goog
> > >
> >
> > Need gc-sections tests for linkers with and without -z start-stop-gc.
> >
> > --
> > H.J.
>
> I don't know how to add such a test... It needs to check flush at ext
> time but I cannot find a template in libio/tst-* ...
You can add a special rule to check for linker output with
--print-gc-sections.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-30 19:30 ` H.J. Lu
@ 2021-03-31 4:34 ` Fāng-ruì Sòng
2021-03-31 16:17 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fāng-ruì Sòng @ 2021-03-31 4:34 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-03-30, H.J. Lu wrote:
>On Tue, Mar 30, 2021 at 12:17 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>>
>> On Tue, Mar 30, 2021 at 11:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>> >
>> > On Mon, Mar 29, 2021 at 4:24 PM Fangrui Song <maskray@google.com> wrote:
>> > >
>> > > 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).
>> > > ---
>> > > Changes in v1 -> v2:
>> > > * Define attribute_used_retain_section
>> > > Changes in v2 -> v3:
>> > > * Use attribute_used_retain instead attribute_used_retain_section
>> > > ---
>> > > config.h.in | 3 +++
>> > > configure | 23 +++++++++++++++++++++++
>> > > configure.ac | 16 ++++++++++++++++
>> > > include/libc-symbols.h | 14 ++++++++++----
>> > > 4 files changed, 52 insertions(+), 4 deletions(-)
>> > >
>> > > diff --git a/config.h.in b/config.h.in
>> > > index ca1547ae67..95af1ef229 100644
>> > > --- a/config.h.in
>> > > +++ b/config.h.in
>> > > @@ -187,6 +187,9 @@
>> > > /* Define if gcc supports attribute ifunc. */
>> > > #undef HAVE_GCC_IFUNC
>> > >
>> > > +/* Define if gcc supports attribute retain. */
>> > > +#undef HAVE_GCC_RETAIN
>> > > +
>> > > /* Define if the linker defines __ehdr_start. */
>> > > #undef HAVE_EHDR_START
>> > >
>> > > diff --git a/configure b/configure
>> > > index fcf43bf7de..6a6b8ac264 100755
>> > > --- a/configure
>> > > +++ b/configure
>> > > @@ -4105,6 +4105,29 @@ fi
>> > > $as_echo "$libc_cv_textrel_ifunc" >&6; }
>> > >
>> > >
>> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
>> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
>> > > +$as_echo_n "checking for gcc attribute retain support... " >&6; }
>> > > +if ${libc_cv_gcc_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_gcc_retain=no
>> > > +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
>> > > + 2>&5 ; then
>> > > + libc_cv_gcc_retain=yes
>> > > +fi
>> > > +rm -f conftest*
>> > > +fi
>> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
>> > > +$as_echo "$libc_cv_gcc_retain" >&6; }
>> > > +if test $libc_cv_gcc_retain = yes; then
>> > > + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
>> > > +
>> > > +fi
>> > > +
>> > > # 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; }
>> > > diff --git a/configure.ac b/configure.ac
>> > > index fce967f2c2..031b8c3fb3 100644
>> > > --- a/configure.ac
>> > > +++ b/configure.ac
>> > > @@ -707,6 +707,22 @@ fi
>> > > rm -f conftest*])
>> > > AC_SUBST(libc_cv_textrel_ifunc)
>> > >
>> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
>> > > +AC_CACHE_CHECK([for gcc attribute retain support],
>> > > + libc_cv_gcc_retain, [dnl
>> > > +cat > conftest.c <<EOF
>> > > +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
>> > > +EOF
>> > > +libc_cv_gcc_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_gcc_retain=yes
>> > > +fi
>> > > +rm -f conftest*])
>> > > +if test $libc_cv_gcc_retain = yes; then
>> > > + AC_DEFINE(HAVE_GCC_RETAIN)
>> > > +fi
>> > > +
>> > > # 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
>> > > diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> > > index 546fc26a7b..b311c90f0c 100644
>> > > --- a/include/libc-symbols.h
>> > > +++ b/include/libc-symbols.h
>> > > @@ -352,6 +352,12 @@ for linking")
>> > >
>> > > */
>> > >
>> > > +#ifdef HAVE_GCC_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. */
>> > > @@ -367,12 +373,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
>> > > --
>> > > 2.31.0.291.g576ba9dcdaf-goog
>> > >
>> >
>> > Need gc-sections tests for linkers with and without -z start-stop-gc.
>> >
>> > --
>> > H.J.
>>
>> I don't know how to add such a test... It needs to check flush at ext
>> time but I cannot find a template in libio/tst-* ...
>
>You can add a special rule to check for linker output with
>--print-gc-sections.
I can come up runtime tests. ( https://github.com/MaskRay/glibc/tree/retain)
Runtime tests are direct.
(Unsure how to test --print-gc-sections with tests-static...)
diff --git a/libio/Makefile b/libio/Makefile
index 12ce41038f..5e0e7f00cd 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -195,6 +195,13 @@ ifeq (yes,$(build-shared))
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
$(objpfx)tst-bz24228-mem.out
endif
+
+tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
+tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
+tests-special += $(objpfx)tst-cleanup-start-stop-gc.out \
+ $(objpfx)tst-cleanup-nostart-stop-gc.out
+LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
+LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
endif
include ../Rules
@@ -224,6 +231,20 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.out: $(gen-locales)
endif
+$(objpfx)tst-cleanup-start-stop-gc.out: $(objpfx)tst-cleanup-start-stop-gc
+ $< > $@T
+ grep hello $@T; $(evaluate-test)
+ rm -f $@T
+$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+
+$(objpfx)tst-cleanup-nostart-stop-gc.out: $(objpfx)tst-cleanup-nostart-stop-gc
+ $< > $@T
+ grep hello $@T; $(evaluate-test)
+ rm -f $@T
+$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
$(common-objpfx)libio/; \
diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
new file mode 100644
index 0000000000..de8130a482
--- /dev/null
+++ b/libio/tst-cleanup.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+hook (void)
+{
+ puts ("hello");
+}
+
+int
+main (void)
+{
+ atexit (hook);
+}
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-31 4:34 ` Fāng-ruì Sòng
@ 2021-03-31 16:17 ` H.J. Lu
2021-03-31 18:09 ` Fāng-ruì Sòng
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-03-31 16:17 UTC (permalink / raw)
To: Fāng-ruì Sòng; +Cc: GNU C Library, Florian Weimer
On Tue, Mar 30, 2021 at 9:34 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>
> On 2021-03-30, H.J. Lu wrote:
> >On Tue, Mar 30, 2021 at 12:17 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> >>
> >> On Tue, Mar 30, 2021 at 11:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >> >
> >> > On Mon, Mar 29, 2021 at 4:24 PM Fangrui Song <maskray@google.com> wrote:
> >> > >
> >> > > 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).
> >> > > ---
> >> > > Changes in v1 -> v2:
> >> > > * Define attribute_used_retain_section
> >> > > Changes in v2 -> v3:
> >> > > * Use attribute_used_retain instead attribute_used_retain_section
> >> > > ---
> >> > > config.h.in | 3 +++
> >> > > configure | 23 +++++++++++++++++++++++
> >> > > configure.ac | 16 ++++++++++++++++
> >> > > include/libc-symbols.h | 14 ++++++++++----
> >> > > 4 files changed, 52 insertions(+), 4 deletions(-)
> >> > >
> >> > > diff --git a/config.h.in b/config.h.in
> >> > > index ca1547ae67..95af1ef229 100644
> >> > > --- a/config.h.in
> >> > > +++ b/config.h.in
> >> > > @@ -187,6 +187,9 @@
> >> > > /* Define if gcc supports attribute ifunc. */
> >> > > #undef HAVE_GCC_IFUNC
> >> > >
> >> > > +/* Define if gcc supports attribute retain. */
> >> > > +#undef HAVE_GCC_RETAIN
> >> > > +
> >> > > /* Define if the linker defines __ehdr_start. */
> >> > > #undef HAVE_EHDR_START
> >> > >
> >> > > diff --git a/configure b/configure
> >> > > index fcf43bf7de..6a6b8ac264 100755
> >> > > --- a/configure
> >> > > +++ b/configure
> >> > > @@ -4105,6 +4105,29 @@ fi
> >> > > $as_echo "$libc_cv_textrel_ifunc" >&6; }
> >> > >
> >> > >
> >> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> >> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> >> > > +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> >> > > +if ${libc_cv_gcc_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_gcc_retain=no
> >> > > +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> >> > > + 2>&5 ; then
> >> > > + libc_cv_gcc_retain=yes
> >> > > +fi
> >> > > +rm -f conftest*
> >> > > +fi
> >> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> >> > > +$as_echo "$libc_cv_gcc_retain" >&6; }
> >> > > +if test $libc_cv_gcc_retain = yes; then
> >> > > + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> >> > > +
> >> > > +fi
> >> > > +
> >> > > # 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; }
> >> > > diff --git a/configure.ac b/configure.ac
> >> > > index fce967f2c2..031b8c3fb3 100644
> >> > > --- a/configure.ac
> >> > > +++ b/configure.ac
> >> > > @@ -707,6 +707,22 @@ fi
> >> > > rm -f conftest*])
> >> > > AC_SUBST(libc_cv_textrel_ifunc)
> >> > >
> >> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> >> > > +AC_CACHE_CHECK([for gcc attribute retain support],
> >> > > + libc_cv_gcc_retain, [dnl
> >> > > +cat > conftest.c <<EOF
> >> > > +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> >> > > +EOF
> >> > > +libc_cv_gcc_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_gcc_retain=yes
> >> > > +fi
> >> > > +rm -f conftest*])
> >> > > +if test $libc_cv_gcc_retain = yes; then
> >> > > + AC_DEFINE(HAVE_GCC_RETAIN)
> >> > > +fi
> >> > > +
> >> > > # 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
> >> > > diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> > > index 546fc26a7b..b311c90f0c 100644
> >> > > --- a/include/libc-symbols.h
> >> > > +++ b/include/libc-symbols.h
> >> > > @@ -352,6 +352,12 @@ for linking")
> >> > >
> >> > > */
> >> > >
> >> > > +#ifdef HAVE_GCC_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. */
> >> > > @@ -367,12 +373,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
> >> > > --
> >> > > 2.31.0.291.g576ba9dcdaf-goog
> >> > >
> >> >
> >> > Need gc-sections tests for linkers with and without -z start-stop-gc.
> >> >
> >> > --
> >> > H.J.
> >>
> >> I don't know how to add such a test... It needs to check flush at ext
> >> time but I cannot find a template in libio/tst-* ...
> >
> >You can add a special rule to check for linker output with
> >--print-gc-sections.
>
> I can come up runtime tests. ( https://github.com/MaskRay/glibc/tree/retain)
> Runtime tests are direct.
> (Unsure how to test --print-gc-sections with tests-static...)
>
>
> diff --git a/libio/Makefile b/libio/Makefile
> index 12ce41038f..5e0e7f00cd 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -195,6 +195,13 @@ ifeq (yes,$(build-shared))
> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> $(objpfx)tst-bz24228-mem.out
> endif
> +
> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> +tests-special += $(objpfx)tst-cleanup-start-stop-gc.out \
> + $(objpfx)tst-cleanup-nostart-stop-gc.out
> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
1. Need to check if linker supports -z start-stop-gc.
2. Need to test with only -Wl,--gc-sections.
> endif
>
> include ../Rules
> @@ -224,6 +231,20 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> endif
>
> +$(objpfx)tst-cleanup-start-stop-gc.out: $(objpfx)tst-cleanup-start-stop-gc
> + $< > $@T
> + grep hello $@T; $(evaluate-test)
> + rm -f $@T
tst-cleanup-start-stop-gc.out isn't generated. You should add a ".exp" file
and compare the .out file against it.
> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> +$(objpfx)tst-cleanup-nostart-stop-gc.out: $(objpfx)tst-cleanup-nostart-stop-gc
> + $< > $@T
> + grep hello $@T; $(evaluate-test)
> + rm -f $@T
> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> $(common-objpfx)libio/; \
> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> new file mode 100644
> index 0000000000..de8130a482
> --- /dev/null
> +++ b/libio/tst-cleanup.c
> @@ -0,0 +1,14 @@
Missing comments and copyright notice.
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +void
> +hook (void)
> +{
> + puts ("hello");
> +}
> +
> +int
> +main (void)
> +{
> + atexit (hook);
> +}
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-31 16:17 ` H.J. Lu
@ 2021-03-31 18:09 ` Fāng-ruì Sòng
2021-03-31 18:57 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fāng-ruì Sòng @ 2021-03-31 18:09 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-03-31, H.J. Lu wrote:
>On Tue, Mar 30, 2021 at 9:34 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>>
>> On 2021-03-30, H.J. Lu wrote:
>> >On Tue, Mar 30, 2021 at 12:17 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>> >>
>> >> On Tue, Mar 30, 2021 at 11:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>> >> >
>> >> > On Mon, Mar 29, 2021 at 4:24 PM Fangrui Song <maskray@google.com> wrote:
>> >> > >
>> >> > > 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).
>> >> > > ---
>> >> > > Changes in v1 -> v2:
>> >> > > * Define attribute_used_retain_section
>> >> > > Changes in v2 -> v3:
>> >> > > * Use attribute_used_retain instead attribute_used_retain_section
>> >> > > ---
>> >> > > config.h.in | 3 +++
>> >> > > configure | 23 +++++++++++++++++++++++
>> >> > > configure.ac | 16 ++++++++++++++++
>> >> > > include/libc-symbols.h | 14 ++++++++++----
>> >> > > 4 files changed, 52 insertions(+), 4 deletions(-)
>> >> > >
>> >> > > diff --git a/config.h.in b/config.h.in
>> >> > > index ca1547ae67..95af1ef229 100644
>> >> > > --- a/config.h.in
>> >> > > +++ b/config.h.in
>> >> > > @@ -187,6 +187,9 @@
>> >> > > /* Define if gcc supports attribute ifunc. */
>> >> > > #undef HAVE_GCC_IFUNC
>> >> > >
>> >> > > +/* Define if gcc supports attribute retain. */
>> >> > > +#undef HAVE_GCC_RETAIN
>> >> > > +
>> >> > > /* Define if the linker defines __ehdr_start. */
>> >> > > #undef HAVE_EHDR_START
>> >> > >
>> >> > > diff --git a/configure b/configure
>> >> > > index fcf43bf7de..6a6b8ac264 100755
>> >> > > --- a/configure
>> >> > > +++ b/configure
>> >> > > @@ -4105,6 +4105,29 @@ fi
>> >> > > $as_echo "$libc_cv_textrel_ifunc" >&6; }
>> >> > >
>> >> > >
>> >> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
>> >> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
>> >> > > +$as_echo_n "checking for gcc attribute retain support... " >&6; }
>> >> > > +if ${libc_cv_gcc_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_gcc_retain=no
>> >> > > +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
>> >> > > + 2>&5 ; then
>> >> > > + libc_cv_gcc_retain=yes
>> >> > > +fi
>> >> > > +rm -f conftest*
>> >> > > +fi
>> >> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
>> >> > > +$as_echo "$libc_cv_gcc_retain" >&6; }
>> >> > > +if test $libc_cv_gcc_retain = yes; then
>> >> > > + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
>> >> > > +
>> >> > > +fi
>> >> > > +
>> >> > > # 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; }
>> >> > > diff --git a/configure.ac b/configure.ac
>> >> > > index fce967f2c2..031b8c3fb3 100644
>> >> > > --- a/configure.ac
>> >> > > +++ b/configure.ac
>> >> > > @@ -707,6 +707,22 @@ fi
>> >> > > rm -f conftest*])
>> >> > > AC_SUBST(libc_cv_textrel_ifunc)
>> >> > >
>> >> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
>> >> > > +AC_CACHE_CHECK([for gcc attribute retain support],
>> >> > > + libc_cv_gcc_retain, [dnl
>> >> > > +cat > conftest.c <<EOF
>> >> > > +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
>> >> > > +EOF
>> >> > > +libc_cv_gcc_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_gcc_retain=yes
>> >> > > +fi
>> >> > > +rm -f conftest*])
>> >> > > +if test $libc_cv_gcc_retain = yes; then
>> >> > > + AC_DEFINE(HAVE_GCC_RETAIN)
>> >> > > +fi
>> >> > > +
>> >> > > # 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
>> >> > > diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> > > index 546fc26a7b..b311c90f0c 100644
>> >> > > --- a/include/libc-symbols.h
>> >> > > +++ b/include/libc-symbols.h
>> >> > > @@ -352,6 +352,12 @@ for linking")
>> >> > >
>> >> > > */
>> >> > >
>> >> > > +#ifdef HAVE_GCC_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. */
>> >> > > @@ -367,12 +373,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
>> >> > > --
>> >> > > 2.31.0.291.g576ba9dcdaf-goog
>> >> > >
>> >> >
>> >> > Need gc-sections tests for linkers with and without -z start-stop-gc.
>> >> >
>> >> > --
>> >> > H.J.
>> >>
>> >> I don't know how to add such a test... It needs to check flush at ext
>> >> time but I cannot find a template in libio/tst-* ...
>> >
>> >You can add a special rule to check for linker output with
>> >--print-gc-sections.
>>
>> I can come up runtime tests. ( https://github.com/MaskRay/glibc/tree/retain)
>> Runtime tests are direct.
>> (Unsure how to test --print-gc-sections with tests-static...)
>>
>>
>> diff --git a/libio/Makefile b/libio/Makefile
>> index 12ce41038f..5e0e7f00cd 100644
>> --- a/libio/Makefile
>> +++ b/libio/Makefile
>> @@ -195,6 +195,13 @@ ifeq (yes,$(build-shared))
>> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> $(objpfx)tst-bz24228-mem.out
>> endif
>> +
>> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> +tests-special += $(objpfx)tst-cleanup-start-stop-gc.out \
>> + $(objpfx)tst-cleanup-nostart-stop-gc.out
>> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
>> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
>
>1. Need to check if linker supports -z start-stop-gc.
This seems difficult to do with Makefile... Second, do we need to check it?
ld warns instead of errors for an unknown -z option, so not checking it
may be fine. (GNU ld warns even with --fatal-warnings.)
>2. Need to test with only -Wl,--gc-sections.
OK, removed -z,nostart-stop-gc
-LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
+LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections
>> endif
>>
>> include ../Rules
>> @@ -224,6 +231,20 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> endif
>>
>> +$(objpfx)tst-cleanup-start-stop-gc.out: $(objpfx)tst-cleanup-start-stop-gc
>> + $< > $@T
>> + grep hello $@T; $(evaluate-test)
>> + rm -f $@T
>
>tst-cleanup-start-stop-gc.out isn't generated. You should add a ".exp" file
>and compare the .out file against it.
Thanks for the tip. Added tst-cleanup.exp with the content "hello\n" (see the usage below).
>
>> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> +$(objpfx)tst-cleanup-nostart-stop-gc.out: $(objpfx)tst-cleanup-nostart-stop-gc
>> + $< > $@T
>> + grep hello $@T; $(evaluate-test)
>> + rm -f $@T
>> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> $(common-objpfx)libio/; \
>> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> new file mode 100644
>> index 0000000000..de8130a482
>> --- /dev/null
>> +++ b/libio/tst-cleanup.c
>> @@ -0,0 +1,14 @@
>
>Missing comments and copyright notice.
OK. I find that many tst* files don't have a copyright notice..
Added.
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +
>> +void
>> +hook (void)
>> +{
>> + puts ("hello");
>> +}
>> +
>> +int
>> +main (void)
>> +{
>> + atexit (hook);
>> +}
diff --git a/libio/Makefile b/libio/Makefile
index 12ce41038f..472a1e064c 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -195,6 +195,13 @@ ifeq (yes,$(build-shared))
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
$(objpfx)tst-bz24228-mem.out
endif
+
+tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
+tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
+tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
+ $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
+LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
+LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
endif
include ../Rules
@@ -224,6 +231,18 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.out: $(gen-locales)
endif
+$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+
+$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
$(common-objpfx)libio/; \
diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
new file mode 100644
index 0000000000..7f0a34a91e
--- /dev/null
+++ b/libio/tst-cleanup.c
@@ -0,0 +1,33 @@
+/* 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. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+hook (void)
+{
+ puts ("hello");
+}
+
+int
+main (void)
+{
+ atexit (hook);
+}
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-31 18:09 ` Fāng-ruì Sòng
@ 2021-03-31 18:57 ` H.J. Lu
2021-03-31 19:39 ` [PATCH v4] " Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-03-31 18:57 UTC (permalink / raw)
To: Fāng-ruì Sòng; +Cc: GNU C Library, Florian Weimer
On Wed, Mar 31, 2021 at 11:09 AM Fāng-ruì Sòng <maskray@google.com> wrote:
>
>
> On 2021-03-31, H.J. Lu wrote:
> >On Tue, Mar 30, 2021 at 9:34 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> >>
> >> On 2021-03-30, H.J. Lu wrote:
> >> >On Tue, Mar 30, 2021 at 12:17 PM Fāng-ruì Sòng <maskray@google.com> wrote:
> >> >>
> >> >> On Tue, Mar 30, 2021 at 11:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >> >> >
> >> >> > On Mon, Mar 29, 2021 at 4:24 PM Fangrui Song <maskray@google.com> wrote:
> >> >> > >
> >> >> > > 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).
> >> >> > > ---
> >> >> > > Changes in v1 -> v2:
> >> >> > > * Define attribute_used_retain_section
> >> >> > > Changes in v2 -> v3:
> >> >> > > * Use attribute_used_retain instead attribute_used_retain_section
> >> >> > > ---
> >> >> > > config.h.in | 3 +++
> >> >> > > configure | 23 +++++++++++++++++++++++
> >> >> > > configure.ac | 16 ++++++++++++++++
> >> >> > > include/libc-symbols.h | 14 ++++++++++----
> >> >> > > 4 files changed, 52 insertions(+), 4 deletions(-)
> >> >> > >
> >> >> > > diff --git a/config.h.in b/config.h.in
> >> >> > > index ca1547ae67..95af1ef229 100644
> >> >> > > --- a/config.h.in
> >> >> > > +++ b/config.h.in
> >> >> > > @@ -187,6 +187,9 @@
> >> >> > > /* Define if gcc supports attribute ifunc. */
> >> >> > > #undef HAVE_GCC_IFUNC
> >> >> > >
> >> >> > > +/* Define if gcc supports attribute retain. */
> >> >> > > +#undef HAVE_GCC_RETAIN
> >> >> > > +
> >> >> > > /* Define if the linker defines __ehdr_start. */
> >> >> > > #undef HAVE_EHDR_START
> >> >> > >
> >> >> > > diff --git a/configure b/configure
> >> >> > > index fcf43bf7de..6a6b8ac264 100755
> >> >> > > --- a/configure
> >> >> > > +++ b/configure
> >> >> > > @@ -4105,6 +4105,29 @@ fi
> >> >> > > $as_echo "$libc_cv_textrel_ifunc" >&6; }
> >> >> > >
> >> >> > >
> >> >> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> >> >> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> >> >> > > +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> >> >> > > +if ${libc_cv_gcc_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_gcc_retain=no
> >> >> > > +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> >> >> > > + 2>&5 ; then
> >> >> > > + libc_cv_gcc_retain=yes
> >> >> > > +fi
> >> >> > > +rm -f conftest*
> >> >> > > +fi
> >> >> > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> >> >> > > +$as_echo "$libc_cv_gcc_retain" >&6; }
> >> >> > > +if test $libc_cv_gcc_retain = yes; then
> >> >> > > + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> >> >> > > +
> >> >> > > +fi
> >> >> > > +
> >> >> > > # 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; }
> >> >> > > diff --git a/configure.ac b/configure.ac
> >> >> > > index fce967f2c2..031b8c3fb3 100644
> >> >> > > --- a/configure.ac
> >> >> > > +++ b/configure.ac
> >> >> > > @@ -707,6 +707,22 @@ fi
> >> >> > > rm -f conftest*])
> >> >> > > AC_SUBST(libc_cv_textrel_ifunc)
> >> >> > >
> >> >> > > +# Check if gcc supports attribute ifunc as it is used in libc_ifunc macro.
> >> >> > > +AC_CACHE_CHECK([for gcc attribute retain support],
> >> >> > > + libc_cv_gcc_retain, [dnl
> >> >> > > +cat > conftest.c <<EOF
> >> >> > > +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> >> >> > > +EOF
> >> >> > > +libc_cv_gcc_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_gcc_retain=yes
> >> >> > > +fi
> >> >> > > +rm -f conftest*])
> >> >> > > +if test $libc_cv_gcc_retain = yes; then
> >> >> > > + AC_DEFINE(HAVE_GCC_RETAIN)
> >> >> > > +fi
> >> >> > > +
> >> >> > > # 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
> >> >> > > diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> > > index 546fc26a7b..b311c90f0c 100644
> >> >> > > --- a/include/libc-symbols.h
> >> >> > > +++ b/include/libc-symbols.h
> >> >> > > @@ -352,6 +352,12 @@ for linking")
> >> >> > >
> >> >> > > */
> >> >> > >
> >> >> > > +#ifdef HAVE_GCC_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. */
> >> >> > > @@ -367,12 +373,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
> >> >> > > --
> >> >> > > 2.31.0.291.g576ba9dcdaf-goog
> >> >> > >
> >> >> >
> >> >> > Need gc-sections tests for linkers with and without -z start-stop-gc.
> >> >> >
> >> >> > --
> >> >> > H.J.
> >> >>
> >> >> I don't know how to add such a test... It needs to check flush at ext
> >> >> time but I cannot find a template in libio/tst-* ...
> >> >
> >> >You can add a special rule to check for linker output with
> >> >--print-gc-sections.
> >>
> >> I can come up runtime tests. ( https://github.com/MaskRay/glibc/tree/retain)
> >> Runtime tests are direct.
> >> (Unsure how to test --print-gc-sections with tests-static...)
> >>
> >>
> >> diff --git a/libio/Makefile b/libio/Makefile
> >> index 12ce41038f..5e0e7f00cd 100644
> >> --- a/libio/Makefile
> >> +++ b/libio/Makefile
> >> @@ -195,6 +195,13 @@ ifeq (yes,$(build-shared))
> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> $(objpfx)tst-bz24228-mem.out
> >> endif
> >> +
> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc.out \
> >> + $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> >
> >1. Need to check if linker supports -z start-stop-gc.
>
> This seems difficult to do with Makefile... Second, do we need to check it?
> ld warns instead of errors for an unknown -z option, so not checking it
> may be fine. (GNU ld warns even with --fatal-warnings.)
Please use LIBC_LINKER_FEATURE and LIBC_CONFIG_VAR to
detect and check linker features.
> >2. Need to test with only -Wl,--gc-sections.
>
> OK, removed -z,nostart-stop-gc
We need all 3 tests with -Wl,--gc-sections.
> -LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections
>
> >> endif
> >>
> >> include ../Rules
> >> @@ -224,6 +231,20 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> endif
> >>
> >> +$(objpfx)tst-cleanup-start-stop-gc.out: $(objpfx)tst-cleanup-start-stop-gc
> >> + $< > $@T
> >> + grep hello $@T; $(evaluate-test)
> >> + rm -f $@T
> >
> >tst-cleanup-start-stop-gc.out isn't generated. You should add a ".exp" file
> >and compare the .out file against it.
>
> Thanks for the tip. Added tst-cleanup.exp with the content "hello\n" (see the usage below).
> >
> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +
> >> +$(objpfx)tst-cleanup-nostart-stop-gc.out: $(objpfx)tst-cleanup-nostart-stop-gc
> >> + $< > $@T
> >> + grep hello $@T; $(evaluate-test)
> >> + rm -f $@T
> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +
> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> $(common-objpfx)libio/; \
> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> >> new file mode 100644
> >> index 0000000000..de8130a482
> >> --- /dev/null
> >> +++ b/libio/tst-cleanup.c
> >> @@ -0,0 +1,14 @@
> >
> >Missing comments and copyright notice.
>
> OK. I find that many tst* files don't have a copyright notice..
> Added.
>
> >> +#include <stdio.h>
> >> +#include <stdlib.h>
> >> +
> >> +void
> >> +hook (void)
> >> +{
> >> + puts ("hello");
> >> +}
> >> +
> >> +int
> >> +main (void)
> >> +{
> >> + atexit (hook);
> >> +}
>
>
> diff --git a/libio/Makefile b/libio/Makefile
> index 12ce41038f..472a1e064c 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -195,6 +195,13 @@ ifeq (yes,$(build-shared))
> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> $(objpfx)tst-bz24228-mem.out
> endif
> +
> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> endif
>
> include ../Rules
> @@ -224,6 +231,18 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> endif
>
> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> $(common-objpfx)libio/; \
> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> new file mode 100644
> index 0000000000..7f0a34a91e
> --- /dev/null
> +++ b/libio/tst-cleanup.c
> @@ -0,0 +1,33 @@
> +/* 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. */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +void
> +hook (void)
> +{
> + puts ("hello");
> +}
> +
> +int
> +main (void)
> +{
> + atexit (hook);
> +}
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v4] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-31 18:57 ` H.J. Lu
@ 2021-03-31 19:39 ` Fangrui Song
2021-03-31 23:38 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-03-31 19:39 UTC (permalink / raw)
To: libc-alpha, Florian Weimer, H . J . Lu ; +Cc: Fangrui Song
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).
---
Changes in v1 -> v2:
* Define attribute_used_retain_section
Changes in v2 -> v3:
* Use attribute_used_retain instead attribute_used_retain_section
Changes in v3 -> v4:
* Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
---
config.h.in | 3 +++
configure | 58 ++++++++++++++++++++++++++++++++++++++++++
configure.ac | 20 +++++++++++++++
include/libc-symbols.h | 14 +++++++---
libio/Makefile | 32 +++++++++++++++++++++++
libio/tst-cleanup.c | 33 ++++++++++++++++++++++++
libio/tst-cleanup.exp | 1 +
7 files changed, 157 insertions(+), 4 deletions(-)
create mode 100644 libio/tst-cleanup.c
create mode 100644 libio/tst-cleanup.exp
diff --git a/config.h.in b/config.h.in
index ca1547ae67..95af1ef229 100644
--- a/config.h.in
+++ b/config.h.in
@@ -187,6 +187,9 @@
/* Define if gcc supports attribute ifunc. */
#undef HAVE_GCC_IFUNC
+/* Define if gcc supports attribute retain. */
+#undef HAVE_GCC_RETAIN
+
/* Define if the linker defines __ehdr_start. */
#undef HAVE_EHDR_START
diff --git a/configure b/configure
index fcf43bf7de..fa86348342 100755
--- a/configure
+++ b/configure
@@ -626,6 +626,7 @@ fno_unit_at_a_time
libc_cv_has_glob_dat
libc_cv_hashstyle
libc_cv_fpie
+libc_cv_z_start_stop_gc
libc_cv_z_execstack
libc_cv_z_combreloc
ASFLAGS_config
@@ -4105,6 +4106,29 @@ fi
$as_echo "$libc_cv_textrel_ifunc" >&6; }
+# Check if gcc supports attribute retain as it is used in attribute_used_retain macro.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
+$as_echo_n "checking for gcc attribute retain support... " >&6; }
+if ${libc_cv_gcc_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_gcc_retain=no
+if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
+ 2>&5 ; then
+ libc_cv_gcc_retain=yes
+fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
+$as_echo "$libc_cv_gcc_retain" >&6; }
+if test $libc_cv_gcc_retain = yes; then
+ $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
+
+fi
+
# 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; }
@@ -5871,6 +5895,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
diff --git a/configure.ac b/configure.ac
index fce967f2c2..4e2907da92 100644
--- a/configure.ac
+++ b/configure.ac
@@ -707,6 +707,22 @@ fi
rm -f conftest*])
AC_SUBST(libc_cv_textrel_ifunc)
+# Check if gcc supports attribute retain as it is used in attribute_used_retain macro.
+AC_CACHE_CHECK([for gcc attribute retain support],
+ libc_cv_gcc_retain, [dnl
+cat > conftest.c <<EOF
+static int var __attribute__ ((used, retain, section ("__libc_atexit")));
+EOF
+libc_cv_gcc_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_gcc_retain=yes
+fi
+rm -f conftest*])
+if test $libc_cv_gcc_retain = yes; then
+ AC_DEFINE(HAVE_GCC_RETAIN)
+fi
+
# 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 +1333,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],
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index 546fc26a7b..b311c90f0c 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -352,6 +352,12 @@ for linking")
\f
*/
+#ifdef HAVE_GCC_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. */
@@ -367,12 +373,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
diff --git a/libio/Makefile b/libio/Makefile
index 12ce41038f..439d22e057 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
$(objpfx)tst-bz24228-mem.out
endif
+
+tests += tst-cleanup-default
+tests-static += tst-cleanup-default
+tests-special += $(objpfx)tst-cleanup-default-cmp.out
+LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
+
+ifeq ($(have-z-start-stop-gc),yes)
+tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
+tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
+tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
+ $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
+LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
+LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
+endif
endif
include ../Rules
@@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.out: $(gen-locales)
endif
+$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-default.o: tst-cleanup.c
+ $(compile.c) -o $@
+
+$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+
+$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
$(common-objpfx)libio/; \
diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
new file mode 100644
index 0000000000..7f0a34a91e
--- /dev/null
+++ b/libio/tst-cleanup.c
@@ -0,0 +1,33 @@
+/* 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. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+hook (void)
+{
+ puts ("hello");
+}
+
+int
+main (void)
+{
+ atexit (hook);
+}
diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
new file mode 100644
index 0000000000..ce01362503
--- /dev/null
+++ b/libio/tst-cleanup.exp
@@ -0,0 +1 @@
+hello
--
2.31.0.291.g576ba9dcdaf-goog
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v4] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-31 19:39 ` [PATCH v4] " Fangrui Song
@ 2021-03-31 23:38 ` H.J. Lu
2021-04-01 0:02 ` Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-03-31 23:38 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Wed, Mar 31, 2021 at 12:39 PM Fangrui Song <maskray@google.com> wrote:
>
> 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).
> ---
> Changes in v1 -> v2:
> * Define attribute_used_retain_section
> Changes in v2 -> v3:
> * Use attribute_used_retain instead attribute_used_retain_section
> Changes in v3 -> v4:
> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> ---
> config.h.in | 3 +++
> configure | 58 ++++++++++++++++++++++++++++++++++++++++++
> configure.ac | 20 +++++++++++++++
> include/libc-symbols.h | 14 +++++++---
> libio/Makefile | 32 +++++++++++++++++++++++
> libio/tst-cleanup.c | 33 ++++++++++++++++++++++++
> libio/tst-cleanup.exp | 1 +
> 7 files changed, 157 insertions(+), 4 deletions(-)
> create mode 100644 libio/tst-cleanup.c
> create mode 100644 libio/tst-cleanup.exp
>
> diff --git a/config.h.in b/config.h.in
> index ca1547ae67..95af1ef229 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -187,6 +187,9 @@
> /* Define if gcc supports attribute ifunc. */
> #undef HAVE_GCC_IFUNC
>
> +/* Define if gcc supports attribute retain. */
> +#undef HAVE_GCC_RETAIN
> +
> /* Define if the linker defines __ehdr_start. */
> #undef HAVE_EHDR_START
>
> diff --git a/configure b/configure
> index fcf43bf7de..fa86348342 100755
> --- a/configure
> +++ b/configure
> @@ -626,6 +626,7 @@ fno_unit_at_a_time
> libc_cv_has_glob_dat
> libc_cv_hashstyle
> libc_cv_fpie
> +libc_cv_z_start_stop_gc
> libc_cv_z_execstack
> libc_cv_z_combreloc
> ASFLAGS_config
> @@ -4105,6 +4106,29 @@ fi
> $as_echo "$libc_cv_textrel_ifunc" >&6; }
>
>
> +# Check if gcc supports attribute retain as it is used in attribute_used_retain macro.
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> +if ${libc_cv_gcc_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_gcc_retain=no
> +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> + 2>&5 ; then
> + libc_cv_gcc_retain=yes
> +fi
> +rm -f conftest*
> +fi
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> +$as_echo "$libc_cv_gcc_retain" >&6; }
> +if test $libc_cv_gcc_retain = yes; then
> + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> +
> +fi
> +
> # 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; }
> @@ -5871,6 +5895,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
> diff --git a/configure.ac b/configure.ac
> index fce967f2c2..4e2907da92 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -707,6 +707,22 @@ fi
> rm -f conftest*])
> AC_SUBST(libc_cv_textrel_ifunc)
>
> +# Check if gcc supports attribute retain as it is used in attribute_used_retain macro.
> +AC_CACHE_CHECK([for gcc attribute retain support],
> + libc_cv_gcc_retain, [dnl
> +cat > conftest.c <<EOF
> +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> +EOF
> +libc_cv_gcc_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_gcc_retain=yes
> +fi
> +rm -f conftest*])
> +if test $libc_cv_gcc_retain = yes; then
> + AC_DEFINE(HAVE_GCC_RETAIN)
> +fi
> +
> # 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 +1333,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],
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index 546fc26a7b..b311c90f0c 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -352,6 +352,12 @@ for linking")
>
> */
>
> +#ifdef HAVE_GCC_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. */
> @@ -367,12 +373,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
> diff --git a/libio/Makefile b/libio/Makefile
> index 12ce41038f..439d22e057 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> $(objpfx)tst-bz24228-mem.out
> endif
> +
> +tests += tst-cleanup-default
> +tests-static += tst-cleanup-default
> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> +
> +ifeq ($(have-z-start-stop-gc),yes)
> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
Won't this test fail if linker supports -z start-stop-gc and GCC doesn't support
retain attribute?
> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> +endif
> endif
>
> include ../Rules
> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> endif
>
> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> $(common-objpfx)libio/; \
> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> new file mode 100644
> index 0000000000..7f0a34a91e
> --- /dev/null
> +++ b/libio/tst-cleanup.c
> @@ -0,0 +1,33 @@
> +/* 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. */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +void
> +hook (void)
> +{
> + puts ("hello");
> +}
> +
> +int
> +main (void)
> +{
> + atexit (hook);
> +}
> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> new file mode 100644
> index 0000000000..ce01362503
> --- /dev/null
> +++ b/libio/tst-cleanup.exp
> @@ -0,0 +1 @@
> +hello
> --
> 2.31.0.291.g576ba9dcdaf-goog
>
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v4] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-03-31 23:38 ` H.J. Lu
@ 2021-04-01 0:02 ` Fangrui Song
2021-04-01 1:00 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-04-01 0:02 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-03-31, H.J. Lu wrote:
>On Wed, Mar 31, 2021 at 12:39 PM Fangrui Song <maskray@google.com> wrote:
>>
>> 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).
>> ---
>> Changes in v1 -> v2:
>> * Define attribute_used_retain_section
>> Changes in v2 -> v3:
>> * Use attribute_used_retain instead attribute_used_retain_section
>> Changes in v3 -> v4:
>> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
>> ---
>> config.h.in | 3 +++
>> configure | 58 ++++++++++++++++++++++++++++++++++++++++++
>> configure.ac | 20 +++++++++++++++
>> include/libc-symbols.h | 14 +++++++---
>> libio/Makefile | 32 +++++++++++++++++++++++
>> libio/tst-cleanup.c | 33 ++++++++++++++++++++++++
>> libio/tst-cleanup.exp | 1 +
>> 7 files changed, 157 insertions(+), 4 deletions(-)
>> create mode 100644 libio/tst-cleanup.c
>> create mode 100644 libio/tst-cleanup.exp
>>
>> diff --git a/config.h.in b/config.h.in
>> index ca1547ae67..95af1ef229 100644
>> --- a/config.h.in
>> +++ b/config.h.in
>> @@ -187,6 +187,9 @@
>> /* Define if gcc supports attribute ifunc. */
>> #undef HAVE_GCC_IFUNC
>>
>> +/* Define if gcc supports attribute retain. */
>> +#undef HAVE_GCC_RETAIN
>> +
>> /* Define if the linker defines __ehdr_start. */
>> #undef HAVE_EHDR_START
>>
>> diff --git a/configure b/configure
>> index fcf43bf7de..fa86348342 100755
>> --- a/configure
>> +++ b/configure
>> @@ -626,6 +626,7 @@ fno_unit_at_a_time
>> libc_cv_has_glob_dat
>> libc_cv_hashstyle
>> libc_cv_fpie
>> +libc_cv_z_start_stop_gc
>> libc_cv_z_execstack
>> libc_cv_z_combreloc
>> ASFLAGS_config
>> @@ -4105,6 +4106,29 @@ fi
>> $as_echo "$libc_cv_textrel_ifunc" >&6; }
>>
>>
>> +# Check if gcc supports attribute retain as it is used in attribute_used_retain macro.
>> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
>> +$as_echo_n "checking for gcc attribute retain support... " >&6; }
>> +if ${libc_cv_gcc_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_gcc_retain=no
>> +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
>> + 2>&5 ; then
>> + libc_cv_gcc_retain=yes
>> +fi
>> +rm -f conftest*
>> +fi
>> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
>> +$as_echo "$libc_cv_gcc_retain" >&6; }
>> +if test $libc_cv_gcc_retain = yes; then
>> + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
>> +
>> +fi
>> +
>> # 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; }
>> @@ -5871,6 +5895,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
>> diff --git a/configure.ac b/configure.ac
>> index fce967f2c2..4e2907da92 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -707,6 +707,22 @@ fi
>> rm -f conftest*])
>> AC_SUBST(libc_cv_textrel_ifunc)
>>
>> +# Check if gcc supports attribute retain as it is used in attribute_used_retain macro.
>> +AC_CACHE_CHECK([for gcc attribute retain support],
>> + libc_cv_gcc_retain, [dnl
>> +cat > conftest.c <<EOF
>> +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
>> +EOF
>> +libc_cv_gcc_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_gcc_retain=yes
>> +fi
>> +rm -f conftest*])
>> +if test $libc_cv_gcc_retain = yes; then
>> + AC_DEFINE(HAVE_GCC_RETAIN)
>> +fi
>> +
>> # 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 +1333,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],
>> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> index 546fc26a7b..b311c90f0c 100644
>> --- a/include/libc-symbols.h
>> +++ b/include/libc-symbols.h
>> @@ -352,6 +352,12 @@ for linking")
>>
>> */
>>
>> +#ifdef HAVE_GCC_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. */
>> @@ -367,12 +373,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
>> diff --git a/libio/Makefile b/libio/Makefile
>> index 12ce41038f..439d22e057 100644
>> --- a/libio/Makefile
>> +++ b/libio/Makefile
>> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
>> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> $(objpfx)tst-bz24228-mem.out
>> endif
>> +
>> +tests += tst-cleanup-default
>> +tests-static += tst-cleanup-default
>> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
>> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
>> +
>> +ifeq ($(have-z-start-stop-gc),yes)
>> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
>> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
>> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
>
>Won't this test fail if linker supports -z start-stop-gc and GCC doesn't support
>retain attribute?
Yes, but that doesn't happen in practice. If ld supports -z start-stop-gc,
the GNU as should be new and the GCC should support 'retain'.
But perhaps it is good to prevent the issue, I can change
+ifeq ($(have-z-start-stop-gc),yes)
to
+ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
and add a LIBC_CONFIG_VAR in configure.ac.
>> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
>> +endif
>> endif
>>
>> include ../Rules
>> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> endif
>>
>> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> $(common-objpfx)libio/; \
>> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> new file mode 100644
>> index 0000000000..7f0a34a91e
>> --- /dev/null
>> +++ b/libio/tst-cleanup.c
>> @@ -0,0 +1,33 @@
>> +/* 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. */
>> +
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +
>> +void
>> +hook (void)
>> +{
>> + puts ("hello");
>> +}
>> +
>> +int
>> +main (void)
>> +{
>> + atexit (hook);
>> +}
>> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> new file mode 100644
>> index 0000000000..ce01362503
>> --- /dev/null
>> +++ b/libio/tst-cleanup.exp
>> @@ -0,0 +1 @@
>> +hello
>> --
>> 2.31.0.291.g576ba9dcdaf-goog
>>
>
>
>--
>H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v4] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-01 0:02 ` Fangrui Song
@ 2021-04-01 1:00 ` H.J. Lu
2021-04-01 1:06 ` [PATCH v5] " Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-04-01 1:00 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Wed, Mar 31, 2021 at 5:02 PM Fangrui Song <maskray@google.com> wrote:
>
> On 2021-03-31, H.J. Lu wrote:
> >On Wed, Mar 31, 2021 at 12:39 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> 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).
> >> ---
> >> Changes in v1 -> v2:
> >> * Define attribute_used_retain_section
> >> Changes in v2 -> v3:
> >> * Use attribute_used_retain instead attribute_used_retain_section
> >> Changes in v3 -> v4:
> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> >> ---
> >> config.h.in | 3 +++
> >> configure | 58 ++++++++++++++++++++++++++++++++++++++++++
> >> configure.ac | 20 +++++++++++++++
> >> include/libc-symbols.h | 14 +++++++---
> >> libio/Makefile | 32 +++++++++++++++++++++++
> >> libio/tst-cleanup.c | 33 ++++++++++++++++++++++++
> >> libio/tst-cleanup.exp | 1 +
> >> 7 files changed, 157 insertions(+), 4 deletions(-)
> >> create mode 100644 libio/tst-cleanup.c
> >> create mode 100644 libio/tst-cleanup.exp
> >>
> >> diff --git a/config.h.in b/config.h.in
> >> index ca1547ae67..95af1ef229 100644
> >> --- a/config.h.in
> >> +++ b/config.h.in
> >> @@ -187,6 +187,9 @@
> >> /* Define if gcc supports attribute ifunc. */
> >> #undef HAVE_GCC_IFUNC
> >>
> >> +/* Define if gcc supports attribute retain. */
> >> +#undef HAVE_GCC_RETAIN
> >> +
> >> /* Define if the linker defines __ehdr_start. */
> >> #undef HAVE_EHDR_START
> >>
> >> diff --git a/configure b/configure
> >> index fcf43bf7de..fa86348342 100755
> >> --- a/configure
> >> +++ b/configure
> >> @@ -626,6 +626,7 @@ fno_unit_at_a_time
> >> libc_cv_has_glob_dat
> >> libc_cv_hashstyle
> >> libc_cv_fpie
> >> +libc_cv_z_start_stop_gc
> >> libc_cv_z_execstack
> >> libc_cv_z_combreloc
> >> ASFLAGS_config
> >> @@ -4105,6 +4106,29 @@ fi
> >> $as_echo "$libc_cv_textrel_ifunc" >&6; }
> >>
> >>
> >> +# Check if gcc supports attribute retain as it is used in attribute_used_retain macro.
> >> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc attribute retain support" >&5
> >> +$as_echo_n "checking for gcc attribute retain support... " >&6; }
> >> +if ${libc_cv_gcc_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_gcc_retain=no
> >> +if ${CC-cc} -Werror -c conftest.c -o /dev/null 1>&5 \
> >> + 2>&5 ; then
> >> + libc_cv_gcc_retain=yes
> >> +fi
> >> +rm -f conftest*
> >> +fi
> >> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_gcc_retain" >&5
> >> +$as_echo "$libc_cv_gcc_retain" >&6; }
> >> +if test $libc_cv_gcc_retain = yes; then
> >> + $as_echo "#define HAVE_GCC_RETAIN 1" >>confdefs.h
> >> +
> >> +fi
> >> +
> >> # 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; }
> >> @@ -5871,6 +5895,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
> >> diff --git a/configure.ac b/configure.ac
> >> index fce967f2c2..4e2907da92 100644
> >> --- a/configure.ac
> >> +++ b/configure.ac
> >> @@ -707,6 +707,22 @@ fi
> >> rm -f conftest*])
> >> AC_SUBST(libc_cv_textrel_ifunc)
> >>
> >> +# Check if gcc supports attribute retain as it is used in attribute_used_retain macro.
> >> +AC_CACHE_CHECK([for gcc attribute retain support],
> >> + libc_cv_gcc_retain, [dnl
> >> +cat > conftest.c <<EOF
> >> +static int var __attribute__ ((used, retain, section ("__libc_atexit")));
> >> +EOF
> >> +libc_cv_gcc_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_gcc_retain=yes
> >> +fi
> >> +rm -f conftest*])
> >> +if test $libc_cv_gcc_retain = yes; then
> >> + AC_DEFINE(HAVE_GCC_RETAIN)
> >> +fi
> >> +
> >> # 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 +1333,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],
> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> index 546fc26a7b..b311c90f0c 100644
> >> --- a/include/libc-symbols.h
> >> +++ b/include/libc-symbols.h
> >> @@ -352,6 +352,12 @@ for linking")
> >>
> >> */
> >>
> >> +#ifdef HAVE_GCC_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. */
> >> @@ -367,12 +373,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
> >> diff --git a/libio/Makefile b/libio/Makefile
> >> index 12ce41038f..439d22e057 100644
> >> --- a/libio/Makefile
> >> +++ b/libio/Makefile
> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> $(objpfx)tst-bz24228-mem.out
> >> endif
> >> +
> >> +tests += tst-cleanup-default
> >> +tests-static += tst-cleanup-default
> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> >> +
> >> +ifeq ($(have-z-start-stop-gc),yes)
> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >
> >Won't this test fail if linker supports -z start-stop-gc and GCC doesn't support
> >retain attribute?
>
> Yes, but that doesn't happen in practice. If ld supports -z start-stop-gc,
> the GNU as should be new and the GCC should support 'retain'.
I am using GCC 10 and binutils 2.37.
> But perhaps it is good to prevent the issue, I can change
>
> +ifeq ($(have-z-start-stop-gc),yes)
>
> to
>
> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
>
> and add a LIBC_CONFIG_VAR in configure.ac.
>
Yes, please.
Thanks.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-01 1:00 ` H.J. Lu
@ 2021-04-01 1:06 ` Fangrui Song
2021-04-01 12:52 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-04-01 1:06 UTC (permalink / raw)
To: libc-alpha, Florian Weimer, H . J . Lu ; +Cc: Fangrui Song
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).
---
Changes in v1 -> v2:
* Define attribute_used_retain_section
Changes in v2 -> v3:
* Use attribute_used_retain instead attribute_used_retain_section
Changes in v3 -> v4:
* Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
Changes in v4 -> v5:
* Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
* Rename *gcc_retain* to *gnu_retain*
---
config.h.in | 3 +++
configure | 59 ++++++++++++++++++++++++++++++++++++++++++
configure.ac | 21 +++++++++++++++
include/libc-symbols.h | 14 +++++++---
libio/Makefile | 32 +++++++++++++++++++++++
libio/tst-cleanup.c | 33 +++++++++++++++++++++++
libio/tst-cleanup.exp | 1 +
7 files changed, 159 insertions(+), 4 deletions(-)
create mode 100644 libio/tst-cleanup.c
create mode 100644 libio/tst-cleanup.exp
diff --git a/config.h.in b/config.h.in
index ca1547ae67..96a08c7757 100644
--- a/config.h.in
+++ b/config.h.in
@@ -187,6 +187,9 @@
/* Define if gcc supports attribute ifunc. */
#undef HAVE_GCC_IFUNC
+/* Define if CC supports attribute retain. */
+#undef HAVE_GNU_RETAIN
+
/* Define if the linker defines __ehdr_start. */
#undef HAVE_EHDR_START
diff --git a/configure b/configure
index fcf43bf7de..e64b7f8efe 100755
--- a/configure
+++ b/configure
@@ -4105,6 +4105,31 @@ fi
$as_echo "$libc_cv_textrel_ifunc" >&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; }
@@ -5871,6 +5896,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
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],
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index 546fc26a7b..127ea656c2 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -352,6 +352,12 @@ for linking")
\f
*/
+#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. */
@@ -367,12 +373,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
diff --git a/libio/Makefile b/libio/Makefile
index 12ce41038f..c9c232ebc2 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
$(objpfx)tst-bz24228-mem.out
endif
+
+tests += tst-cleanup-default
+tests-static += tst-cleanup-default
+tests-special += $(objpfx)tst-cleanup-default-cmp.out
+LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
+
+ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
+tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
+tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
+tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
+ $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
+LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
+LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
+endif
endif
include ../Rules
@@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.out: $(gen-locales)
endif
+$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-default.o: tst-cleanup.c
+ $(compile.c) -o $@
+
+$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+
+$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
$(common-objpfx)libio/; \
diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
new file mode 100644
index 0000000000..7f0a34a91e
--- /dev/null
+++ b/libio/tst-cleanup.c
@@ -0,0 +1,33 @@
+/* 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. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+hook (void)
+{
+ puts ("hello");
+}
+
+int
+main (void)
+{
+ atexit (hook);
+}
diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
new file mode 100644
index 0000000000..ce01362503
--- /dev/null
+++ b/libio/tst-cleanup.exp
@@ -0,0 +1 @@
+hello
--
2.31.0.291.g576ba9dcdaf-goog
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-01 1:06 ` [PATCH v5] " Fangrui Song
@ 2021-04-01 12:52 ` H.J. Lu
2021-04-02 3:23 ` Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-04-01 12:52 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
>
> 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).
> ---
> Changes in v1 -> v2:
> * Define attribute_used_retain_section
> Changes in v2 -> v3:
> * Use attribute_used_retain instead attribute_used_retain_section
> Changes in v3 -> v4:
> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> Changes in v4 -> v5:
> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> * Rename *gcc_retain* to *gnu_retain*
> ---
> config.h.in | 3 +++
> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> configure.ac | 21 +++++++++++++++
> include/libc-symbols.h | 14 +++++++---
> libio/Makefile | 32 +++++++++++++++++++++++
> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> libio/tst-cleanup.exp | 1 +
> 7 files changed, 159 insertions(+), 4 deletions(-)
> create mode 100644 libio/tst-cleanup.c
> create mode 100644 libio/tst-cleanup.exp
>
> diff --git a/config.h.in b/config.h.in
> index ca1547ae67..96a08c7757 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -187,6 +187,9 @@
> /* Define if gcc supports attribute ifunc. */
> #undef HAVE_GCC_IFUNC
>
> +/* Define if CC supports attribute retain. */
> +#undef HAVE_GNU_RETAIN
> +
> /* Define if the linker defines __ehdr_start. */
> #undef HAVE_EHDR_START
>
> diff --git a/configure b/configure
> index fcf43bf7de..e64b7f8efe 100755
> --- a/configure
> +++ b/configure
> @@ -4105,6 +4105,31 @@ fi
> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> @@ -5871,6 +5896,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
> 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],
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index 546fc26a7b..127ea656c2 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -352,6 +352,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. */
> @@ -367,12 +373,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
> diff --git a/libio/Makefile b/libio/Makefile
> index 12ce41038f..c9c232ebc2 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> $(objpfx)tst-bz24228-mem.out
> endif
> +
> +tests += tst-cleanup-default
> +tests-static += tst-cleanup-default
> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> +
> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
Same here.
> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> +endif
> endif
>
> include ../Rules
> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> endif
>
> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
>
> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> $(common-objpfx)libio/; \
> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> new file mode 100644
> index 0000000000..7f0a34a91e
> --- /dev/null
> +++ b/libio/tst-cleanup.c
> @@ -0,0 +1,33 @@
Please add a comment saying that test --gc-sections.
> +/* 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. */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +void
> +hook (void)
> +{
> + puts ("hello");
> +}
> +
> +int
> +main (void)
> +{
> + atexit (hook);
> +}
> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> new file mode 100644
> index 0000000000..ce01362503
> --- /dev/null
> +++ b/libio/tst-cleanup.exp
> @@ -0,0 +1 @@
> +hello
> --
> 2.31.0.291.g576ba9dcdaf-goog
>
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-01 12:52 ` H.J. Lu
@ 2021-04-02 3:23 ` Fangrui Song
2021-04-02 14:14 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-04-02 3:23 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-04-01, H.J. Lu wrote:
>On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
>>
>> 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).
>> ---
>> Changes in v1 -> v2:
>> * Define attribute_used_retain_section
>> Changes in v2 -> v3:
>> * Use attribute_used_retain instead attribute_used_retain_section
>> Changes in v3 -> v4:
>> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
>> Changes in v4 -> v5:
>> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
>> * Rename *gcc_retain* to *gnu_retain*
>> ---
>> config.h.in | 3 +++
>> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
>> configure.ac | 21 +++++++++++++++
>> include/libc-symbols.h | 14 +++++++---
>> libio/Makefile | 32 +++++++++++++++++++++++
>> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
>> libio/tst-cleanup.exp | 1 +
>> 7 files changed, 159 insertions(+), 4 deletions(-)
>> create mode 100644 libio/tst-cleanup.c
>> create mode 100644 libio/tst-cleanup.exp
>>
>> diff --git a/config.h.in b/config.h.in
>> index ca1547ae67..96a08c7757 100644
>> --- a/config.h.in
>> +++ b/config.h.in
>> @@ -187,6 +187,9 @@
>> /* Define if gcc supports attribute ifunc. */
>> #undef HAVE_GCC_IFUNC
>>
>> +/* Define if CC supports attribute retain. */
>> +#undef HAVE_GNU_RETAIN
>> +
>> /* Define if the linker defines __ehdr_start. */
>> #undef HAVE_EHDR_START
>>
>> diff --git a/configure b/configure
>> index fcf43bf7de..e64b7f8efe 100755
>> --- a/configure
>> +++ b/configure
>> @@ -4105,6 +4105,31 @@ fi
>> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> @@ -5871,6 +5896,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
>> 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],
>> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> index 546fc26a7b..127ea656c2 100644
>> --- a/include/libc-symbols.h
>> +++ b/include/libc-symbols.h
>> @@ -352,6 +352,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. */
>> @@ -367,12 +373,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
>> diff --git a/libio/Makefile b/libio/Makefile
>> index 12ce41038f..c9c232ebc2 100644
>> --- a/libio/Makefile
>> +++ b/libio/Makefile
>> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
>> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> $(objpfx)tst-bz24228-mem.out
>> endif
>> +
>> +tests += tst-cleanup-default
>> +tests-static += tst-cleanup-default
>> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
>
>Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
Added.
>> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
>> +
>> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
>> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
>> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
>
>Same here.
Added.
>> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
>> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
>> +endif
>> endif
>>
>> include ../Rules
>> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> endif
>>
>> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>>
>> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> $(common-objpfx)libio/; \
>> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> new file mode 100644
>> index 0000000000..7f0a34a91e
>> --- /dev/null
>> +++ b/libio/tst-cleanup.c
>> @@ -0,0 +1,33 @@
>
>Please add a comment saying that test --gc-sections.
OK, added.
>> +/* 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. */
>> +
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +
>> +void
>> +hook (void)
>> +{
>> + puts ("hello");
>> +}
>> +
>> +int
>> +main (void)
>> +{
>> + atexit (hook);
>> +}
>> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> new file mode 100644
>> index 0000000000..ce01362503
>> --- /dev/null
>> +++ b/libio/tst-cleanup.exp
>> @@ -0,0 +1 @@
>> +hello
>> --
>> 2.31.0.291.g576ba9dcdaf-goog
>>
>
diff --git a/config.h.in b/config.h.in
index ca1547ae67..96a08c7757 100644
--- a/config.h.in
+++ b/config.h.in
@@ -187,6 +187,9 @@
/* Define if gcc supports attribute ifunc. */
#undef HAVE_GCC_IFUNC
+/* Define if CC supports attribute retain. */
+#undef HAVE_GNU_RETAIN
+
/* Define if the linker defines __ehdr_start. */
#undef HAVE_EHDR_START
diff --git a/configure b/configure
index fcf43bf7de..e64b7f8efe 100755
--- a/configure
+++ b/configure
@@ -4105,6 +4105,31 @@ fi
$as_echo "$libc_cv_textrel_ifunc" >&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; }
@@ -5871,6 +5896,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
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],
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index 546fc26a7b..127ea656c2 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -352,6 +352,12 @@ for linking")
\f
*/
+#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. */
@@ -367,12 +373,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
diff --git a/libio/Makefile b/libio/Makefile
index 12ce41038f..ad0d53bb49 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
$(objpfx)tst-bz24228-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
@@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.out: $(gen-locales)
endif
+$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-default.o: tst-cleanup.c
+ $(compile.c) -o $@
+$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
+ $(compile.c) -o $@
+
+$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
+ $(compile.c) -o $@
+
+$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-nostart-stop-gc-static.o: tst-cleanup.c
+ $(compile.c) -o $@
+
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
$(common-objpfx)libio/; \
diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
new file mode 100644
index 0000000000..837feac164
--- /dev/null
+++ b/libio/tst-cleanup.c
@@ -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);
+}
diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
new file mode 100644
index 0000000000..ce01362503
--- /dev/null
+++ b/libio/tst-cleanup.exp
@@ -0,0 +1 @@
+hello
--
2.31.0.208.g409f899ff0-goog
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-02 3:23 ` Fangrui Song
@ 2021-04-02 14:14 ` H.J. Lu
2021-04-02 17:09 ` Fangrui Song
2021-04-03 18:02 ` Fangrui Song
0 siblings, 2 replies; 40+ messages in thread
From: H.J. Lu @ 2021-04-02 14:14 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
>
> On 2021-04-01, H.J. Lu wrote:
> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> 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).
> >> ---
> >> Changes in v1 -> v2:
> >> * Define attribute_used_retain_section
> >> Changes in v2 -> v3:
> >> * Use attribute_used_retain instead attribute_used_retain_section
> >> Changes in v3 -> v4:
> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> >> Changes in v4 -> v5:
> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> >> * Rename *gcc_retain* to *gnu_retain*
> >> ---
> >> config.h.in | 3 +++
> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> >> configure.ac | 21 +++++++++++++++
> >> include/libc-symbols.h | 14 +++++++---
> >> libio/Makefile | 32 +++++++++++++++++++++++
> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> >> libio/tst-cleanup.exp | 1 +
> >> 7 files changed, 159 insertions(+), 4 deletions(-)
> >> create mode 100644 libio/tst-cleanup.c
> >> create mode 100644 libio/tst-cleanup.exp
> >>
> >> diff --git a/config.h.in b/config.h.in
> >> index ca1547ae67..96a08c7757 100644
> >> --- a/config.h.in
> >> +++ b/config.h.in
> >> @@ -187,6 +187,9 @@
> >> /* Define if gcc supports attribute ifunc. */
> >> #undef HAVE_GCC_IFUNC
> >>
> >> +/* Define if CC supports attribute retain. */
> >> +#undef HAVE_GNU_RETAIN
> >> +
> >> /* Define if the linker defines __ehdr_start. */
> >> #undef HAVE_EHDR_START
> >>
> >> diff --git a/configure b/configure
> >> index fcf43bf7de..e64b7f8efe 100755
> >> --- a/configure
> >> +++ b/configure
> >> @@ -4105,6 +4105,31 @@ fi
> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> @@ -5871,6 +5896,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
> >> 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],
> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> index 546fc26a7b..127ea656c2 100644
> >> --- a/include/libc-symbols.h
> >> +++ b/include/libc-symbols.h
> >> @@ -352,6 +352,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. */
> >> @@ -367,12 +373,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
> >> diff --git a/libio/Makefile b/libio/Makefile
> >> index 12ce41038f..c9c232ebc2 100644
> >> --- a/libio/Makefile
> >> +++ b/libio/Makefile
> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> $(objpfx)tst-bz24228-mem.out
> >> endif
> >> +
> >> +tests += tst-cleanup-default
> >> +tests-static += tst-cleanup-default
> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> >
> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
>
> Added.
>
> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> >> +
> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> >
> >Same here.
>
> Added.
>
> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> >> +endif
> >> endif
> >>
> >> include ../Rules
> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> endif
> >>
> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +
> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +
> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >>
> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> $(common-objpfx)libio/; \
> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> >> new file mode 100644
> >> index 0000000000..7f0a34a91e
> >> --- /dev/null
> >> +++ b/libio/tst-cleanup.c
> >> @@ -0,0 +1,33 @@
> >
> >Please add a comment saying that test --gc-sections.
>
> OK, added.
>
> >> +/* 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. */
> >> +
> >> +#include <stdio.h>
> >> +#include <stdlib.h>
> >> +
> >> +void
> >> +hook (void)
> >> +{
> >> + puts ("hello");
> >> +}
> >> +
> >> +int
> >> +main (void)
> >> +{
> >> + atexit (hook);
> >> +}
> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> >> new file mode 100644
> >> index 0000000000..ce01362503
> >> --- /dev/null
> >> +++ b/libio/tst-cleanup.exp
> >> @@ -0,0 +1 @@
> >> +hello
> >> --
> >> 2.31.0.291.g576ba9dcdaf-goog
> >>
> >
>
> diff --git a/config.h.in b/config.h.in
> index ca1547ae67..96a08c7757 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -187,6 +187,9 @@
> /* Define if gcc supports attribute ifunc. */
> #undef HAVE_GCC_IFUNC
>
> +/* Define if CC supports attribute retain. */
> +#undef HAVE_GNU_RETAIN
> +
> /* Define if the linker defines __ehdr_start. */
> #undef HAVE_EHDR_START
>
> diff --git a/configure b/configure
> index fcf43bf7de..e64b7f8efe 100755
> --- a/configure
> +++ b/configure
> @@ -4105,6 +4105,31 @@ fi
> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> @@ -5871,6 +5896,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
> 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],
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index 546fc26a7b..127ea656c2 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -352,6 +352,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. */
> @@ -367,12 +373,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
> diff --git a/libio/Makefile b/libio/Makefile
> index 12ce41038f..ad0d53bb49 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> $(objpfx)tst-bz24228-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
> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> endif
>
> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> + $(compile.c) -o $@
> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
> + $(compile.c) -o $@
Please add a separate .c file for each test to get the correct dependency.
> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-nostart-stop-gc-static.o: tst-cleanup.c
> + $(compile.c) -o $@
> +
> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> $(common-objpfx)libio/; \
> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> new file mode 100644
> index 0000000000..837feac164
> --- /dev/null
> +++ b/libio/tst-cleanup.c
> @@ -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);
> +}
> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> new file mode 100644
> index 0000000000..ce01362503
> --- /dev/null
> +++ b/libio/tst-cleanup.exp
> @@ -0,0 +1 @@
> +hello
> --
> 2.31.0.208.g409f899ff0-goog
>
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-02 14:14 ` H.J. Lu
@ 2021-04-02 17:09 ` Fangrui Song
2021-04-02 17:33 ` H.J. Lu
2021-04-03 18:02 ` Fangrui Song
1 sibling, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-04-02 17:09 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-04-02, H.J. Lu wrote:
>On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
>>
>> On 2021-04-01, H.J. Lu wrote:
>> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
>> >>
>> >> 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).
>> >> ---
>> >> Changes in v1 -> v2:
>> >> * Define attribute_used_retain_section
>> >> Changes in v2 -> v3:
>> >> * Use attribute_used_retain instead attribute_used_retain_section
>> >> Changes in v3 -> v4:
>> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
>> >> Changes in v4 -> v5:
>> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
>> >> * Rename *gcc_retain* to *gnu_retain*
>> >> ---
>> >> config.h.in | 3 +++
>> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
>> >> configure.ac | 21 +++++++++++++++
>> >> include/libc-symbols.h | 14 +++++++---
>> >> libio/Makefile | 32 +++++++++++++++++++++++
>> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
>> >> libio/tst-cleanup.exp | 1 +
>> >> 7 files changed, 159 insertions(+), 4 deletions(-)
>> >> create mode 100644 libio/tst-cleanup.c
>> >> create mode 100644 libio/tst-cleanup.exp
>> >>
>> >> diff --git a/config.h.in b/config.h.in
>> >> index ca1547ae67..96a08c7757 100644
>> >> --- a/config.h.in
>> >> +++ b/config.h.in
>> >> @@ -187,6 +187,9 @@
>> >> /* Define if gcc supports attribute ifunc. */
>> >> #undef HAVE_GCC_IFUNC
>> >>
>> >> +/* Define if CC supports attribute retain. */
>> >> +#undef HAVE_GNU_RETAIN
>> >> +
>> >> /* Define if the linker defines __ehdr_start. */
>> >> #undef HAVE_EHDR_START
>> >>
>> >> diff --git a/configure b/configure
>> >> index fcf43bf7de..e64b7f8efe 100755
>> >> --- a/configure
>> >> +++ b/configure
>> >> @@ -4105,6 +4105,31 @@ fi
>> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> @@ -5871,6 +5896,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
>> >> 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],
>> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> index 546fc26a7b..127ea656c2 100644
>> >> --- a/include/libc-symbols.h
>> >> +++ b/include/libc-symbols.h
>> >> @@ -352,6 +352,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. */
>> >> @@ -367,12 +373,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
>> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> index 12ce41038f..c9c232ebc2 100644
>> >> --- a/libio/Makefile
>> >> +++ b/libio/Makefile
>> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
>> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> $(objpfx)tst-bz24228-mem.out
>> >> endif
>> >> +
>> >> +tests += tst-cleanup-default
>> >> +tests-static += tst-cleanup-default
>> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
>> >
>> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
>>
>> Added.
>>
>> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
>> >> +
>> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
>> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
>> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
>> >
>> >Same here.
>>
>> Added.
>>
>> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
>> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
>> >> +endif
>> >> endif
>> >>
>> >> include ../Rules
>> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> endif
>> >>
>> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >> +
>> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >> +
>> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >>
>> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> >> $(common-objpfx)libio/; \
>> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> >> new file mode 100644
>> >> index 0000000000..7f0a34a91e
>> >> --- /dev/null
>> >> +++ b/libio/tst-cleanup.c
>> >> @@ -0,0 +1,33 @@
>> >
>> >Please add a comment saying that test --gc-sections.
>>
>> OK, added.
>>
>> >> +/* 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. */
>> >> +
>> >> +#include <stdio.h>
>> >> +#include <stdlib.h>
>> >> +
>> >> +void
>> >> +hook (void)
>> >> +{
>> >> + puts ("hello");
>> >> +}
>> >> +
>> >> +int
>> >> +main (void)
>> >> +{
>> >> + atexit (hook);
>> >> +}
>> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> >> new file mode 100644
>> >> index 0000000000..ce01362503
>> >> --- /dev/null
>> >> +++ b/libio/tst-cleanup.exp
>> >> @@ -0,0 +1 @@
>> >> +hello
>> >> --
>> >> 2.31.0.291.g576ba9dcdaf-goog
>> >>
>> >
>>
>> diff --git a/config.h.in b/config.h.in
>> index ca1547ae67..96a08c7757 100644
>> --- a/config.h.in
>> +++ b/config.h.in
>> @@ -187,6 +187,9 @@
>> /* Define if gcc supports attribute ifunc. */
>> #undef HAVE_GCC_IFUNC
>>
>> +/* Define if CC supports attribute retain. */
>> +#undef HAVE_GNU_RETAIN
>> +
>> /* Define if the linker defines __ehdr_start. */
>> #undef HAVE_EHDR_START
>>
>> diff --git a/configure b/configure
>> index fcf43bf7de..e64b7f8efe 100755
>> --- a/configure
>> +++ b/configure
>> @@ -4105,6 +4105,31 @@ fi
>> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> @@ -5871,6 +5896,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
>> 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],
>> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> index 546fc26a7b..127ea656c2 100644
>> --- a/include/libc-symbols.h
>> +++ b/include/libc-symbols.h
>> @@ -352,6 +352,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. */
>> @@ -367,12 +373,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
>> diff --git a/libio/Makefile b/libio/Makefile
>> index 12ce41038f..ad0d53bb49 100644
>> --- a/libio/Makefile
>> +++ b/libio/Makefile
>> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
>> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> $(objpfx)tst-bz24228-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
>> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> endif
>>
>> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
>> + $(compile.c) -o $@
>
>Please add a separate .c file for each test to get the correct dependency.
This is unnecessary.
$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
does the work perfectly.
>> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-nostart-stop-gc-static.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> $(common-objpfx)libio/; \
>> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> new file mode 100644
>> index 0000000000..837feac164
>> --- /dev/null
>> +++ b/libio/tst-cleanup.c
>> @@ -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);
>> +}
>> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> new file mode 100644
>> index 0000000000..ce01362503
>> --- /dev/null
>> +++ b/libio/tst-cleanup.exp
>> @@ -0,0 +1 @@
>> +hello
>> --
>> 2.31.0.208.g409f899ff0-goog
>>
>
>
>--
>H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-02 17:09 ` Fangrui Song
@ 2021-04-02 17:33 ` H.J. Lu
0 siblings, 0 replies; 40+ messages in thread
From: H.J. Lu @ 2021-04-02 17:33 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Fri, Apr 2, 2021 at 10:09 AM Fangrui Song <maskray@google.com> wrote:
>
> On 2021-04-02, H.J. Lu wrote:
> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2021-04-01, H.J. Lu wrote:
> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
> >> >>
> >> >> 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).
> >> >> ---
> >> >> Changes in v1 -> v2:
> >> >> * Define attribute_used_retain_section
> >> >> Changes in v2 -> v3:
> >> >> * Use attribute_used_retain instead attribute_used_retain_section
> >> >> Changes in v3 -> v4:
> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> >> >> Changes in v4 -> v5:
> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> >> >> * Rename *gcc_retain* to *gnu_retain*
> >> >> ---
> >> >> config.h.in | 3 +++
> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> >> >> configure.ac | 21 +++++++++++++++
> >> >> include/libc-symbols.h | 14 +++++++---
> >> >> libio/Makefile | 32 +++++++++++++++++++++++
> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> >> >> libio/tst-cleanup.exp | 1 +
> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
> >> >> create mode 100644 libio/tst-cleanup.c
> >> >> create mode 100644 libio/tst-cleanup.exp
> >> >>
> >> >> diff --git a/config.h.in b/config.h.in
> >> >> index ca1547ae67..96a08c7757 100644
> >> >> --- a/config.h.in
> >> >> +++ b/config.h.in
> >> >> @@ -187,6 +187,9 @@
> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> #undef HAVE_GCC_IFUNC
> >> >>
> >> >> +/* Define if CC supports attribute retain. */
> >> >> +#undef HAVE_GNU_RETAIN
> >> >> +
> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> #undef HAVE_EHDR_START
> >> >>
> >> >> diff --git a/configure b/configure
> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> --- a/configure
> >> >> +++ b/configure
> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> @@ -5871,6 +5896,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
> >> >> 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],
> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> --- a/include/libc-symbols.h
> >> >> +++ b/include/libc-symbols.h
> >> >> @@ -352,6 +352,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. */
> >> >> @@ -367,12 +373,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
> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> index 12ce41038f..c9c232ebc2 100644
> >> >> --- a/libio/Makefile
> >> >> +++ b/libio/Makefile
> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> $(objpfx)tst-bz24228-mem.out
> >> >> endif
> >> >> +
> >> >> +tests += tst-cleanup-default
> >> >> +tests-static += tst-cleanup-default
> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> >> >
> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
> >>
> >> Added.
> >>
> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> >> >> +
> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> >> >
> >> >Same here.
> >>
> >> Added.
> >>
> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> >> >> +endif
> >> >> endif
> >> >>
> >> >> include ../Rules
> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> endif
> >> >>
> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >> +
> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >> +
> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >>
> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> $(common-objpfx)libio/; \
> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> >> >> new file mode 100644
> >> >> index 0000000000..7f0a34a91e
> >> >> --- /dev/null
> >> >> +++ b/libio/tst-cleanup.c
> >> >> @@ -0,0 +1,33 @@
> >> >
> >> >Please add a comment saying that test --gc-sections.
> >>
> >> OK, added.
> >>
> >> >> +/* 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. */
> >> >> +
> >> >> +#include <stdio.h>
> >> >> +#include <stdlib.h>
> >> >> +
> >> >> +void
> >> >> +hook (void)
> >> >> +{
> >> >> + puts ("hello");
> >> >> +}
> >> >> +
> >> >> +int
> >> >> +main (void)
> >> >> +{
> >> >> + atexit (hook);
> >> >> +}
> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> >> >> new file mode 100644
> >> >> index 0000000000..ce01362503
> >> >> --- /dev/null
> >> >> +++ b/libio/tst-cleanup.exp
> >> >> @@ -0,0 +1 @@
> >> >> +hello
> >> >> --
> >> >> 2.31.0.291.g576ba9dcdaf-goog
> >> >>
> >> >
> >>
> >> diff --git a/config.h.in b/config.h.in
> >> index ca1547ae67..96a08c7757 100644
> >> --- a/config.h.in
> >> +++ b/config.h.in
> >> @@ -187,6 +187,9 @@
> >> /* Define if gcc supports attribute ifunc. */
> >> #undef HAVE_GCC_IFUNC
> >>
> >> +/* Define if CC supports attribute retain. */
> >> +#undef HAVE_GNU_RETAIN
> >> +
> >> /* Define if the linker defines __ehdr_start. */
> >> #undef HAVE_EHDR_START
> >>
> >> diff --git a/configure b/configure
> >> index fcf43bf7de..e64b7f8efe 100755
> >> --- a/configure
> >> +++ b/configure
> >> @@ -4105,6 +4105,31 @@ fi
> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> @@ -5871,6 +5896,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
> >> 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],
> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> index 546fc26a7b..127ea656c2 100644
> >> --- a/include/libc-symbols.h
> >> +++ b/include/libc-symbols.h
> >> @@ -352,6 +352,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. */
> >> @@ -367,12 +373,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
> >> diff --git a/libio/Makefile b/libio/Makefile
> >> index 12ce41038f..ad0d53bb49 100644
> >> --- a/libio/Makefile
> >> +++ b/libio/Makefile
> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> $(objpfx)tst-bz24228-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
> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> endif
> >>
> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +
> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >
> >Please add a separate .c file for each test to get the correct dependency.
>
> This is unnecessary.
>
> $(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
>
> does the work perfectly.
>
What does tst-cleanup-start-stop-gc-static.o.d contain?
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-02 14:14 ` H.J. Lu
2021-04-02 17:09 ` Fangrui Song
@ 2021-04-03 18:02 ` Fangrui Song
2021-04-03 20:47 ` H.J. Lu
1 sibling, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-04-03 18:02 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-04-02, H.J. Lu wrote:
>On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
>>
>> On 2021-04-01, H.J. Lu wrote:
>> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
>> >>
>> >> 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).
>> >> ---
>> >> Changes in v1 -> v2:
>> >> * Define attribute_used_retain_section
>> >> Changes in v2 -> v3:
>> >> * Use attribute_used_retain instead attribute_used_retain_section
>> >> Changes in v3 -> v4:
>> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
>> >> Changes in v4 -> v5:
>> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
>> >> * Rename *gcc_retain* to *gnu_retain*
>> >> ---
>> >> config.h.in | 3 +++
>> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
>> >> configure.ac | 21 +++++++++++++++
>> >> include/libc-symbols.h | 14 +++++++---
>> >> libio/Makefile | 32 +++++++++++++++++++++++
>> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
>> >> libio/tst-cleanup.exp | 1 +
>> >> 7 files changed, 159 insertions(+), 4 deletions(-)
>> >> create mode 100644 libio/tst-cleanup.c
>> >> create mode 100644 libio/tst-cleanup.exp
>> >>
>> >> diff --git a/config.h.in b/config.h.in
>> >> index ca1547ae67..96a08c7757 100644
>> >> --- a/config.h.in
>> >> +++ b/config.h.in
>> >> @@ -187,6 +187,9 @@
>> >> /* Define if gcc supports attribute ifunc. */
>> >> #undef HAVE_GCC_IFUNC
>> >>
>> >> +/* Define if CC supports attribute retain. */
>> >> +#undef HAVE_GNU_RETAIN
>> >> +
>> >> /* Define if the linker defines __ehdr_start. */
>> >> #undef HAVE_EHDR_START
>> >>
>> >> diff --git a/configure b/configure
>> >> index fcf43bf7de..e64b7f8efe 100755
>> >> --- a/configure
>> >> +++ b/configure
>> >> @@ -4105,6 +4105,31 @@ fi
>> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> @@ -5871,6 +5896,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
>> >> 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],
>> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> index 546fc26a7b..127ea656c2 100644
>> >> --- a/include/libc-symbols.h
>> >> +++ b/include/libc-symbols.h
>> >> @@ -352,6 +352,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. */
>> >> @@ -367,12 +373,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
>> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> index 12ce41038f..c9c232ebc2 100644
>> >> --- a/libio/Makefile
>> >> +++ b/libio/Makefile
>> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
>> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> $(objpfx)tst-bz24228-mem.out
>> >> endif
>> >> +
>> >> +tests += tst-cleanup-default
>> >> +tests-static += tst-cleanup-default
>> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
>> >
>> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
>>
>> Added.
>>
>> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
>> >> +
>> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
>> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
>> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
>> >
>> >Same here.
>>
>> Added.
>>
>> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
>> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
>> >> +endif
>> >> endif
>> >>
>> >> include ../Rules
>> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> endif
>> >>
>> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >> +
>> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >> +
>> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >>
>> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> >> $(common-objpfx)libio/; \
>> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> >> new file mode 100644
>> >> index 0000000000..7f0a34a91e
>> >> --- /dev/null
>> >> +++ b/libio/tst-cleanup.c
>> >> @@ -0,0 +1,33 @@
>> >
>> >Please add a comment saying that test --gc-sections.
>>
>> OK, added.
>>
>> >> +/* 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. */
>> >> +
>> >> +#include <stdio.h>
>> >> +#include <stdlib.h>
>> >> +
>> >> +void
>> >> +hook (void)
>> >> +{
>> >> + puts ("hello");
>> >> +}
>> >> +
>> >> +int
>> >> +main (void)
>> >> +{
>> >> + atexit (hook);
>> >> +}
>> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> >> new file mode 100644
>> >> index 0000000000..ce01362503
>> >> --- /dev/null
>> >> +++ b/libio/tst-cleanup.exp
>> >> @@ -0,0 +1 @@
>> >> +hello
>> >> --
>> >> 2.31.0.291.g576ba9dcdaf-goog
>> >>
>> >
>>
>> diff --git a/config.h.in b/config.h.in
>> index ca1547ae67..96a08c7757 100644
>> --- a/config.h.in
>> +++ b/config.h.in
>> @@ -187,6 +187,9 @@
>> /* Define if gcc supports attribute ifunc. */
>> #undef HAVE_GCC_IFUNC
>>
>> +/* Define if CC supports attribute retain. */
>> +#undef HAVE_GNU_RETAIN
>> +
>> /* Define if the linker defines __ehdr_start. */
>> #undef HAVE_EHDR_START
>>
>> diff --git a/configure b/configure
>> index fcf43bf7de..e64b7f8efe 100755
>> --- a/configure
>> +++ b/configure
>> @@ -4105,6 +4105,31 @@ fi
>> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> @@ -5871,6 +5896,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
>> 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],
>> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> index 546fc26a7b..127ea656c2 100644
>> --- a/include/libc-symbols.h
>> +++ b/include/libc-symbols.h
>> @@ -352,6 +352,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. */
>> @@ -367,12 +373,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
>> diff --git a/libio/Makefile b/libio/Makefile
>> index 12ce41038f..ad0d53bb49 100644
>> --- a/libio/Makefile
>> +++ b/libio/Makefile
>> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
>> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> $(objpfx)tst-bz24228-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
>> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> endif
>>
>> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
>> + $(compile.c) -o $@
>
>Please add a separate .c file for each test to get the correct dependency.
Changed this block to:
@@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.out: $(gen-locales)
endif
+$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-default.c: tst-cleanup.c
+ cp $< $@
+$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
+ cp $< $@
+
+$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
+ $(compile.c) -o $@
+$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
+ cp $< $@
+
+$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
+ cp $< $@
+$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
+ cmp $^ > $@; \
+ $(evaluate-test)
+$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
+ cp $< $@
+
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
$(common-objpfx)libio/; \
>> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-nostart-stop-gc-static.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +
>> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> $(common-objpfx)libio/; \
>> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> new file mode 100644
>> index 0000000000..837feac164
>> --- /dev/null
>> +++ b/libio/tst-cleanup.c
>> @@ -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);
>> +}
>> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> new file mode 100644
>> index 0000000000..ce01362503
>> --- /dev/null
>> +++ b/libio/tst-cleanup.exp
>> @@ -0,0 +1 @@
>> +hello
>> --
>> 2.31.0.208.g409f899ff0-goog
>>
>
>
>--
>H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-03 18:02 ` Fangrui Song
@ 2021-04-03 20:47 ` H.J. Lu
2021-04-03 21:57 ` Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-04-03 20:47 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
>
>
> On 2021-04-02, H.J. Lu wrote:
> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2021-04-01, H.J. Lu wrote:
> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
> >> >>
> >> >> 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).
> >> >> ---
> >> >> Changes in v1 -> v2:
> >> >> * Define attribute_used_retain_section
> >> >> Changes in v2 -> v3:
> >> >> * Use attribute_used_retain instead attribute_used_retain_section
> >> >> Changes in v3 -> v4:
> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> >> >> Changes in v4 -> v5:
> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> >> >> * Rename *gcc_retain* to *gnu_retain*
> >> >> ---
> >> >> config.h.in | 3 +++
> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> >> >> configure.ac | 21 +++++++++++++++
> >> >> include/libc-symbols.h | 14 +++++++---
> >> >> libio/Makefile | 32 +++++++++++++++++++++++
> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> >> >> libio/tst-cleanup.exp | 1 +
> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
> >> >> create mode 100644 libio/tst-cleanup.c
> >> >> create mode 100644 libio/tst-cleanup.exp
> >> >>
> >> >> diff --git a/config.h.in b/config.h.in
> >> >> index ca1547ae67..96a08c7757 100644
> >> >> --- a/config.h.in
> >> >> +++ b/config.h.in
> >> >> @@ -187,6 +187,9 @@
> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> #undef HAVE_GCC_IFUNC
> >> >>
> >> >> +/* Define if CC supports attribute retain. */
> >> >> +#undef HAVE_GNU_RETAIN
> >> >> +
> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> #undef HAVE_EHDR_START
> >> >>
> >> >> diff --git a/configure b/configure
> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> --- a/configure
> >> >> +++ b/configure
> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> @@ -5871,6 +5896,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
> >> >> 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],
> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> --- a/include/libc-symbols.h
> >> >> +++ b/include/libc-symbols.h
> >> >> @@ -352,6 +352,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. */
> >> >> @@ -367,12 +373,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
> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> index 12ce41038f..c9c232ebc2 100644
> >> >> --- a/libio/Makefile
> >> >> +++ b/libio/Makefile
> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> $(objpfx)tst-bz24228-mem.out
> >> >> endif
> >> >> +
> >> >> +tests += tst-cleanup-default
> >> >> +tests-static += tst-cleanup-default
> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> >> >
> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
> >>
> >> Added.
> >>
> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> >> >> +
> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> >> >
> >> >Same here.
> >>
> >> Added.
> >>
> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> >> >> +endif
> >> >> endif
> >> >>
> >> >> include ../Rules
> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> endif
> >> >>
> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >> +
> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >> +
> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >>
> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> $(common-objpfx)libio/; \
> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> >> >> new file mode 100644
> >> >> index 0000000000..7f0a34a91e
> >> >> --- /dev/null
> >> >> +++ b/libio/tst-cleanup.c
> >> >> @@ -0,0 +1,33 @@
> >> >
> >> >Please add a comment saying that test --gc-sections.
> >>
> >> OK, added.
> >>
> >> >> +/* 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. */
> >> >> +
> >> >> +#include <stdio.h>
> >> >> +#include <stdlib.h>
> >> >> +
> >> >> +void
> >> >> +hook (void)
> >> >> +{
> >> >> + puts ("hello");
> >> >> +}
> >> >> +
> >> >> +int
> >> >> +main (void)
> >> >> +{
> >> >> + atexit (hook);
> >> >> +}
> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> >> >> new file mode 100644
> >> >> index 0000000000..ce01362503
> >> >> --- /dev/null
> >> >> +++ b/libio/tst-cleanup.exp
> >> >> @@ -0,0 +1 @@
> >> >> +hello
> >> >> --
> >> >> 2.31.0.291.g576ba9dcdaf-goog
> >> >>
> >> >
> >>
> >> diff --git a/config.h.in b/config.h.in
> >> index ca1547ae67..96a08c7757 100644
> >> --- a/config.h.in
> >> +++ b/config.h.in
> >> @@ -187,6 +187,9 @@
> >> /* Define if gcc supports attribute ifunc. */
> >> #undef HAVE_GCC_IFUNC
> >>
> >> +/* Define if CC supports attribute retain. */
> >> +#undef HAVE_GNU_RETAIN
> >> +
> >> /* Define if the linker defines __ehdr_start. */
> >> #undef HAVE_EHDR_START
> >>
> >> diff --git a/configure b/configure
> >> index fcf43bf7de..e64b7f8efe 100755
> >> --- a/configure
> >> +++ b/configure
> >> @@ -4105,6 +4105,31 @@ fi
> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> @@ -5871,6 +5896,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
> >> 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],
> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> index 546fc26a7b..127ea656c2 100644
> >> --- a/include/libc-symbols.h
> >> +++ b/include/libc-symbols.h
> >> @@ -352,6 +352,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. */
> >> @@ -367,12 +373,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
> >> diff --git a/libio/Makefile b/libio/Makefile
> >> index 12ce41038f..ad0d53bb49 100644
> >> --- a/libio/Makefile
> >> +++ b/libio/Makefile
> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> $(objpfx)tst-bz24228-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
> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> endif
> >>
> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +
> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >
> >Please add a separate .c file for each test to get the correct dependency.
>
> Changed this block to:
>
> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> endif
>
> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
> + cp $< $@
> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
> + cp $< $@
> +
> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> + $(compile.c) -o $@
> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
> + cp $< $@
> +
> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
> + cp $< $@
> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
> + cmp $^ > $@; \
> + $(evaluate-test)
> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
> + cp $< $@
> +
> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> $(common-objpfx)libio/; \
>
"make clean" doesn't remove the generated files. The standard way in glibc
is to add a *-static.c source.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-03 20:47 ` H.J. Lu
@ 2021-04-03 21:57 ` Fangrui Song
2021-04-05 1:55 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-04-03 21:57 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-04-03, H.J. Lu wrote:
>On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
>>
>>
>> On 2021-04-02, H.J. Lu wrote:
>> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
>> >>
>> >> On 2021-04-01, H.J. Lu wrote:
>> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
>> >> >>
>> >> >> 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).
>> >> >> ---
>> >> >> Changes in v1 -> v2:
>> >> >> * Define attribute_used_retain_section
>> >> >> Changes in v2 -> v3:
>> >> >> * Use attribute_used_retain instead attribute_used_retain_section
>> >> >> Changes in v3 -> v4:
>> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
>> >> >> Changes in v4 -> v5:
>> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
>> >> >> * Rename *gcc_retain* to *gnu_retain*
>> >> >> ---
>> >> >> config.h.in | 3 +++
>> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
>> >> >> configure.ac | 21 +++++++++++++++
>> >> >> include/libc-symbols.h | 14 +++++++---
>> >> >> libio/Makefile | 32 +++++++++++++++++++++++
>> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
>> >> >> libio/tst-cleanup.exp | 1 +
>> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
>> >> >> create mode 100644 libio/tst-cleanup.c
>> >> >> create mode 100644 libio/tst-cleanup.exp
>> >> >>
>> >> >> diff --git a/config.h.in b/config.h.in
>> >> >> index ca1547ae67..96a08c7757 100644
>> >> >> --- a/config.h.in
>> >> >> +++ b/config.h.in
>> >> >> @@ -187,6 +187,9 @@
>> >> >> /* Define if gcc supports attribute ifunc. */
>> >> >> #undef HAVE_GCC_IFUNC
>> >> >>
>> >> >> +/* Define if CC supports attribute retain. */
>> >> >> +#undef HAVE_GNU_RETAIN
>> >> >> +
>> >> >> /* Define if the linker defines __ehdr_start. */
>> >> >> #undef HAVE_EHDR_START
>> >> >>
>> >> >> diff --git a/configure b/configure
>> >> >> index fcf43bf7de..e64b7f8efe 100755
>> >> >> --- a/configure
>> >> >> +++ b/configure
>> >> >> @@ -4105,6 +4105,31 @@ fi
>> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> >> @@ -5871,6 +5896,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
>> >> >> 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],
>> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> >> index 546fc26a7b..127ea656c2 100644
>> >> >> --- a/include/libc-symbols.h
>> >> >> +++ b/include/libc-symbols.h
>> >> >> @@ -352,6 +352,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. */
>> >> >> @@ -367,12 +373,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
>> >> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> >> index 12ce41038f..c9c232ebc2 100644
>> >> >> --- a/libio/Makefile
>> >> >> +++ b/libio/Makefile
>> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
>> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> >> $(objpfx)tst-bz24228-mem.out
>> >> >> endif
>> >> >> +
>> >> >> +tests += tst-cleanup-default
>> >> >> +tests-static += tst-cleanup-default
>> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
>> >> >
>> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
>> >>
>> >> Added.
>> >>
>> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
>> >> >> +
>> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
>> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
>> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
>> >> >
>> >> >Same here.
>> >>
>> >> Added.
>> >>
>> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
>> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
>> >> >> +endif
>> >> >> endif
>> >> >>
>> >> >> include ../Rules
>> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> >> endif
>> >> >>
>> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> >> + $(compile.c) -o $@
>> >> >> +
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> >> + $(compile.c) -o $@
>> >> >> +
>> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> >> >> + $(compile.c) -o $@
>> >> >>
>> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> >> >> $(common-objpfx)libio/; \
>> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> >> >> new file mode 100644
>> >> >> index 0000000000..7f0a34a91e
>> >> >> --- /dev/null
>> >> >> +++ b/libio/tst-cleanup.c
>> >> >> @@ -0,0 +1,33 @@
>> >> >
>> >> >Please add a comment saying that test --gc-sections.
>> >>
>> >> OK, added.
>> >>
>> >> >> +/* 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. */
>> >> >> +
>> >> >> +#include <stdio.h>
>> >> >> +#include <stdlib.h>
>> >> >> +
>> >> >> +void
>> >> >> +hook (void)
>> >> >> +{
>> >> >> + puts ("hello");
>> >> >> +}
>> >> >> +
>> >> >> +int
>> >> >> +main (void)
>> >> >> +{
>> >> >> + atexit (hook);
>> >> >> +}
>> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> >> >> new file mode 100644
>> >> >> index 0000000000..ce01362503
>> >> >> --- /dev/null
>> >> >> +++ b/libio/tst-cleanup.exp
>> >> >> @@ -0,0 +1 @@
>> >> >> +hello
>> >> >> --
>> >> >> 2.31.0.291.g576ba9dcdaf-goog
>> >> >>
>> >> >
>> >>
>> >> diff --git a/config.h.in b/config.h.in
>> >> index ca1547ae67..96a08c7757 100644
>> >> --- a/config.h.in
>> >> +++ b/config.h.in
>> >> @@ -187,6 +187,9 @@
>> >> /* Define if gcc supports attribute ifunc. */
>> >> #undef HAVE_GCC_IFUNC
>> >>
>> >> +/* Define if CC supports attribute retain. */
>> >> +#undef HAVE_GNU_RETAIN
>> >> +
>> >> /* Define if the linker defines __ehdr_start. */
>> >> #undef HAVE_EHDR_START
>> >>
>> >> diff --git a/configure b/configure
>> >> index fcf43bf7de..e64b7f8efe 100755
>> >> --- a/configure
>> >> +++ b/configure
>> >> @@ -4105,6 +4105,31 @@ fi
>> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> @@ -5871,6 +5896,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
>> >> 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],
>> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> index 546fc26a7b..127ea656c2 100644
>> >> --- a/include/libc-symbols.h
>> >> +++ b/include/libc-symbols.h
>> >> @@ -352,6 +352,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. */
>> >> @@ -367,12 +373,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
>> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> index 12ce41038f..ad0d53bb49 100644
>> >> --- a/libio/Makefile
>> >> +++ b/libio/Makefile
>> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
>> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> $(objpfx)tst-bz24228-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
>> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> endif
>> >>
>> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >> +
>> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >
>> >Please add a separate .c file for each test to get the correct dependency.
>>
>> Changed this block to:
>>
>> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> endif
>>
>> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
>> + cp $< $@
>> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
>> + cp $< $@
>> +
>> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> + $(compile.c) -o $@
>> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
>> + cp $< $@
>> +
>> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
>> + cp $< $@
>> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
>> + cmp $^ > $@; \
>> + $(evaluate-test)
>> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
>> + cp $< $@
>> +
>> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> $(common-objpfx)libio/; \
>>
>
>"make clean" doesn't remove the generated files. The standard way in glibc
>is to add a *-static.c source.
I'll use .INTERMEDIATE and $(eval $(call ..))
diff --git a/libio/Makefile b/libio/Makefile
index 12ce41038f..a9b44f04df 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
$(objpfx)tst-bz24228-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
@@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.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)
+$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
+ cp $$< $$@
+.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
+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/; \
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-03 21:57 ` Fangrui Song
@ 2021-04-05 1:55 ` H.J. Lu
2021-04-05 18:17 ` Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-04-05 1:55 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Sat, Apr 3, 2021 at 2:57 PM Fangrui Song <maskray@google.com> wrote:
>
> On 2021-04-03, H.J. Lu wrote:
> >On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
> >>
> >>
> >> On 2021-04-02, H.J. Lu wrote:
> >> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
> >> >>
> >> >> On 2021-04-01, H.J. Lu wrote:
> >> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >>
> >> >> >> 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).
> >> >> >> ---
> >> >> >> Changes in v1 -> v2:
> >> >> >> * Define attribute_used_retain_section
> >> >> >> Changes in v2 -> v3:
> >> >> >> * Use attribute_used_retain instead attribute_used_retain_section
> >> >> >> Changes in v3 -> v4:
> >> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> >> >> >> Changes in v4 -> v5:
> >> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> >> >> >> * Rename *gcc_retain* to *gnu_retain*
> >> >> >> ---
> >> >> >> config.h.in | 3 +++
> >> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> >> >> >> configure.ac | 21 +++++++++++++++
> >> >> >> include/libc-symbols.h | 14 +++++++---
> >> >> >> libio/Makefile | 32 +++++++++++++++++++++++
> >> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> >> >> >> libio/tst-cleanup.exp | 1 +
> >> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
> >> >> >> create mode 100644 libio/tst-cleanup.c
> >> >> >> create mode 100644 libio/tst-cleanup.exp
> >> >> >>
> >> >> >> diff --git a/config.h.in b/config.h.in
> >> >> >> index ca1547ae67..96a08c7757 100644
> >> >> >> --- a/config.h.in
> >> >> >> +++ b/config.h.in
> >> >> >> @@ -187,6 +187,9 @@
> >> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> >> #undef HAVE_GCC_IFUNC
> >> >> >>
> >> >> >> +/* Define if CC supports attribute retain. */
> >> >> >> +#undef HAVE_GNU_RETAIN
> >> >> >> +
> >> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> >> #undef HAVE_EHDR_START
> >> >> >>
> >> >> >> diff --git a/configure b/configure
> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> >> --- a/configure
> >> >> >> +++ b/configure
> >> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> >> @@ -5871,6 +5896,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
> >> >> >> 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],
> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> >> --- a/include/libc-symbols.h
> >> >> >> +++ b/include/libc-symbols.h
> >> >> >> @@ -352,6 +352,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. */
> >> >> >> @@ -367,12 +373,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
> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> index 12ce41038f..c9c232ebc2 100644
> >> >> >> --- a/libio/Makefile
> >> >> >> +++ b/libio/Makefile
> >> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> $(objpfx)tst-bz24228-mem.out
> >> >> >> endif
> >> >> >> +
> >> >> >> +tests += tst-cleanup-default
> >> >> >> +tests-static += tst-cleanup-default
> >> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> >> >> >
> >> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
> >> >>
> >> >> Added.
> >> >>
> >> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> >> >> >> +
> >> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> >> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> >> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> >> >> >
> >> >> >Same here.
> >> >>
> >> >> Added.
> >> >>
> >> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> >> >> >> +endif
> >> >> >> endif
> >> >> >>
> >> >> >> include ../Rules
> >> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> endif
> >> >> >>
> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> >> + $(compile.c) -o $@
> >> >> >> +
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> + $(compile.c) -o $@
> >> >> >> +
> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> >> >> >> + $(compile.c) -o $@
> >> >> >>
> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> >> $(common-objpfx)libio/; \
> >> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> >> >> >> new file mode 100644
> >> >> >> index 0000000000..7f0a34a91e
> >> >> >> --- /dev/null
> >> >> >> +++ b/libio/tst-cleanup.c
> >> >> >> @@ -0,0 +1,33 @@
> >> >> >
> >> >> >Please add a comment saying that test --gc-sections.
> >> >>
> >> >> OK, added.
> >> >>
> >> >> >> +/* 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. */
> >> >> >> +
> >> >> >> +#include <stdio.h>
> >> >> >> +#include <stdlib.h>
> >> >> >> +
> >> >> >> +void
> >> >> >> +hook (void)
> >> >> >> +{
> >> >> >> + puts ("hello");
> >> >> >> +}
> >> >> >> +
> >> >> >> +int
> >> >> >> +main (void)
> >> >> >> +{
> >> >> >> + atexit (hook);
> >> >> >> +}
> >> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> >> >> >> new file mode 100644
> >> >> >> index 0000000000..ce01362503
> >> >> >> --- /dev/null
> >> >> >> +++ b/libio/tst-cleanup.exp
> >> >> >> @@ -0,0 +1 @@
> >> >> >> +hello
> >> >> >> --
> >> >> >> 2.31.0.291.g576ba9dcdaf-goog
> >> >> >>
> >> >> >
> >> >>
> >> >> diff --git a/config.h.in b/config.h.in
> >> >> index ca1547ae67..96a08c7757 100644
> >> >> --- a/config.h.in
> >> >> +++ b/config.h.in
> >> >> @@ -187,6 +187,9 @@
> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> #undef HAVE_GCC_IFUNC
> >> >>
> >> >> +/* Define if CC supports attribute retain. */
> >> >> +#undef HAVE_GNU_RETAIN
> >> >> +
> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> #undef HAVE_EHDR_START
> >> >>
> >> >> diff --git a/configure b/configure
> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> --- a/configure
> >> >> +++ b/configure
> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> @@ -5871,6 +5896,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
> >> >> 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],
> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> --- a/include/libc-symbols.h
> >> >> +++ b/include/libc-symbols.h
> >> >> @@ -352,6 +352,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. */
> >> >> @@ -367,12 +373,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
> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> index 12ce41038f..ad0d53bb49 100644
> >> >> --- a/libio/Makefile
> >> >> +++ b/libio/Makefile
> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> $(objpfx)tst-bz24228-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
> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> endif
> >> >>
> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >> +
> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >
> >> >Please add a separate .c file for each test to get the correct dependency.
> >>
> >> Changed this block to:
> >>
> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> endif
> >>
> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
> >> + cp $< $@
> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
> >> + cp $< $@
> >> +
> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> + $(compile.c) -o $@
> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
> >> + cp $< $@
> >> +
> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
> >> + cp $< $@
> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
> >> + cmp $^ > $@; \
> >> + $(evaluate-test)
> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
> >> + cp $< $@
> >> +
> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> $(common-objpfx)libio/; \
> >>
> >
> >"make clean" doesn't remove the generated files. The standard way in glibc
> >is to add a *-static.c source.
>
> I'll use .INTERMEDIATE and $(eval $(call ..))
>
> diff --git a/libio/Makefile b/libio/Makefile
> index 12ce41038f..a9b44f04df 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> $(objpfx)tst-bz24228-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
> @@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> $(objpfx)tst-wfile-sync.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)
> +$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
> + cp $$< $$@
> +.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
> +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/; \
There are 2 issues with static tests:
1. A separate static source is needed.
2. We need to add the static test to both tests and tests-static.
If you want to add a separate static source, you can submit a separate patch
to address these 2 issues together.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-05 1:55 ` H.J. Lu
@ 2021-04-05 18:17 ` Fangrui Song
2021-04-05 20:35 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-04-05 18:17 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-04-04, H.J. Lu wrote:
>On Sat, Apr 3, 2021 at 2:57 PM Fangrui Song <maskray@google.com> wrote:
>>
>> On 2021-04-03, H.J. Lu wrote:
>> >On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
>> >>
>> >>
>> >> On 2021-04-02, H.J. Lu wrote:
>> >> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
>> >> >>
>> >> >> On 2021-04-01, H.J. Lu wrote:
>> >> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
>> >> >> >>
>> >> >> >> 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).
>> >> >> >> ---
>> >> >> >> Changes in v1 -> v2:
>> >> >> >> * Define attribute_used_retain_section
>> >> >> >> Changes in v2 -> v3:
>> >> >> >> * Use attribute_used_retain instead attribute_used_retain_section
>> >> >> >> Changes in v3 -> v4:
>> >> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
>> >> >> >> Changes in v4 -> v5:
>> >> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
>> >> >> >> * Rename *gcc_retain* to *gnu_retain*
>> >> >> >> ---
>> >> >> >> config.h.in | 3 +++
>> >> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
>> >> >> >> configure.ac | 21 +++++++++++++++
>> >> >> >> include/libc-symbols.h | 14 +++++++---
>> >> >> >> libio/Makefile | 32 +++++++++++++++++++++++
>> >> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
>> >> >> >> libio/tst-cleanup.exp | 1 +
>> >> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
>> >> >> >> create mode 100644 libio/tst-cleanup.c
>> >> >> >> create mode 100644 libio/tst-cleanup.exp
>> >> >> >>
>> >> >> >> diff --git a/config.h.in b/config.h.in
>> >> >> >> index ca1547ae67..96a08c7757 100644
>> >> >> >> --- a/config.h.in
>> >> >> >> +++ b/config.h.in
>> >> >> >> @@ -187,6 +187,9 @@
>> >> >> >> /* Define if gcc supports attribute ifunc. */
>> >> >> >> #undef HAVE_GCC_IFUNC
>> >> >> >>
>> >> >> >> +/* Define if CC supports attribute retain. */
>> >> >> >> +#undef HAVE_GNU_RETAIN
>> >> >> >> +
>> >> >> >> /* Define if the linker defines __ehdr_start. */
>> >> >> >> #undef HAVE_EHDR_START
>> >> >> >>
>> >> >> >> diff --git a/configure b/configure
>> >> >> >> index fcf43bf7de..e64b7f8efe 100755
>> >> >> >> --- a/configure
>> >> >> >> +++ b/configure
>> >> >> >> @@ -4105,6 +4105,31 @@ fi
>> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> >> >> @@ -5871,6 +5896,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
>> >> >> >> 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],
>> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> >> >> index 546fc26a7b..127ea656c2 100644
>> >> >> >> --- a/include/libc-symbols.h
>> >> >> >> +++ b/include/libc-symbols.h
>> >> >> >> @@ -352,6 +352,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. */
>> >> >> >> @@ -367,12 +373,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
>> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> >> >> index 12ce41038f..c9c232ebc2 100644
>> >> >> >> --- a/libio/Makefile
>> >> >> >> +++ b/libio/Makefile
>> >> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
>> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> >> >> $(objpfx)tst-bz24228-mem.out
>> >> >> >> endif
>> >> >> >> +
>> >> >> >> +tests += tst-cleanup-default
>> >> >> >> +tests-static += tst-cleanup-default
>> >> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
>> >> >> >
>> >> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
>> >> >>
>> >> >> Added.
>> >> >>
>> >> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
>> >> >> >> +
>> >> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
>> >> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
>> >> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
>> >> >> >
>> >> >> >Same here.
>> >> >>
>> >> >> Added.
>> >> >>
>> >> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
>> >> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
>> >> >> >> +endif
>> >> >> >> endif
>> >> >> >>
>> >> >> >> include ../Rules
>> >> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> >> >> endif
>> >> >> >>
>> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> >> >> + $(compile.c) -o $@
>> >> >> >> +
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> >> >> + $(compile.c) -o $@
>> >> >> >> +
>> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> >> >> >> + $(compile.c) -o $@
>> >> >> >>
>> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> >> >> >> $(common-objpfx)libio/; \
>> >> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> >> >> >> new file mode 100644
>> >> >> >> index 0000000000..7f0a34a91e
>> >> >> >> --- /dev/null
>> >> >> >> +++ b/libio/tst-cleanup.c
>> >> >> >> @@ -0,0 +1,33 @@
>> >> >> >
>> >> >> >Please add a comment saying that test --gc-sections.
>> >> >>
>> >> >> OK, added.
>> >> >>
>> >> >> >> +/* 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. */
>> >> >> >> +
>> >> >> >> +#include <stdio.h>
>> >> >> >> +#include <stdlib.h>
>> >> >> >> +
>> >> >> >> +void
>> >> >> >> +hook (void)
>> >> >> >> +{
>> >> >> >> + puts ("hello");
>> >> >> >> +}
>> >> >> >> +
>> >> >> >> +int
>> >> >> >> +main (void)
>> >> >> >> +{
>> >> >> >> + atexit (hook);
>> >> >> >> +}
>> >> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> >> >> >> new file mode 100644
>> >> >> >> index 0000000000..ce01362503
>> >> >> >> --- /dev/null
>> >> >> >> +++ b/libio/tst-cleanup.exp
>> >> >> >> @@ -0,0 +1 @@
>> >> >> >> +hello
>> >> >> >> --
>> >> >> >> 2.31.0.291.g576ba9dcdaf-goog
>> >> >> >>
>> >> >> >
>> >> >>
>> >> >> diff --git a/config.h.in b/config.h.in
>> >> >> index ca1547ae67..96a08c7757 100644
>> >> >> --- a/config.h.in
>> >> >> +++ b/config.h.in
>> >> >> @@ -187,6 +187,9 @@
>> >> >> /* Define if gcc supports attribute ifunc. */
>> >> >> #undef HAVE_GCC_IFUNC
>> >> >>
>> >> >> +/* Define if CC supports attribute retain. */
>> >> >> +#undef HAVE_GNU_RETAIN
>> >> >> +
>> >> >> /* Define if the linker defines __ehdr_start. */
>> >> >> #undef HAVE_EHDR_START
>> >> >>
>> >> >> diff --git a/configure b/configure
>> >> >> index fcf43bf7de..e64b7f8efe 100755
>> >> >> --- a/configure
>> >> >> +++ b/configure
>> >> >> @@ -4105,6 +4105,31 @@ fi
>> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> >> @@ -5871,6 +5896,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
>> >> >> 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],
>> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> >> index 546fc26a7b..127ea656c2 100644
>> >> >> --- a/include/libc-symbols.h
>> >> >> +++ b/include/libc-symbols.h
>> >> >> @@ -352,6 +352,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. */
>> >> >> @@ -367,12 +373,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
>> >> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> >> index 12ce41038f..ad0d53bb49 100644
>> >> >> --- a/libio/Makefile
>> >> >> +++ b/libio/Makefile
>> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
>> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> >> $(objpfx)tst-bz24228-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
>> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> >> endif
>> >> >>
>> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> >> + $(compile.c) -o $@
>> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
>> >> >> + $(compile.c) -o $@
>> >> >> +
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> >> + $(compile.c) -o $@
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
>> >> >> + $(compile.c) -o $@
>> >> >
>> >> >Please add a separate .c file for each test to get the correct dependency.
>> >>
>> >> Changed this block to:
>> >>
>> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> endif
>> >>
>> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
>> >> + cp $< $@
>> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
>> >> + cp $< $@
>> >> +
>> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> + $(compile.c) -o $@
>> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
>> >> + cp $< $@
>> >> +
>> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
>> >> + cp $< $@
>> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
>> >> + cmp $^ > $@; \
>> >> + $(evaluate-test)
>> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
>> >> + cp $< $@
>> >> +
>> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> >> $(common-objpfx)libio/; \
>> >>
>> >
>> >"make clean" doesn't remove the generated files. The standard way in glibc
>> >is to add a *-static.c source.
>>
>> I'll use .INTERMEDIATE and $(eval $(call ..))
>>
>> diff --git a/libio/Makefile b/libio/Makefile
>> index 12ce41038f..a9b44f04df 100644
>> --- a/libio/Makefile
>> +++ b/libio/Makefile
>> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
>> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> $(objpfx)tst-bz24228-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
>> @@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> $(objpfx)tst-wfile-sync.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)
>> +$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
>> + cp $$< $$@
>> +.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
>> +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/; \
>
>There are 2 issues with static tests:
>
>1. A separate static source is needed.
.INTERMEDIATE perfectly solves the lingering copied source issue.
I don't see lingering libio/tst-cleanup-*.c
>2. We need to add the static test to both tests and tests-static.
tests-static suffices. I have checked some tests-static usage in other
directories.
I have additionally checked that:
* touch libc.a => next invocation `make -r -C ~/Dev/glibc/libio objdir=$PWD check -j 20` will rebuild the static tests
* touch libc.so => next invocation `make -r -C ~/Dev/glibc/libio objdir=$PWD check -j 20` will rebuild the dynamic tests
* rm libio/tst-cleanup-default-cmp.out => next invocation `make -r -C ~/Dev/glibc/libio objdir=$PWD check -j 20` will rerun the single test
>If you want to add a separate static source, you can submit a separate patch
>to address these 2 issues together.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-05 18:17 ` Fangrui Song
@ 2021-04-05 20:35 ` H.J. Lu
2021-04-05 21:03 ` Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-04-05 20:35 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Mon, Apr 5, 2021 at 11:17 AM Fangrui Song <maskray@google.com> wrote:
>
> On 2021-04-04, H.J. Lu wrote:
> >On Sat, Apr 3, 2021 at 2:57 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2021-04-03, H.J. Lu wrote:
> >> >On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
> >> >>
> >> >>
> >> >> On 2021-04-02, H.J. Lu wrote:
> >> >> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >>
> >> >> >> On 2021-04-01, H.J. Lu wrote:
> >> >> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >> >>
> >> >> >> >> 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).
> >> >> >> >> ---
> >> >> >> >> Changes in v1 -> v2:
> >> >> >> >> * Define attribute_used_retain_section
> >> >> >> >> Changes in v2 -> v3:
> >> >> >> >> * Use attribute_used_retain instead attribute_used_retain_section
> >> >> >> >> Changes in v3 -> v4:
> >> >> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> >> >> >> >> Changes in v4 -> v5:
> >> >> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> >> >> >> >> * Rename *gcc_retain* to *gnu_retain*
> >> >> >> >> ---
> >> >> >> >> config.h.in | 3 +++
> >> >> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> >> >> >> >> configure.ac | 21 +++++++++++++++
> >> >> >> >> include/libc-symbols.h | 14 +++++++---
> >> >> >> >> libio/Makefile | 32 +++++++++++++++++++++++
> >> >> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> >> >> >> >> libio/tst-cleanup.exp | 1 +
> >> >> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
> >> >> >> >> create mode 100644 libio/tst-cleanup.c
> >> >> >> >> create mode 100644 libio/tst-cleanup.exp
> >> >> >> >>
> >> >> >> >> diff --git a/config.h.in b/config.h.in
> >> >> >> >> index ca1547ae67..96a08c7757 100644
> >> >> >> >> --- a/config.h.in
> >> >> >> >> +++ b/config.h.in
> >> >> >> >> @@ -187,6 +187,9 @@
> >> >> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> >> >> #undef HAVE_GCC_IFUNC
> >> >> >> >>
> >> >> >> >> +/* Define if CC supports attribute retain. */
> >> >> >> >> +#undef HAVE_GNU_RETAIN
> >> >> >> >> +
> >> >> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> >> >> #undef HAVE_EHDR_START
> >> >> >> >>
> >> >> >> >> diff --git a/configure b/configure
> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> >> >> --- a/configure
> >> >> >> >> +++ b/configure
> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> >> >> @@ -5871,6 +5896,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
> >> >> >> >> 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],
> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> >> >> --- a/include/libc-symbols.h
> >> >> >> >> +++ b/include/libc-symbols.h
> >> >> >> >> @@ -352,6 +352,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. */
> >> >> >> >> @@ -367,12 +373,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
> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> >> index 12ce41038f..c9c232ebc2 100644
> >> >> >> >> --- a/libio/Makefile
> >> >> >> >> +++ b/libio/Makefile
> >> >> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> >> $(objpfx)tst-bz24228-mem.out
> >> >> >> >> endif
> >> >> >> >> +
> >> >> >> >> +tests += tst-cleanup-default
> >> >> >> >> +tests-static += tst-cleanup-default
> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> >> >> >> >
> >> >> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
> >> >> >>
> >> >> >> Added.
> >> >> >>
> >> >> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> >> >> >> >> +
> >> >> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> >> >> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> >> >> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> >> >> >> >
> >> >> >> >Same here.
> >> >> >>
> >> >> >> Added.
> >> >> >>
> >> >> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >> >> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> >> >> >> >> +endif
> >> >> >> >> endif
> >> >> >> >>
> >> >> >> >> include ../Rules
> >> >> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> >> endif
> >> >> >> >>
> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> +
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> +
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >>
> >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> >> >> $(common-objpfx)libio/; \
> >> >> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> >> >> >> >> new file mode 100644
> >> >> >> >> index 0000000000..7f0a34a91e
> >> >> >> >> --- /dev/null
> >> >> >> >> +++ b/libio/tst-cleanup.c
> >> >> >> >> @@ -0,0 +1,33 @@
> >> >> >> >
> >> >> >> >Please add a comment saying that test --gc-sections.
> >> >> >>
> >> >> >> OK, added.
> >> >> >>
> >> >> >> >> +/* 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. */
> >> >> >> >> +
> >> >> >> >> +#include <stdio.h>
> >> >> >> >> +#include <stdlib.h>
> >> >> >> >> +
> >> >> >> >> +void
> >> >> >> >> +hook (void)
> >> >> >> >> +{
> >> >> >> >> + puts ("hello");
> >> >> >> >> +}
> >> >> >> >> +
> >> >> >> >> +int
> >> >> >> >> +main (void)
> >> >> >> >> +{
> >> >> >> >> + atexit (hook);
> >> >> >> >> +}
> >> >> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> >> >> >> >> new file mode 100644
> >> >> >> >> index 0000000000..ce01362503
> >> >> >> >> --- /dev/null
> >> >> >> >> +++ b/libio/tst-cleanup.exp
> >> >> >> >> @@ -0,0 +1 @@
> >> >> >> >> +hello
> >> >> >> >> --
> >> >> >> >> 2.31.0.291.g576ba9dcdaf-goog
> >> >> >> >>
> >> >> >> >
> >> >> >>
> >> >> >> diff --git a/config.h.in b/config.h.in
> >> >> >> index ca1547ae67..96a08c7757 100644
> >> >> >> --- a/config.h.in
> >> >> >> +++ b/config.h.in
> >> >> >> @@ -187,6 +187,9 @@
> >> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> >> #undef HAVE_GCC_IFUNC
> >> >> >>
> >> >> >> +/* Define if CC supports attribute retain. */
> >> >> >> +#undef HAVE_GNU_RETAIN
> >> >> >> +
> >> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> >> #undef HAVE_EHDR_START
> >> >> >>
> >> >> >> diff --git a/configure b/configure
> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> >> --- a/configure
> >> >> >> +++ b/configure
> >> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> >> @@ -5871,6 +5896,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
> >> >> >> 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],
> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> >> --- a/include/libc-symbols.h
> >> >> >> +++ b/include/libc-symbols.h
> >> >> >> @@ -352,6 +352,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. */
> >> >> >> @@ -367,12 +373,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
> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> index 12ce41038f..ad0d53bb49 100644
> >> >> >> --- a/libio/Makefile
> >> >> >> +++ b/libio/Makefile
> >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> $(objpfx)tst-bz24228-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
> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> endif
> >> >> >>
> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> >> + $(compile.c) -o $@
> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
> >> >> >> + $(compile.c) -o $@
> >> >> >> +
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> + $(compile.c) -o $@
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
> >> >> >> + $(compile.c) -o $@
> >> >> >
> >> >> >Please add a separate .c file for each test to get the correct dependency.
> >> >>
> >> >> Changed this block to:
> >> >>
> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> endif
> >> >>
> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
> >> >> + cp $< $@
> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
> >> >> + cp $< $@
> >> >> +
> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> + $(compile.c) -o $@
> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
> >> >> + cp $< $@
> >> >> +
> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
> >> >> + cp $< $@
> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
> >> >> + cmp $^ > $@; \
> >> >> + $(evaluate-test)
> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
> >> >> + cp $< $@
> >> >> +
> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> $(common-objpfx)libio/; \
> >> >>
> >> >
> >> >"make clean" doesn't remove the generated files. The standard way in glibc
> >> >is to add a *-static.c source.
> >>
> >> I'll use .INTERMEDIATE and $(eval $(call ..))
> >>
> >> diff --git a/libio/Makefile b/libio/Makefile
> >> index 12ce41038f..a9b44f04df 100644
> >> --- a/libio/Makefile
> >> +++ b/libio/Makefile
> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> $(objpfx)tst-bz24228-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
> >> @@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> $(objpfx)tst-wfile-sync.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)
> >> +$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
> >> + cp $$< $$@
> >> +.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
> >> +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/; \
> >
> >There are 2 issues with static tests:
> >
> >1. A separate static source is needed.
>
> .INTERMEDIATE perfectly solves the lingering copied source issue.
> I don't see lingering libio/tst-cleanup-*.c
I was referring to
elf/tst-array1-static.c
elf/tst-array5-static.c
elf/tst-dl-iter-static.c
elf/tst-dst-static.c
elf/tst-leaks1-static.c
elf/tst-libc_dlvsym-static.c
elf/tst-linkall-static.c
elf/tst-ptrguard1-static.c
elf/tst-single_threaded-pthread-static.c
elf/tst-single_threaded-static.c
elf/tst-stackguard1-static.c
elf/tst-tls1-static.c
elf/tst-tls2-static.c
elf/tst-tls9-static.c
elf/tst-tlsalign-extern-static.c
elf/tst-tlsalign-static.c
gmon/tst-gmon-static.c
gmon/tst-profile-static.c
localedata/bug-setlocale1-static.c
localedata/tst-langinfo-newlocale-static.c
localedata/tst-langinfo-setlocale-static.c
localedata/tst-langinfo-static.c
malloc/tst-malloc-usable-static.c
math/test-fpucw-ieee-static.c
math/test-fpucw-static.c
math/test-signgam-uchar-init-static.c
math/test-signgam-uchar-static.c
math/test-signgam-uint-init-static.c
math/test-signgam-uint-static.c
math/test-signgam-ullong-init-static.c
math/test-signgam-ullong-static.c
nptl/tst-mutex8-static.c
nptl/tst-mutexpi8-static.c
nptl/tst-sem11-static.c
nptl/tst-sem12-static.c
nptl/tst-setuid1-static.c
nptl/tst-stackguard1-static.c
nss/tst-nss-static.c
posix/tst-exec-static.c
posix/tst-spawn-static.c
setjmp/tst-setjmp-static.c
> >2. We need to add the static test to both tests and tests-static.
>
> tests-static suffices. I have checked some tests-static usage in other
> directories.
There are
tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
tst-sigsetjmp tst-setjmp-static
tests-static := tst-setjmp-static
They should be replaced by something like
tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
tst-sigsetjmp
tests-static-add := tst-setjmp-static
> I have additionally checked that:
>
> * touch libc.a => next invocation `make -r -C ~/Dev/glibc/libio objdir=$PWD check -j 20` will rebuild the static tests
> * touch libc.so => next invocation `make -r -C ~/Dev/glibc/libio objdir=$PWD check -j 20` will rebuild the dynamic tests
> * rm libio/tst-cleanup-default-cmp.out => next invocation `make -r -C ~/Dev/glibc/libio objdir=$PWD check -j 20` will rerun the single test
>
> >If you want to add a separate static source, you can submit a separate patch
> >to address these 2 issues together.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-05 20:35 ` H.J. Lu
@ 2021-04-05 21:03 ` Fangrui Song
2021-04-05 21:58 ` H.J. Lu
0 siblings, 1 reply; 40+ messages in thread
From: Fangrui Song @ 2021-04-05 21:03 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-04-05, H.J. Lu wrote:
>On Mon, Apr 5, 2021 at 11:17 AM Fangrui Song <maskray@google.com> wrote:
>>
>> On 2021-04-04, H.J. Lu wrote:
>> >On Sat, Apr 3, 2021 at 2:57 PM Fangrui Song <maskray@google.com> wrote:
>> >>
>> >> On 2021-04-03, H.J. Lu wrote:
>> >> >On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
>> >> >>
>> >> >>
>> >> >> On 2021-04-02, H.J. Lu wrote:
>> >> >> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
>> >> >> >>
>> >> >> >> On 2021-04-01, H.J. Lu wrote:
>> >> >> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
>> >> >> >> >>
>> >> >> >> >> 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).
>> >> >> >> >> ---
>> >> >> >> >> Changes in v1 -> v2:
>> >> >> >> >> * Define attribute_used_retain_section
>> >> >> >> >> Changes in v2 -> v3:
>> >> >> >> >> * Use attribute_used_retain instead attribute_used_retain_section
>> >> >> >> >> Changes in v3 -> v4:
>> >> >> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
>> >> >> >> >> Changes in v4 -> v5:
>> >> >> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
>> >> >> >> >> * Rename *gcc_retain* to *gnu_retain*
>> >> >> >> >> ---
>> >> >> >> >> config.h.in | 3 +++
>> >> >> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
>> >> >> >> >> configure.ac | 21 +++++++++++++++
>> >> >> >> >> include/libc-symbols.h | 14 +++++++---
>> >> >> >> >> libio/Makefile | 32 +++++++++++++++++++++++
>> >> >> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
>> >> >> >> >> libio/tst-cleanup.exp | 1 +
>> >> >> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
>> >> >> >> >> create mode 100644 libio/tst-cleanup.c
>> >> >> >> >> create mode 100644 libio/tst-cleanup.exp
>> >> >> >> >>
>> >> >> >> >> diff --git a/config.h.in b/config.h.in
>> >> >> >> >> index ca1547ae67..96a08c7757 100644
>> >> >> >> >> --- a/config.h.in
>> >> >> >> >> +++ b/config.h.in
>> >> >> >> >> @@ -187,6 +187,9 @@
>> >> >> >> >> /* Define if gcc supports attribute ifunc. */
>> >> >> >> >> #undef HAVE_GCC_IFUNC
>> >> >> >> >>
>> >> >> >> >> +/* Define if CC supports attribute retain. */
>> >> >> >> >> +#undef HAVE_GNU_RETAIN
>> >> >> >> >> +
>> >> >> >> >> /* Define if the linker defines __ehdr_start. */
>> >> >> >> >> #undef HAVE_EHDR_START
>> >> >> >> >>
>> >> >> >> >> diff --git a/configure b/configure
>> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
>> >> >> >> >> --- a/configure
>> >> >> >> >> +++ b/configure
>> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
>> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> >> >> >> @@ -5871,6 +5896,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
>> >> >> >> >> 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],
>> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> >> >> >> index 546fc26a7b..127ea656c2 100644
>> >> >> >> >> --- a/include/libc-symbols.h
>> >> >> >> >> +++ b/include/libc-symbols.h
>> >> >> >> >> @@ -352,6 +352,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. */
>> >> >> >> >> @@ -367,12 +373,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
>> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> >> >> >> index 12ce41038f..c9c232ebc2 100644
>> >> >> >> >> --- a/libio/Makefile
>> >> >> >> >> +++ b/libio/Makefile
>> >> >> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
>> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> >> >> >> $(objpfx)tst-bz24228-mem.out
>> >> >> >> >> endif
>> >> >> >> >> +
>> >> >> >> >> +tests += tst-cleanup-default
>> >> >> >> >> +tests-static += tst-cleanup-default
>> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
>> >> >> >> >
>> >> >> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
>> >> >> >>
>> >> >> >> Added.
>> >> >> >>
>> >> >> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
>> >> >> >> >> +
>> >> >> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
>> >> >> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> >> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
>> >> >> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
>> >> >> >> >
>> >> >> >> >Same here.
>> >> >> >>
>> >> >> >> Added.
>> >> >> >>
>> >> >> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
>> >> >> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
>> >> >> >> >> +endif
>> >> >> >> >> endif
>> >> >> >> >>
>> >> >> >> >> include ../Rules
>> >> >> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> >> >> >> endif
>> >> >> >> >>
>> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >> +
>> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >> +
>> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >>
>> >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> >> >> >> >> $(common-objpfx)libio/; \
>> >> >> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> >> >> >> >> new file mode 100644
>> >> >> >> >> index 0000000000..7f0a34a91e
>> >> >> >> >> --- /dev/null
>> >> >> >> >> +++ b/libio/tst-cleanup.c
>> >> >> >> >> @@ -0,0 +1,33 @@
>> >> >> >> >
>> >> >> >> >Please add a comment saying that test --gc-sections.
>> >> >> >>
>> >> >> >> OK, added.
>> >> >> >>
>> >> >> >> >> +/* 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. */
>> >> >> >> >> +
>> >> >> >> >> +#include <stdio.h>
>> >> >> >> >> +#include <stdlib.h>
>> >> >> >> >> +
>> >> >> >> >> +void
>> >> >> >> >> +hook (void)
>> >> >> >> >> +{
>> >> >> >> >> + puts ("hello");
>> >> >> >> >> +}
>> >> >> >> >> +
>> >> >> >> >> +int
>> >> >> >> >> +main (void)
>> >> >> >> >> +{
>> >> >> >> >> + atexit (hook);
>> >> >> >> >> +}
>> >> >> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> >> >> >> >> new file mode 100644
>> >> >> >> >> index 0000000000..ce01362503
>> >> >> >> >> --- /dev/null
>> >> >> >> >> +++ b/libio/tst-cleanup.exp
>> >> >> >> >> @@ -0,0 +1 @@
>> >> >> >> >> +hello
>> >> >> >> >> --
>> >> >> >> >> 2.31.0.291.g576ba9dcdaf-goog
>> >> >> >> >>
>> >> >> >> >
>> >> >> >>
>> >> >> >> diff --git a/config.h.in b/config.h.in
>> >> >> >> index ca1547ae67..96a08c7757 100644
>> >> >> >> --- a/config.h.in
>> >> >> >> +++ b/config.h.in
>> >> >> >> @@ -187,6 +187,9 @@
>> >> >> >> /* Define if gcc supports attribute ifunc. */
>> >> >> >> #undef HAVE_GCC_IFUNC
>> >> >> >>
>> >> >> >> +/* Define if CC supports attribute retain. */
>> >> >> >> +#undef HAVE_GNU_RETAIN
>> >> >> >> +
>> >> >> >> /* Define if the linker defines __ehdr_start. */
>> >> >> >> #undef HAVE_EHDR_START
>> >> >> >>
>> >> >> >> diff --git a/configure b/configure
>> >> >> >> index fcf43bf7de..e64b7f8efe 100755
>> >> >> >> --- a/configure
>> >> >> >> +++ b/configure
>> >> >> >> @@ -4105,6 +4105,31 @@ fi
>> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> >> >> @@ -5871,6 +5896,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
>> >> >> >> 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],
>> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> >> >> index 546fc26a7b..127ea656c2 100644
>> >> >> >> --- a/include/libc-symbols.h
>> >> >> >> +++ b/include/libc-symbols.h
>> >> >> >> @@ -352,6 +352,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. */
>> >> >> >> @@ -367,12 +373,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
>> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> >> >> index 12ce41038f..ad0d53bb49 100644
>> >> >> >> --- a/libio/Makefile
>> >> >> >> +++ b/libio/Makefile
>> >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
>> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> >> >> $(objpfx)tst-bz24228-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
>> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> >> >> endif
>> >> >> >>
>> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> >> >> + $(compile.c) -o $@
>> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
>> >> >> >> + $(compile.c) -o $@
>> >> >> >> +
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> >> >> + $(compile.c) -o $@
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
>> >> >> >> + $(compile.c) -o $@
>> >> >> >
>> >> >> >Please add a separate .c file for each test to get the correct dependency.
>> >> >>
>> >> >> Changed this block to:
>> >> >>
>> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> >> endif
>> >> >>
>> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
>> >> >> + cp $< $@
>> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
>> >> >> + cp $< $@
>> >> >> +
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> >> + $(compile.c) -o $@
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
>> >> >> + cp $< $@
>> >> >> +
>> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
>> >> >> + cp $< $@
>> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
>> >> >> + cmp $^ > $@; \
>> >> >> + $(evaluate-test)
>> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
>> >> >> + cp $< $@
>> >> >> +
>> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> >> >> $(common-objpfx)libio/; \
>> >> >>
>> >> >
>> >> >"make clean" doesn't remove the generated files. The standard way in glibc
>> >> >is to add a *-static.c source.
>> >>
>> >> I'll use .INTERMEDIATE and $(eval $(call ..))
>> >>
>> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> index 12ce41038f..a9b44f04df 100644
>> >> --- a/libio/Makefile
>> >> +++ b/libio/Makefile
>> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
>> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> $(objpfx)tst-bz24228-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
>> >> @@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> $(objpfx)tst-wfile-sync.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)
>> >> +$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
>> >> + cp $$< $$@
>> >> +.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
>> >> +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/; \
>> >
>> >There are 2 issues with static tests:
>> >
>> >1. A separate static source is needed.
>>
>> .INTERMEDIATE perfectly solves the lingering copied source issue.
>> I don't see lingering libio/tst-cleanup-*.c
>
>I was referring to
>
>elf/tst-array1-static.c
>elf/tst-array5-static.c
>elf/tst-dl-iter-static.c
>elf/tst-dst-static.c
>elf/tst-leaks1-static.c
>elf/tst-libc_dlvsym-static.c
>elf/tst-linkall-static.c
>elf/tst-ptrguard1-static.c
>elf/tst-single_threaded-pthread-static.c
>elf/tst-single_threaded-static.c
>elf/tst-stackguard1-static.c
>elf/tst-tls1-static.c
>elf/tst-tls2-static.c
>elf/tst-tls9-static.c
>elf/tst-tlsalign-extern-static.c
>elf/tst-tlsalign-static.c
>gmon/tst-gmon-static.c
>gmon/tst-profile-static.c
>localedata/bug-setlocale1-static.c
>localedata/tst-langinfo-newlocale-static.c
>localedata/tst-langinfo-setlocale-static.c
>localedata/tst-langinfo-static.c
>malloc/tst-malloc-usable-static.c
>math/test-fpucw-ieee-static.c
>math/test-fpucw-static.c
>math/test-signgam-uchar-init-static.c
>math/test-signgam-uchar-static.c
>math/test-signgam-uint-init-static.c
>math/test-signgam-uint-static.c
>math/test-signgam-ullong-init-static.c
>math/test-signgam-ullong-static.c
>nptl/tst-mutex8-static.c
>nptl/tst-mutexpi8-static.c
>nptl/tst-sem11-static.c
>nptl/tst-sem12-static.c
>nptl/tst-setuid1-static.c
>nptl/tst-stackguard1-static.c
>nss/tst-nss-static.c
>posix/tst-exec-static.c
>posix/tst-spawn-static.c
>setjmp/tst-setjmp-static.c
>
>> >2. We need to add the static test to both tests and tests-static.
>>
>> tests-static suffices. I have checked some tests-static usage in other
>> directories.
>
>There are
>
>tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> tst-sigsetjmp tst-setjmp-static
>tests-static := tst-setjmp-static
>
>They should be replaced by something like
>
>tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> tst-sigsetjmp
>tests-static-add := tst-setjmp-static
Re-checking, the tst-cleanup* targets are in tests-special so `make tests` will build them.
If a tests-static target is not in tests-internal/tests-special, looks like it needs to be in tests.
As is, I think my usage is correct.
>> I have additionally checked that:
>>
>> * touch libc.a => next invocation `make -r -C ~/Dev/glibc/libio objdir=$PWD check -j 20` will rebuild the static tests
>> * touch libc.so => next invocation `make -r -C ~/Dev/glibc/libio objdir=$PWD check -j 20` will rebuild the dynamic tests
>> * rm libio/tst-cleanup-default-cmp.out => next invocation `make -r -C ~/Dev/glibc/libio objdir=$PWD check -j 20` will rerun the single test
>>
>> >If you want to add a separate static source, you can submit a separate patch
>> >to address these 2 issues together.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-05 21:03 ` Fangrui Song
@ 2021-04-05 21:58 ` H.J. Lu
2021-04-06 21:46 ` Fangrui Song
0 siblings, 1 reply; 40+ messages in thread
From: H.J. Lu @ 2021-04-05 21:58 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Mon, Apr 5, 2021 at 2:03 PM Fangrui Song <maskray@google.com> wrote:
>
> On 2021-04-05, H.J. Lu wrote:
> >On Mon, Apr 5, 2021 at 11:17 AM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2021-04-04, H.J. Lu wrote:
> >> >On Sat, Apr 3, 2021 at 2:57 PM Fangrui Song <maskray@google.com> wrote:
> >> >>
> >> >> On 2021-04-03, H.J. Lu wrote:
> >> >> >On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
> >> >> >>
> >> >> >>
> >> >> >> On 2021-04-02, H.J. Lu wrote:
> >> >> >> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >> >>
> >> >> >> >> On 2021-04-01, H.J. Lu wrote:
> >> >> >> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >> >> >>
> >> >> >> >> >> 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).
> >> >> >> >> >> ---
> >> >> >> >> >> Changes in v1 -> v2:
> >> >> >> >> >> * Define attribute_used_retain_section
> >> >> >> >> >> Changes in v2 -> v3:
> >> >> >> >> >> * Use attribute_used_retain instead attribute_used_retain_section
> >> >> >> >> >> Changes in v3 -> v4:
> >> >> >> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> >> >> >> >> >> Changes in v4 -> v5:
> >> >> >> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> >> >> >> >> >> * Rename *gcc_retain* to *gnu_retain*
> >> >> >> >> >> ---
> >> >> >> >> >> config.h.in | 3 +++
> >> >> >> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> >> >> >> >> >> configure.ac | 21 +++++++++++++++
> >> >> >> >> >> include/libc-symbols.h | 14 +++++++---
> >> >> >> >> >> libio/Makefile | 32 +++++++++++++++++++++++
> >> >> >> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> >> >> >> >> >> libio/tst-cleanup.exp | 1 +
> >> >> >> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
> >> >> >> >> >> create mode 100644 libio/tst-cleanup.c
> >> >> >> >> >> create mode 100644 libio/tst-cleanup.exp
> >> >> >> >> >>
> >> >> >> >> >> diff --git a/config.h.in b/config.h.in
> >> >> >> >> >> index ca1547ae67..96a08c7757 100644
> >> >> >> >> >> --- a/config.h.in
> >> >> >> >> >> +++ b/config.h.in
> >> >> >> >> >> @@ -187,6 +187,9 @@
> >> >> >> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> >> >> >> #undef HAVE_GCC_IFUNC
> >> >> >> >> >>
> >> >> >> >> >> +/* Define if CC supports attribute retain. */
> >> >> >> >> >> +#undef HAVE_GNU_RETAIN
> >> >> >> >> >> +
> >> >> >> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> >> >> >> #undef HAVE_EHDR_START
> >> >> >> >> >>
> >> >> >> >> >> diff --git a/configure b/configure
> >> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> >> >> >> --- a/configure
> >> >> >> >> >> +++ b/configure
> >> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> >> >> >> @@ -5871,6 +5896,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
> >> >> >> >> >> 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],
> >> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> >> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> >> >> >> --- a/include/libc-symbols.h
> >> >> >> >> >> +++ b/include/libc-symbols.h
> >> >> >> >> >> @@ -352,6 +352,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. */
> >> >> >> >> >> @@ -367,12 +373,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
> >> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> >> >> index 12ce41038f..c9c232ebc2 100644
> >> >> >> >> >> --- a/libio/Makefile
> >> >> >> >> >> +++ b/libio/Makefile
> >> >> >> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> >> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> >> >> $(objpfx)tst-bz24228-mem.out
> >> >> >> >> >> endif
> >> >> >> >> >> +
> >> >> >> >> >> +tests += tst-cleanup-default
> >> >> >> >> >> +tests-static += tst-cleanup-default
> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> >> >> >> >> >
> >> >> >> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
> >> >> >> >>
> >> >> >> >> Added.
> >> >> >> >>
> >> >> >> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> >> >> >> >> >> +
> >> >> >> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> >> >> >> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> >> >> >> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> >> >> >> >> >
> >> >> >> >> >Same here.
> >> >> >> >>
> >> >> >> >> Added.
> >> >> >> >>
> >> >> >> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >> >> >> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> >> >> >> >> >> +endif
> >> >> >> >> >> endif
> >> >> >> >> >>
> >> >> >> >> >> include ../Rules
> >> >> >> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> >> >> endif
> >> >> >> >> >>
> >> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> +
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> +
> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >>
> >> >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> >> >> >> $(common-objpfx)libio/; \
> >> >> >> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> >> >> >> >> >> new file mode 100644
> >> >> >> >> >> index 0000000000..7f0a34a91e
> >> >> >> >> >> --- /dev/null
> >> >> >> >> >> +++ b/libio/tst-cleanup.c
> >> >> >> >> >> @@ -0,0 +1,33 @@
> >> >> >> >> >
> >> >> >> >> >Please add a comment saying that test --gc-sections.
> >> >> >> >>
> >> >> >> >> OK, added.
> >> >> >> >>
> >> >> >> >> >> +/* 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. */
> >> >> >> >> >> +
> >> >> >> >> >> +#include <stdio.h>
> >> >> >> >> >> +#include <stdlib.h>
> >> >> >> >> >> +
> >> >> >> >> >> +void
> >> >> >> >> >> +hook (void)
> >> >> >> >> >> +{
> >> >> >> >> >> + puts ("hello");
> >> >> >> >> >> +}
> >> >> >> >> >> +
> >> >> >> >> >> +int
> >> >> >> >> >> +main (void)
> >> >> >> >> >> +{
> >> >> >> >> >> + atexit (hook);
> >> >> >> >> >> +}
> >> >> >> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> >> >> >> >> >> new file mode 100644
> >> >> >> >> >> index 0000000000..ce01362503
> >> >> >> >> >> --- /dev/null
> >> >> >> >> >> +++ b/libio/tst-cleanup.exp
> >> >> >> >> >> @@ -0,0 +1 @@
> >> >> >> >> >> +hello
> >> >> >> >> >> --
> >> >> >> >> >> 2.31.0.291.g576ba9dcdaf-goog
> >> >> >> >> >>
> >> >> >> >> >
> >> >> >> >>
> >> >> >> >> diff --git a/config.h.in b/config.h.in
> >> >> >> >> index ca1547ae67..96a08c7757 100644
> >> >> >> >> --- a/config.h.in
> >> >> >> >> +++ b/config.h.in
> >> >> >> >> @@ -187,6 +187,9 @@
> >> >> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> >> >> #undef HAVE_GCC_IFUNC
> >> >> >> >>
> >> >> >> >> +/* Define if CC supports attribute retain. */
> >> >> >> >> +#undef HAVE_GNU_RETAIN
> >> >> >> >> +
> >> >> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> >> >> #undef HAVE_EHDR_START
> >> >> >> >>
> >> >> >> >> diff --git a/configure b/configure
> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> >> >> --- a/configure
> >> >> >> >> +++ b/configure
> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> >> >> @@ -5871,6 +5896,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
> >> >> >> >> 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],
> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> >> >> --- a/include/libc-symbols.h
> >> >> >> >> +++ b/include/libc-symbols.h
> >> >> >> >> @@ -352,6 +352,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. */
> >> >> >> >> @@ -367,12 +373,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
> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> >> index 12ce41038f..ad0d53bb49 100644
> >> >> >> >> --- a/libio/Makefile
> >> >> >> >> +++ b/libio/Makefile
> >> >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> >> $(objpfx)tst-bz24228-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
> >> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> >> endif
> >> >> >> >>
> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> +
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >
> >> >> >> >Please add a separate .c file for each test to get the correct dependency.
> >> >> >>
> >> >> >> Changed this block to:
> >> >> >>
> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> endif
> >> >> >>
> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
> >> >> >> + cp $< $@
> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
> >> >> >> + cp $< $@
> >> >> >> +
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> + $(compile.c) -o $@
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
> >> >> >> + cp $< $@
> >> >> >> +
> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
> >> >> >> + cp $< $@
> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
> >> >> >> + cmp $^ > $@; \
> >> >> >> + $(evaluate-test)
> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
> >> >> >> + cp $< $@
> >> >> >> +
> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> >> $(common-objpfx)libio/; \
> >> >> >>
> >> >> >
> >> >> >"make clean" doesn't remove the generated files. The standard way in glibc
> >> >> >is to add a *-static.c source.
> >> >>
> >> >> I'll use .INTERMEDIATE and $(eval $(call ..))
> >> >>
> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> index 12ce41038f..a9b44f04df 100644
> >> >> --- a/libio/Makefile
> >> >> +++ b/libio/Makefile
> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> $(objpfx)tst-bz24228-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
> >> >> @@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> $(objpfx)tst-wfile-sync.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)
> >> >> +$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
> >> >> + cp $$< $$@
> >> >> +.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
> >> >> +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/; \
> >> >
> >> >There are 2 issues with static tests:
> >> >
> >> >1. A separate static source is needed.
> >>
> >> .INTERMEDIATE perfectly solves the lingering copied source issue.
> >> I don't see lingering libio/tst-cleanup-*.c
> >
> >I was referring to
> >
> >elf/tst-array1-static.c
> >elf/tst-array5-static.c
> >elf/tst-dl-iter-static.c
> >elf/tst-dst-static.c
> >elf/tst-leaks1-static.c
> >elf/tst-libc_dlvsym-static.c
> >elf/tst-linkall-static.c
> >elf/tst-ptrguard1-static.c
> >elf/tst-single_threaded-pthread-static.c
> >elf/tst-single_threaded-static.c
> >elf/tst-stackguard1-static.c
> >elf/tst-tls1-static.c
> >elf/tst-tls2-static.c
> >elf/tst-tls9-static.c
> >elf/tst-tlsalign-extern-static.c
> >elf/tst-tlsalign-static.c
> >gmon/tst-gmon-static.c
> >gmon/tst-profile-static.c
> >localedata/bug-setlocale1-static.c
> >localedata/tst-langinfo-newlocale-static.c
> >localedata/tst-langinfo-setlocale-static.c
> >localedata/tst-langinfo-static.c
> >malloc/tst-malloc-usable-static.c
> >math/test-fpucw-ieee-static.c
> >math/test-fpucw-static.c
> >math/test-signgam-uchar-init-static.c
> >math/test-signgam-uchar-static.c
> >math/test-signgam-uint-init-static.c
> >math/test-signgam-uint-static.c
> >math/test-signgam-ullong-init-static.c
> >math/test-signgam-ullong-static.c
> >nptl/tst-mutex8-static.c
> >nptl/tst-mutexpi8-static.c
> >nptl/tst-sem11-static.c
> >nptl/tst-sem12-static.c
> >nptl/tst-setuid1-static.c
> >nptl/tst-stackguard1-static.c
> >nss/tst-nss-static.c
> >posix/tst-exec-static.c
> >posix/tst-spawn-static.c
> >setjmp/tst-setjmp-static.c
> >
> >> >2. We need to add the static test to both tests and tests-static.
> >>
> >> tests-static suffices. I have checked some tests-static usage in other
> >> directories.
> >
> >There are
> >
> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> > tst-sigsetjmp tst-setjmp-static
> >tests-static := tst-setjmp-static
> >
> >They should be replaced by something like
> >
> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> > tst-sigsetjmp
> >tests-static-add := tst-setjmp-static
>
> Re-checking, the tst-cleanup* targets are in tests-special so `make tests` will build them.
> If a tests-static target is not in tests-internal/tests-special, looks like it needs to be in tests.
>
> As is, I think my usage is correct.
>
The current glibc convention is to use
[hjl@gnu-cfl-2 x86-glibc]$ cat elf/tst-tls9-static.c
#include "tst-tls9.c"
[hjl@gnu-cfl-2 x86-glibc]$
to test both dynamic and static libc. If we want to use a single
source, we should create
a framework to cover all such tests.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-05 21:58 ` H.J. Lu
@ 2021-04-06 21:46 ` Fangrui Song
2021-04-09 22:36 ` Fāng-ruì Sòng
2021-04-16 13:00 ` H.J. Lu
0 siblings, 2 replies; 40+ messages in thread
From: Fangrui Song @ 2021-04-06 21:46 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On 2021-04-05, H.J. Lu wrote:
>On Mon, Apr 5, 2021 at 2:03 PM Fangrui Song <maskray@google.com> wrote:
>>
>> On 2021-04-05, H.J. Lu wrote:
>> >On Mon, Apr 5, 2021 at 11:17 AM Fangrui Song <maskray@google.com> wrote:
>> >>
>> >> On 2021-04-04, H.J. Lu wrote:
>> >> >On Sat, Apr 3, 2021 at 2:57 PM Fangrui Song <maskray@google.com> wrote:
>> >> >>
>> >> >> On 2021-04-03, H.J. Lu wrote:
>> >> >> >On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
>> >> >> >>
>> >> >> >>
>> >> >> >> On 2021-04-02, H.J. Lu wrote:
>> >> >> >> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
>> >> >> >> >>
>> >> >> >> >> On 2021-04-01, H.J. Lu wrote:
>> >> >> >> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
>> >> >> >> >> >>
>> >> >> >> >> >> 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).
>> >> >> >> >> >> ---
>> >> >> >> >> >> Changes in v1 -> v2:
>> >> >> >> >> >> * Define attribute_used_retain_section
>> >> >> >> >> >> Changes in v2 -> v3:
>> >> >> >> >> >> * Use attribute_used_retain instead attribute_used_retain_section
>> >> >> >> >> >> Changes in v3 -> v4:
>> >> >> >> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
>> >> >> >> >> >> Changes in v4 -> v5:
>> >> >> >> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
>> >> >> >> >> >> * Rename *gcc_retain* to *gnu_retain*
>> >> >> >> >> >> ---
>> >> >> >> >> >> config.h.in | 3 +++
>> >> >> >> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
>> >> >> >> >> >> configure.ac | 21 +++++++++++++++
>> >> >> >> >> >> include/libc-symbols.h | 14 +++++++---
>> >> >> >> >> >> libio/Makefile | 32 +++++++++++++++++++++++
>> >> >> >> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
>> >> >> >> >> >> libio/tst-cleanup.exp | 1 +
>> >> >> >> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
>> >> >> >> >> >> create mode 100644 libio/tst-cleanup.c
>> >> >> >> >> >> create mode 100644 libio/tst-cleanup.exp
>> >> >> >> >> >>
>> >> >> >> >> >> diff --git a/config.h.in b/config.h.in
>> >> >> >> >> >> index ca1547ae67..96a08c7757 100644
>> >> >> >> >> >> --- a/config.h.in
>> >> >> >> >> >> +++ b/config.h.in
>> >> >> >> >> >> @@ -187,6 +187,9 @@
>> >> >> >> >> >> /* Define if gcc supports attribute ifunc. */
>> >> >> >> >> >> #undef HAVE_GCC_IFUNC
>> >> >> >> >> >>
>> >> >> >> >> >> +/* Define if CC supports attribute retain. */
>> >> >> >> >> >> +#undef HAVE_GNU_RETAIN
>> >> >> >> >> >> +
>> >> >> >> >> >> /* Define if the linker defines __ehdr_start. */
>> >> >> >> >> >> #undef HAVE_EHDR_START
>> >> >> >> >> >>
>> >> >> >> >> >> diff --git a/configure b/configure
>> >> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
>> >> >> >> >> >> --- a/configure
>> >> >> >> >> >> +++ b/configure
>> >> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
>> >> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> >> >> >> >> @@ -5871,6 +5896,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
>> >> >> >> >> >> 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],
>> >> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> >> >> >> >> index 546fc26a7b..127ea656c2 100644
>> >> >> >> >> >> --- a/include/libc-symbols.h
>> >> >> >> >> >> +++ b/include/libc-symbols.h
>> >> >> >> >> >> @@ -352,6 +352,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. */
>> >> >> >> >> >> @@ -367,12 +373,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
>> >> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> >> >> >> >> index 12ce41038f..c9c232ebc2 100644
>> >> >> >> >> >> --- a/libio/Makefile
>> >> >> >> >> >> +++ b/libio/Makefile
>> >> >> >> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
>> >> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> >> >> >> >> $(objpfx)tst-bz24228-mem.out
>> >> >> >> >> >> endif
>> >> >> >> >> >> +
>> >> >> >> >> >> +tests += tst-cleanup-default
>> >> >> >> >> >> +tests-static += tst-cleanup-default
>> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
>> >> >> >> >> >
>> >> >> >> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
>> >> >> >> >>
>> >> >> >> >> Added.
>> >> >> >> >>
>> >> >> >> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
>> >> >> >> >> >> +
>> >> >> >> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
>> >> >> >> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> >> >> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
>> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
>> >> >> >> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
>> >> >> >> >> >
>> >> >> >> >> >Same here.
>> >> >> >> >>
>> >> >> >> >> Added.
>> >> >> >> >>
>> >> >> >> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
>> >> >> >> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
>> >> >> >> >> >> +endif
>> >> >> >> >> >> endif
>> >> >> >> >> >>
>> >> >> >> >> >> include ../Rules
>> >> >> >> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> >> >> >> >> endif
>> >> >> >> >> >>
>> >> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >> >> +
>> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >> >> +
>> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> >> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
>> >> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >> >>
>> >> >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> >> >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> >> >> >> >> >> $(common-objpfx)libio/; \
>> >> >> >> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
>> >> >> >> >> >> new file mode 100644
>> >> >> >> >> >> index 0000000000..7f0a34a91e
>> >> >> >> >> >> --- /dev/null
>> >> >> >> >> >> +++ b/libio/tst-cleanup.c
>> >> >> >> >> >> @@ -0,0 +1,33 @@
>> >> >> >> >> >
>> >> >> >> >> >Please add a comment saying that test --gc-sections.
>> >> >> >> >>
>> >> >> >> >> OK, added.
>> >> >> >> >>
>> >> >> >> >> >> +/* 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. */
>> >> >> >> >> >> +
>> >> >> >> >> >> +#include <stdio.h>
>> >> >> >> >> >> +#include <stdlib.h>
>> >> >> >> >> >> +
>> >> >> >> >> >> +void
>> >> >> >> >> >> +hook (void)
>> >> >> >> >> >> +{
>> >> >> >> >> >> + puts ("hello");
>> >> >> >> >> >> +}
>> >> >> >> >> >> +
>> >> >> >> >> >> +int
>> >> >> >> >> >> +main (void)
>> >> >> >> >> >> +{
>> >> >> >> >> >> + atexit (hook);
>> >> >> >> >> >> +}
>> >> >> >> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
>> >> >> >> >> >> new file mode 100644
>> >> >> >> >> >> index 0000000000..ce01362503
>> >> >> >> >> >> --- /dev/null
>> >> >> >> >> >> +++ b/libio/tst-cleanup.exp
>> >> >> >> >> >> @@ -0,0 +1 @@
>> >> >> >> >> >> +hello
>> >> >> >> >> >> --
>> >> >> >> >> >> 2.31.0.291.g576ba9dcdaf-goog
>> >> >> >> >> >>
>> >> >> >> >> >
>> >> >> >> >>
>> >> >> >> >> diff --git a/config.h.in b/config.h.in
>> >> >> >> >> index ca1547ae67..96a08c7757 100644
>> >> >> >> >> --- a/config.h.in
>> >> >> >> >> +++ b/config.h.in
>> >> >> >> >> @@ -187,6 +187,9 @@
>> >> >> >> >> /* Define if gcc supports attribute ifunc. */
>> >> >> >> >> #undef HAVE_GCC_IFUNC
>> >> >> >> >>
>> >> >> >> >> +/* Define if CC supports attribute retain. */
>> >> >> >> >> +#undef HAVE_GNU_RETAIN
>> >> >> >> >> +
>> >> >> >> >> /* Define if the linker defines __ehdr_start. */
>> >> >> >> >> #undef HAVE_EHDR_START
>> >> >> >> >>
>> >> >> >> >> diff --git a/configure b/configure
>> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
>> >> >> >> >> --- a/configure
>> >> >> >> >> +++ b/configure
>> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
>> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
>> >> >> >> >> @@ -5871,6 +5896,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
>> >> >> >> >> 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],
>> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
>> >> >> >> >> index 546fc26a7b..127ea656c2 100644
>> >> >> >> >> --- a/include/libc-symbols.h
>> >> >> >> >> +++ b/include/libc-symbols.h
>> >> >> >> >> @@ -352,6 +352,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. */
>> >> >> >> >> @@ -367,12 +373,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
>> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> >> >> >> index 12ce41038f..ad0d53bb49 100644
>> >> >> >> >> --- a/libio/Makefile
>> >> >> >> >> +++ b/libio/Makefile
>> >> >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
>> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> >> >> >> $(objpfx)tst-bz24228-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
>> >> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> >> >> >> endif
>> >> >> >> >>
>> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
>> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
>> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >> +
>> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> >> >> >> >> + cmp $^ > $@; \
>> >> >> >> >> + $(evaluate-test)
>> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
>> >> >> >> >> + $(compile.c) -o $@
>> >> >> >> >
>> >> >> >> >Please add a separate .c file for each test to get the correct dependency.
>> >> >> >>
>> >> >> >> Changed this block to:
>> >> >> >>
>> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
>> >> >> >> endif
>> >> >> >>
>> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
>> >> >> >> + cp $< $@
>> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
>> >> >> >> + cp $< $@
>> >> >> >> +
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
>> >> >> >> + $(compile.c) -o $@
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
>> >> >> >> + cp $< $@
>> >> >> >> +
>> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
>> >> >> >> + cp $< $@
>> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
>> >> >> >> + cmp $^ > $@; \
>> >> >> >> + $(evaluate-test)
>> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
>> >> >> >> + cp $< $@
>> >> >> >> +
>> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
>> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
>> >> >> >> $(common-objpfx)libio/; \
>> >> >> >>
>> >> >> >
>> >> >> >"make clean" doesn't remove the generated files. The standard way in glibc
>> >> >> >is to add a *-static.c source.
>> >> >>
>> >> >> I'll use .INTERMEDIATE and $(eval $(call ..))
>> >> >>
>> >> >> diff --git a/libio/Makefile b/libio/Makefile
>> >> >> index 12ce41038f..a9b44f04df 100644
>> >> >> --- a/libio/Makefile
>> >> >> +++ b/libio/Makefile
>> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
>> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
>> >> >> $(objpfx)tst-bz24228-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
>> >> >> @@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
>> >> >> $(objpfx)tst-wfile-sync.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)
>> >> >> +$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
>> >> >> + cp $$< $$@
>> >> >> +.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
>> >> >> +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/; \
>> >> >
>> >> >There are 2 issues with static tests:
>> >> >
>> >> >1. A separate static source is needed.
>> >>
>> >> .INTERMEDIATE perfectly solves the lingering copied source issue.
>> >> I don't see lingering libio/tst-cleanup-*.c
>> >
>> >I was referring to
>> >
>> >elf/tst-array1-static.c
>> >elf/tst-array5-static.c
>> >elf/tst-dl-iter-static.c
>> >elf/tst-dst-static.c
>> >elf/tst-leaks1-static.c
>> >elf/tst-libc_dlvsym-static.c
>> >elf/tst-linkall-static.c
>> >elf/tst-ptrguard1-static.c
>> >elf/tst-single_threaded-pthread-static.c
>> >elf/tst-single_threaded-static.c
>> >elf/tst-stackguard1-static.c
>> >elf/tst-tls1-static.c
>> >elf/tst-tls2-static.c
>> >elf/tst-tls9-static.c
>> >elf/tst-tlsalign-extern-static.c
>> >elf/tst-tlsalign-static.c
>> >gmon/tst-gmon-static.c
>> >gmon/tst-profile-static.c
>> >localedata/bug-setlocale1-static.c
>> >localedata/tst-langinfo-newlocale-static.c
>> >localedata/tst-langinfo-setlocale-static.c
>> >localedata/tst-langinfo-static.c
>> >malloc/tst-malloc-usable-static.c
>> >math/test-fpucw-ieee-static.c
>> >math/test-fpucw-static.c
>> >math/test-signgam-uchar-init-static.c
>> >math/test-signgam-uchar-static.c
>> >math/test-signgam-uint-init-static.c
>> >math/test-signgam-uint-static.c
>> >math/test-signgam-ullong-init-static.c
>> >math/test-signgam-ullong-static.c
>> >nptl/tst-mutex8-static.c
>> >nptl/tst-mutexpi8-static.c
>> >nptl/tst-sem11-static.c
>> >nptl/tst-sem12-static.c
>> >nptl/tst-setuid1-static.c
>> >nptl/tst-stackguard1-static.c
>> >nss/tst-nss-static.c
>> >posix/tst-exec-static.c
>> >posix/tst-spawn-static.c
>> >setjmp/tst-setjmp-static.c
>> >
>> >> >2. We need to add the static test to both tests and tests-static.
>> >>
>> >> tests-static suffices. I have checked some tests-static usage in other
>> >> directories.
>> >
>> >There are
>> >
>> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
>> > tst-sigsetjmp tst-setjmp-static
>> >tests-static := tst-setjmp-static
>> >
>> >They should be replaced by something like
>> >
>> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
>> > tst-sigsetjmp
>> >tests-static-add := tst-setjmp-static
>>
>> Re-checking, the tst-cleanup* targets are in tests-special so `make tests` will build them.
>> If a tests-static target is not in tests-internal/tests-special, looks like it needs to be in tests.
>>
>> As is, I think my usage is correct.
>>
>
>The current glibc convention is to use
>
>[hjl@gnu-cfl-2 x86-glibc]$ cat elf/tst-tls9-static.c
>#include "tst-tls9.c"
>[hjl@gnu-cfl-2 x86-glibc]$
>
>to test both dynamic and static libc. If we want to use a single
>source, we should create
>a framework to cover all such tests.
OK. Dropped cp $< $@ and .INTERMEDIATE
From e937ae26a4a9a8ff6b1198f347f0b141a9285305 Mon Sep 17 00:00:00 2001
From: Fangrui Song <maskray@google.com>
Date: Tue, 6 Apr 2021 14:45:01 -0700
Subject: [PATCH] Set the retain attribute on _elf_set_element if CC supports
[BZ #27492]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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).
---
config.h.in | 3 ++
configure | 59 ++++++++++++++++++++++
configure.ac | 21 ++++++++
include/libc-symbols.h | 14 +++--
libio/Makefile | 28 ++++++++++
libio/tst-cleanup-default-static.c | 1 +
libio/tst-cleanup-default.c | 1 +
libio/tst-cleanup-nostart-stop-gc-static.c | 1 +
libio/tst-cleanup-nostart-stop-gc.c | 1 +
libio/tst-cleanup-start-stop-gc-static.c | 1 +
libio/tst-cleanup-start-stop-gc.c | 1 +
libio/tst-cleanup.c | 34 +++++++++++++
libio/tst-cleanup.exp | 1 +
13 files changed, 162 insertions(+), 4 deletions(-)
create mode 100644 libio/tst-cleanup-default-static.c
create mode 100644 libio/tst-cleanup-default.c
create mode 100644 libio/tst-cleanup-nostart-stop-gc-static.c
create mode 100644 libio/tst-cleanup-nostart-stop-gc.c
create mode 100644 libio/tst-cleanup-start-stop-gc-static.c
create mode 100644 libio/tst-cleanup-start-stop-gc.c
create mode 100644 libio/tst-cleanup.c
create mode 100644 libio/tst-cleanup.exp
diff --git a/config.h.in b/config.h.in
index ca1547ae67..96a08c7757 100644
--- a/config.h.in
+++ b/config.h.in
@@ -187,6 +187,9 @@
/* Define if gcc supports attribute ifunc. */
#undef HAVE_GCC_IFUNC
+/* Define if CC supports attribute retain. */
+#undef HAVE_GNU_RETAIN
+
/* Define if the linker defines __ehdr_start. */
#undef HAVE_EHDR_START
diff --git a/configure b/configure
index fcf43bf7de..e64b7f8efe 100755
--- a/configure
+++ b/configure
@@ -4105,6 +4105,31 @@ fi
$as_echo "$libc_cv_textrel_ifunc" >&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; }
@@ -5871,6 +5896,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
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],
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index 546fc26a7b..127ea656c2 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -352,6 +352,12 @@ for linking")
\f
*/
+#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. */
@@ -367,12 +373,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
diff --git a/libio/Makefile b/libio/Makefile
index 12ce41038f..ed0ce4ee81 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
$(objpfx)tst-bz24228-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
@@ -224,6 +244,14 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.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/; \
diff --git a/libio/tst-cleanup-default-static.c b/libio/tst-cleanup-default-static.c
new file mode 100644
index 0000000000..c39956e2a8
--- /dev/null
+++ b/libio/tst-cleanup-default-static.c
@@ -0,0 +1 @@
+#include "tst-cleanup.c"
diff --git a/libio/tst-cleanup-default.c b/libio/tst-cleanup-default.c
new file mode 100644
index 0000000000..c39956e2a8
--- /dev/null
+++ b/libio/tst-cleanup-default.c
@@ -0,0 +1 @@
+#include "tst-cleanup.c"
diff --git a/libio/tst-cleanup-nostart-stop-gc-static.c b/libio/tst-cleanup-nostart-stop-gc-static.c
new file mode 100644
index 0000000000..c39956e2a8
--- /dev/null
+++ b/libio/tst-cleanup-nostart-stop-gc-static.c
@@ -0,0 +1 @@
+#include "tst-cleanup.c"
diff --git a/libio/tst-cleanup-nostart-stop-gc.c b/libio/tst-cleanup-nostart-stop-gc.c
new file mode 100644
index 0000000000..c39956e2a8
--- /dev/null
+++ b/libio/tst-cleanup-nostart-stop-gc.c
@@ -0,0 +1 @@
+#include "tst-cleanup.c"
diff --git a/libio/tst-cleanup-start-stop-gc-static.c b/libio/tst-cleanup-start-stop-gc-static.c
new file mode 100644
index 0000000000..c39956e2a8
--- /dev/null
+++ b/libio/tst-cleanup-start-stop-gc-static.c
@@ -0,0 +1 @@
+#include "tst-cleanup.c"
diff --git a/libio/tst-cleanup-start-stop-gc.c b/libio/tst-cleanup-start-stop-gc.c
new file mode 100644
index 0000000000..c39956e2a8
--- /dev/null
+++ b/libio/tst-cleanup-start-stop-gc.c
@@ -0,0 +1 @@
+#include "tst-cleanup.c"
diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
new file mode 100644
index 0000000000..837feac164
--- /dev/null
+++ b/libio/tst-cleanup.c
@@ -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);
+}
diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
new file mode 100644
index 0000000000..ce01362503
--- /dev/null
+++ b/libio/tst-cleanup.exp
@@ -0,0 +1 @@
+hello
--
2.31.0.208.g409f899ff0-goog
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-06 21:46 ` Fangrui Song
@ 2021-04-09 22:36 ` Fāng-ruì Sòng
2021-04-16 3:51 ` Fāng-ruì Sòng
2021-04-16 13:00 ` H.J. Lu
1 sibling, 1 reply; 40+ messages in thread
From: Fāng-ruì Sòng @ 2021-04-09 22:36 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On Tue, Apr 6, 2021 at 2:46 PM Fangrui Song <maskray@google.com> wrote:
>
>
> On 2021-04-05, H.J. Lu wrote:
> >On Mon, Apr 5, 2021 at 2:03 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2021-04-05, H.J. Lu wrote:
> >> >On Mon, Apr 5, 2021 at 11:17 AM Fangrui Song <maskray@google.com> wrote:
> >> >>
> >> >> On 2021-04-04, H.J. Lu wrote:
> >> >> >On Sat, Apr 3, 2021 at 2:57 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >>
> >> >> >> On 2021-04-03, H.J. Lu wrote:
> >> >> >> >On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
> >> >> >> >>
> >> >> >> >>
> >> >> >> >> On 2021-04-02, H.J. Lu wrote:
> >> >> >> >> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >> >> >>
> >> >> >> >> >> On 2021-04-01, H.J. Lu wrote:
> >> >> >> >> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >> >> >> >>
> >> >> >> >> >> >> 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).
> >> >> >> >> >> >> ---
> >> >> >> >> >> >> Changes in v1 -> v2:
> >> >> >> >> >> >> * Define attribute_used_retain_section
> >> >> >> >> >> >> Changes in v2 -> v3:
> >> >> >> >> >> >> * Use attribute_used_retain instead attribute_used_retain_section
> >> >> >> >> >> >> Changes in v3 -> v4:
> >> >> >> >> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> >> >> >> >> >> >> Changes in v4 -> v5:
> >> >> >> >> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> >> >> >> >> >> >> * Rename *gcc_retain* to *gnu_retain*
> >> >> >> >> >> >> ---
> >> >> >> >> >> >> config.h.in | 3 +++
> >> >> >> >> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> >> >> >> >> >> >> configure.ac | 21 +++++++++++++++
> >> >> >> >> >> >> include/libc-symbols.h | 14 +++++++---
> >> >> >> >> >> >> libio/Makefile | 32 +++++++++++++++++++++++
> >> >> >> >> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> >> >> >> >> >> >> libio/tst-cleanup.exp | 1 +
> >> >> >> >> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
> >> >> >> >> >> >> create mode 100644 libio/tst-cleanup.c
> >> >> >> >> >> >> create mode 100644 libio/tst-cleanup.exp
> >> >> >> >> >> >>
> >> >> >> >> >> >> diff --git a/config.h.in b/config.h.in
> >> >> >> >> >> >> index ca1547ae67..96a08c7757 100644
> >> >> >> >> >> >> --- a/config.h.in
> >> >> >> >> >> >> +++ b/config.h.in
> >> >> >> >> >> >> @@ -187,6 +187,9 @@
> >> >> >> >> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> >> >> >> >> #undef HAVE_GCC_IFUNC
> >> >> >> >> >> >>
> >> >> >> >> >> >> +/* Define if CC supports attribute retain. */
> >> >> >> >> >> >> +#undef HAVE_GNU_RETAIN
> >> >> >> >> >> >> +
> >> >> >> >> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> >> >> >> >> #undef HAVE_EHDR_START
> >> >> >> >> >> >>
> >> >> >> >> >> >> diff --git a/configure b/configure
> >> >> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> >> >> >> >> --- a/configure
> >> >> >> >> >> >> +++ b/configure
> >> >> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> >> >> >> >> @@ -5871,6 +5896,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
> >> >> >> >> >> >> 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],
> >> >> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> >> >> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> >> >> >> >> --- a/include/libc-symbols.h
> >> >> >> >> >> >> +++ b/include/libc-symbols.h
> >> >> >> >> >> >> @@ -352,6 +352,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. */
> >> >> >> >> >> >> @@ -367,12 +373,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
> >> >> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> >> >> >> index 12ce41038f..c9c232ebc2 100644
> >> >> >> >> >> >> --- a/libio/Makefile
> >> >> >> >> >> >> +++ b/libio/Makefile
> >> >> >> >> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> >> >> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> >> >> >> $(objpfx)tst-bz24228-mem.out
> >> >> >> >> >> >> endif
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +tests += tst-cleanup-default
> >> >> >> >> >> >> +tests-static += tst-cleanup-default
> >> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> >> >> >> >> >> >
> >> >> >> >> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
> >> >> >> >> >>
> >> >> >> >> >> Added.
> >> >> >> >> >>
> >> >> >> >> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> >> >> >> >> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> >> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> >> >> >> >> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> >> >> >> >> >> >
> >> >> >> >> >> >Same here.
> >> >> >> >> >>
> >> >> >> >> >> Added.
> >> >> >> >> >>
> >> >> >> >> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >> >> >> >> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> >> >> >> >> >> >> +endif
> >> >> >> >> >> >> endif
> >> >> >> >> >> >>
> >> >> >> >> >> >> include ../Rules
> >> >> >> >> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> >> >> >> endif
> >> >> >> >> >> >>
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> >> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> >>
> >> >> >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> >> >> >> >> $(common-objpfx)libio/; \
> >> >> >> >> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> >> >> >> >> >> >> new file mode 100644
> >> >> >> >> >> >> index 0000000000..7f0a34a91e
> >> >> >> >> >> >> --- /dev/null
> >> >> >> >> >> >> +++ b/libio/tst-cleanup.c
> >> >> >> >> >> >> @@ -0,0 +1,33 @@
> >> >> >> >> >> >
> >> >> >> >> >> >Please add a comment saying that test --gc-sections.
> >> >> >> >> >>
> >> >> >> >> >> OK, added.
> >> >> >> >> >>
> >> >> >> >> >> >> +/* 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. */
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +#include <stdio.h>
> >> >> >> >> >> >> +#include <stdlib.h>
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +void
> >> >> >> >> >> >> +hook (void)
> >> >> >> >> >> >> +{
> >> >> >> >> >> >> + puts ("hello");
> >> >> >> >> >> >> +}
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +int
> >> >> >> >> >> >> +main (void)
> >> >> >> >> >> >> +{
> >> >> >> >> >> >> + atexit (hook);
> >> >> >> >> >> >> +}
> >> >> >> >> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> >> >> >> >> >> >> new file mode 100644
> >> >> >> >> >> >> index 0000000000..ce01362503
> >> >> >> >> >> >> --- /dev/null
> >> >> >> >> >> >> +++ b/libio/tst-cleanup.exp
> >> >> >> >> >> >> @@ -0,0 +1 @@
> >> >> >> >> >> >> +hello
> >> >> >> >> >> >> --
> >> >> >> >> >> >> 2.31.0.291.g576ba9dcdaf-goog
> >> >> >> >> >> >>
> >> >> >> >> >> >
> >> >> >> >> >>
> >> >> >> >> >> diff --git a/config.h.in b/config.h.in
> >> >> >> >> >> index ca1547ae67..96a08c7757 100644
> >> >> >> >> >> --- a/config.h.in
> >> >> >> >> >> +++ b/config.h.in
> >> >> >> >> >> @@ -187,6 +187,9 @@
> >> >> >> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> >> >> >> #undef HAVE_GCC_IFUNC
> >> >> >> >> >>
> >> >> >> >> >> +/* Define if CC supports attribute retain. */
> >> >> >> >> >> +#undef HAVE_GNU_RETAIN
> >> >> >> >> >> +
> >> >> >> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> >> >> >> #undef HAVE_EHDR_START
> >> >> >> >> >>
> >> >> >> >> >> diff --git a/configure b/configure
> >> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> >> >> >> --- a/configure
> >> >> >> >> >> +++ b/configure
> >> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> >> >> >> @@ -5871,6 +5896,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
> >> >> >> >> >> 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],
> >> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> >> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> >> >> >> --- a/include/libc-symbols.h
> >> >> >> >> >> +++ b/include/libc-symbols.h
> >> >> >> >> >> @@ -352,6 +352,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. */
> >> >> >> >> >> @@ -367,12 +373,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
> >> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> >> >> index 12ce41038f..ad0d53bb49 100644
> >> >> >> >> >> --- a/libio/Makefile
> >> >> >> >> >> +++ b/libio/Makefile
> >> >> >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> >> >> $(objpfx)tst-bz24228-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
> >> >> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> >> >> endif
> >> >> >> >> >>
> >> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> +
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >
> >> >> >> >> >Please add a separate .c file for each test to get the correct dependency.
> >> >> >> >>
> >> >> >> >> Changed this block to:
> >> >> >> >>
> >> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> >> endif
> >> >> >> >>
> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +
> >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> >> >> $(common-objpfx)libio/; \
> >> >> >> >>
> >> >> >> >
> >> >> >> >"make clean" doesn't remove the generated files. The standard way in glibc
> >> >> >> >is to add a *-static.c source.
> >> >> >>
> >> >> >> I'll use .INTERMEDIATE and $(eval $(call ..))
> >> >> >>
> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> index 12ce41038f..a9b44f04df 100644
> >> >> >> --- a/libio/Makefile
> >> >> >> +++ b/libio/Makefile
> >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> $(objpfx)tst-bz24228-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
> >> >> >> @@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> $(objpfx)tst-wfile-sync.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)
> >> >> >> +$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
> >> >> >> + cp $$< $$@
> >> >> >> +.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
> >> >> >> +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/; \
> >> >> >
> >> >> >There are 2 issues with static tests:
> >> >> >
> >> >> >1. A separate static source is needed.
> >> >>
> >> >> .INTERMEDIATE perfectly solves the lingering copied source issue.
> >> >> I don't see lingering libio/tst-cleanup-*.c
> >> >
> >> >I was referring to
> >> >
> >> >elf/tst-array1-static.c
> >> >elf/tst-array5-static.c
> >> >elf/tst-dl-iter-static.c
> >> >elf/tst-dst-static.c
> >> >elf/tst-leaks1-static.c
> >> >elf/tst-libc_dlvsym-static.c
> >> >elf/tst-linkall-static.c
> >> >elf/tst-ptrguard1-static.c
> >> >elf/tst-single_threaded-pthread-static.c
> >> >elf/tst-single_threaded-static.c
> >> >elf/tst-stackguard1-static.c
> >> >elf/tst-tls1-static.c
> >> >elf/tst-tls2-static.c
> >> >elf/tst-tls9-static.c
> >> >elf/tst-tlsalign-extern-static.c
> >> >elf/tst-tlsalign-static.c
> >> >gmon/tst-gmon-static.c
> >> >gmon/tst-profile-static.c
> >> >localedata/bug-setlocale1-static.c
> >> >localedata/tst-langinfo-newlocale-static.c
> >> >localedata/tst-langinfo-setlocale-static.c
> >> >localedata/tst-langinfo-static.c
> >> >malloc/tst-malloc-usable-static.c
> >> >math/test-fpucw-ieee-static.c
> >> >math/test-fpucw-static.c
> >> >math/test-signgam-uchar-init-static.c
> >> >math/test-signgam-uchar-static.c
> >> >math/test-signgam-uint-init-static.c
> >> >math/test-signgam-uint-static.c
> >> >math/test-signgam-ullong-init-static.c
> >> >math/test-signgam-ullong-static.c
> >> >nptl/tst-mutex8-static.c
> >> >nptl/tst-mutexpi8-static.c
> >> >nptl/tst-sem11-static.c
> >> >nptl/tst-sem12-static.c
> >> >nptl/tst-setuid1-static.c
> >> >nptl/tst-stackguard1-static.c
> >> >nss/tst-nss-static.c
> >> >posix/tst-exec-static.c
> >> >posix/tst-spawn-static.c
> >> >setjmp/tst-setjmp-static.c
> >> >
> >> >> >2. We need to add the static test to both tests and tests-static.
> >> >>
> >> >> tests-static suffices. I have checked some tests-static usage in other
> >> >> directories.
> >> >
> >> >There are
> >> >
> >> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> >> > tst-sigsetjmp tst-setjmp-static
> >> >tests-static := tst-setjmp-static
> >> >
> >> >They should be replaced by something like
> >> >
> >> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> >> > tst-sigsetjmp
> >> >tests-static-add := tst-setjmp-static
> >>
> >> Re-checking, the tst-cleanup* targets are in tests-special so `make tests` will build them.
> >> If a tests-static target is not in tests-internal/tests-special, looks like it needs to be in tests.
> >>
> >> As is, I think my usage is correct.
> >>
> >
> >The current glibc convention is to use
> >
> >[hjl@gnu-cfl-2 x86-glibc]$ cat elf/tst-tls9-static.c
> >#include "tst-tls9.c"
> >[hjl@gnu-cfl-2 x86-glibc]$
> >
> >to test both dynamic and static libc. If we want to use a single
> >source, we should create
> >a framework to cover all such tests.
>
> OK. Dropped cp $< $@ and .INTERMEDIATE
>
>
> From e937ae26a4a9a8ff6b1198f347f0b141a9285305 Mon Sep 17 00:00:00 2001
> From: Fangrui Song <maskray@google.com>
> Date: Tue, 6 Apr 2021 14:45:01 -0700
> Subject: [PATCH] Set the retain attribute on _elf_set_element if CC supports
> [BZ #27492]
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
>
> 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).
> ---
> config.h.in | 3 ++
> configure | 59 ++++++++++++++++++++++
> configure.ac | 21 ++++++++
> include/libc-symbols.h | 14 +++--
> libio/Makefile | 28 ++++++++++
> libio/tst-cleanup-default-static.c | 1 +
> libio/tst-cleanup-default.c | 1 +
> libio/tst-cleanup-nostart-stop-gc-static.c | 1 +
> libio/tst-cleanup-nostart-stop-gc.c | 1 +
> libio/tst-cleanup-start-stop-gc-static.c | 1 +
> libio/tst-cleanup-start-stop-gc.c | 1 +
> libio/tst-cleanup.c | 34 +++++++++++++
> libio/tst-cleanup.exp | 1 +
> 13 files changed, 162 insertions(+), 4 deletions(-)
> create mode 100644 libio/tst-cleanup-default-static.c
> create mode 100644 libio/tst-cleanup-default.c
> create mode 100644 libio/tst-cleanup-nostart-stop-gc-static.c
> create mode 100644 libio/tst-cleanup-nostart-stop-gc.c
> create mode 100644 libio/tst-cleanup-start-stop-gc-static.c
> create mode 100644 libio/tst-cleanup-start-stop-gc.c
> create mode 100644 libio/tst-cleanup.c
> create mode 100644 libio/tst-cleanup.exp
>
> diff --git a/config.h.in b/config.h.in
> index ca1547ae67..96a08c7757 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -187,6 +187,9 @@
> /* Define if gcc supports attribute ifunc. */
> #undef HAVE_GCC_IFUNC
>
> +/* Define if CC supports attribute retain. */
> +#undef HAVE_GNU_RETAIN
> +
> /* Define if the linker defines __ehdr_start. */
> #undef HAVE_EHDR_START
>
> diff --git a/configure b/configure
> index fcf43bf7de..e64b7f8efe 100755
> --- a/configure
> +++ b/configure
> @@ -4105,6 +4105,31 @@ fi
> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> @@ -5871,6 +5896,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
> 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],
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index 546fc26a7b..127ea656c2 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -352,6 +352,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. */
> @@ -367,12 +373,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
> diff --git a/libio/Makefile b/libio/Makefile
> index 12ce41038f..ed0ce4ee81 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> $(objpfx)tst-bz24228-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
> @@ -224,6 +244,14 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> $(objpfx)tst-wfile-sync.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/; \
> diff --git a/libio/tst-cleanup-default-static.c b/libio/tst-cleanup-default-static.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-default-static.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-default.c b/libio/tst-cleanup-default.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-default.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-nostart-stop-gc-static.c b/libio/tst-cleanup-nostart-stop-gc-static.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-nostart-stop-gc-static.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-nostart-stop-gc.c b/libio/tst-cleanup-nostart-stop-gc.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-nostart-stop-gc.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-start-stop-gc-static.c b/libio/tst-cleanup-start-stop-gc-static.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-start-stop-gc-static.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-start-stop-gc.c b/libio/tst-cleanup-start-stop-gc.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-start-stop-gc.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> new file mode 100644
> index 0000000000..837feac164
> --- /dev/null
> +++ b/libio/tst-cleanup.c
> @@ -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);
> +}
> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> new file mode 100644
> index 0000000000..ce01362503
> --- /dev/null
> +++ b/libio/tst-cleanup.exp
> @@ -0,0 +1 @@
> +hello
> --
> 2.31.0.208.g409f899ff0-goog
>
Looks good now? I want to push next week.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-09 22:36 ` Fāng-ruì Sòng
@ 2021-04-16 3:51 ` Fāng-ruì Sòng
0 siblings, 0 replies; 40+ messages in thread
From: Fāng-ruì Sòng @ 2021-04-16 3:51 UTC (permalink / raw)
To: H.J. Lu; +Cc: GNU C Library, Florian Weimer
On Fri, Apr 9, 2021 at 3:36 PM Fāng-ruì Sòng <maskray@google.com> wrote:
>
> On Tue, Apr 6, 2021 at 2:46 PM Fangrui Song <maskray@google.com> wrote:
> >
> >
> > On 2021-04-05, H.J. Lu wrote:
> > >On Mon, Apr 5, 2021 at 2:03 PM Fangrui Song <maskray@google.com> wrote:
> > >>
> > >> On 2021-04-05, H.J. Lu wrote:
> > >> >On Mon, Apr 5, 2021 at 11:17 AM Fangrui Song <maskray@google.com> wrote:
> > >> >>
> > >> >> On 2021-04-04, H.J. Lu wrote:
> > >> >> >On Sat, Apr 3, 2021 at 2:57 PM Fangrui Song <maskray@google.com> wrote:
> > >> >> >>
> > >> >> >> On 2021-04-03, H.J. Lu wrote:
> > >> >> >> >On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
> > >> >> >> >>
> > >> >> >> >>
> > >> >> >> >> On 2021-04-02, H.J. Lu wrote:
> > >> >> >> >> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
> > >> >> >> >> >>
> > >> >> >> >> >> On 2021-04-01, H.J. Lu wrote:
> > >> >> >> >> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
> > >> >> >> >> >> >>
> > >> >> >> >> >> >> 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).
> > >> >> >> >> >> >> ---
> > >> >> >> >> >> >> Changes in v1 -> v2:
> > >> >> >> >> >> >> * Define attribute_used_retain_section
> > >> >> >> >> >> >> Changes in v2 -> v3:
> > >> >> >> >> >> >> * Use attribute_used_retain instead attribute_used_retain_section
> > >> >> >> >> >> >> Changes in v3 -> v4:
> > >> >> >> >> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> > >> >> >> >> >> >> Changes in v4 -> v5:
> > >> >> >> >> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> > >> >> >> >> >> >> * Rename *gcc_retain* to *gnu_retain*
> > >> >> >> >> >> >> ---
> > >> >> >> >> >> >> config.h.in | 3 +++
> > >> >> >> >> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> > >> >> >> >> >> >> configure.ac | 21 +++++++++++++++
> > >> >> >> >> >> >> include/libc-symbols.h | 14 +++++++---
> > >> >> >> >> >> >> libio/Makefile | 32 +++++++++++++++++++++++
> > >> >> >> >> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> > >> >> >> >> >> >> libio/tst-cleanup.exp | 1 +
> > >> >> >> >> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
> > >> >> >> >> >> >> create mode 100644 libio/tst-cleanup.c
> > >> >> >> >> >> >> create mode 100644 libio/tst-cleanup.exp
> > >> >> >> >> >> >>
> > >> >> >> >> >> >> diff --git a/config.h.in b/config.h.in
> > >> >> >> >> >> >> index ca1547ae67..96a08c7757 100644
> > >> >> >> >> >> >> --- a/config.h.in
> > >> >> >> >> >> >> +++ b/config.h.in
> > >> >> >> >> >> >> @@ -187,6 +187,9 @@
> > >> >> >> >> >> >> /* Define if gcc supports attribute ifunc. */
> > >> >> >> >> >> >> #undef HAVE_GCC_IFUNC
> > >> >> >> >> >> >>
> > >> >> >> >> >> >> +/* Define if CC supports attribute retain. */
> > >> >> >> >> >> >> +#undef HAVE_GNU_RETAIN
> > >> >> >> >> >> >> +
> > >> >> >> >> >> >> /* Define if the linker defines __ehdr_start. */
> > >> >> >> >> >> >> #undef HAVE_EHDR_START
> > >> >> >> >> >> >>
> > >> >> >> >> >> >> diff --git a/configure b/configure
> > >> >> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> > >> >> >> >> >> >> --- a/configure
> > >> >> >> >> >> >> +++ b/configure
> > >> >> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
> > >> >> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> > >> >> >> >> >> >> @@ -5871,6 +5896,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
> > >> >> >> >> >> >> 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],
> > >> >> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> > >> >> >> >> >> >> index 546fc26a7b..127ea656c2 100644
> > >> >> >> >> >> >> --- a/include/libc-symbols.h
> > >> >> >> >> >> >> +++ b/include/libc-symbols.h
> > >> >> >> >> >> >> @@ -352,6 +352,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. */
> > >> >> >> >> >> >> @@ -367,12 +373,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
> > >> >> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> > >> >> >> >> >> >> index 12ce41038f..c9c232ebc2 100644
> > >> >> >> >> >> >> --- a/libio/Makefile
> > >> >> >> >> >> >> +++ b/libio/Makefile
> > >> >> >> >> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> > >> >> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> > >> >> >> >> >> >> $(objpfx)tst-bz24228-mem.out
> > >> >> >> >> >> >> endif
> > >> >> >> >> >> >> +
> > >> >> >> >> >> >> +tests += tst-cleanup-default
> > >> >> >> >> >> >> +tests-static += tst-cleanup-default
> > >> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> > >> >> >> >> >> >
> > >> >> >> >> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
> > >> >> >> >> >>
> > >> >> >> >> >> Added.
> > >> >> >> >> >>
> > >> >> >> >> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> > >> >> >> >> >> >> +
> > >> >> >> >> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> > >> >> >> >> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> > >> >> >> >> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> > >> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> > >> >> >> >> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> > >> >> >> >> >> >
> > >> >> >> >> >> >Same here.
> > >> >> >> >> >>
> > >> >> >> >> >> Added.
> > >> >> >> >> >>
> > >> >> >> >> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> > >> >> >> >> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> > >> >> >> >> >> >> +endif
> > >> >> >> >> >> >> endif
> > >> >> >> >> >> >>
> > >> >> >> >> >> >> include ../Rules
> > >> >> >> >> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> > >> >> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> > >> >> >> >> >> >> endif
> > >> >> >> >> >> >>
> > >> >> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> > >> >> >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> >> >> + $(evaluate-test)
> > >> >> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> > >> >> >> >> >> >> + $(compile.c) -o $@
> > >> >> >> >> >> >> +
> > >> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> > >> >> >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> >> >> + $(evaluate-test)
> > >> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> > >> >> >> >> >> >> + $(compile.c) -o $@
> > >> >> >> >> >> >> +
> > >> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> > >> >> >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> >> >> + $(evaluate-test)
> > >> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> > >> >> >> >> >> >> + $(compile.c) -o $@
> > >> >> >> >> >> >>
> > >> >> >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> > >> >> >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> > >> >> >> >> >> >> $(common-objpfx)libio/; \
> > >> >> >> >> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> > >> >> >> >> >> >> new file mode 100644
> > >> >> >> >> >> >> index 0000000000..7f0a34a91e
> > >> >> >> >> >> >> --- /dev/null
> > >> >> >> >> >> >> +++ b/libio/tst-cleanup.c
> > >> >> >> >> >> >> @@ -0,0 +1,33 @@
> > >> >> >> >> >> >
> > >> >> >> >> >> >Please add a comment saying that test --gc-sections.
> > >> >> >> >> >>
> > >> >> >> >> >> OK, added.
> > >> >> >> >> >>
> > >> >> >> >> >> >> +/* 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. */
> > >> >> >> >> >> >> +
> > >> >> >> >> >> >> +#include <stdio.h>
> > >> >> >> >> >> >> +#include <stdlib.h>
> > >> >> >> >> >> >> +
> > >> >> >> >> >> >> +void
> > >> >> >> >> >> >> +hook (void)
> > >> >> >> >> >> >> +{
> > >> >> >> >> >> >> + puts ("hello");
> > >> >> >> >> >> >> +}
> > >> >> >> >> >> >> +
> > >> >> >> >> >> >> +int
> > >> >> >> >> >> >> +main (void)
> > >> >> >> >> >> >> +{
> > >> >> >> >> >> >> + atexit (hook);
> > >> >> >> >> >> >> +}
> > >> >> >> >> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> > >> >> >> >> >> >> new file mode 100644
> > >> >> >> >> >> >> index 0000000000..ce01362503
> > >> >> >> >> >> >> --- /dev/null
> > >> >> >> >> >> >> +++ b/libio/tst-cleanup.exp
> > >> >> >> >> >> >> @@ -0,0 +1 @@
> > >> >> >> >> >> >> +hello
> > >> >> >> >> >> >> --
> > >> >> >> >> >> >> 2.31.0.291.g576ba9dcdaf-goog
> > >> >> >> >> >> >>
> > >> >> >> >> >> >
> > >> >> >> >> >>
> > >> >> >> >> >> diff --git a/config.h.in b/config.h.in
> > >> >> >> >> >> index ca1547ae67..96a08c7757 100644
> > >> >> >> >> >> --- a/config.h.in
> > >> >> >> >> >> +++ b/config.h.in
> > >> >> >> >> >> @@ -187,6 +187,9 @@
> > >> >> >> >> >> /* Define if gcc supports attribute ifunc. */
> > >> >> >> >> >> #undef HAVE_GCC_IFUNC
> > >> >> >> >> >>
> > >> >> >> >> >> +/* Define if CC supports attribute retain. */
> > >> >> >> >> >> +#undef HAVE_GNU_RETAIN
> > >> >> >> >> >> +
> > >> >> >> >> >> /* Define if the linker defines __ehdr_start. */
> > >> >> >> >> >> #undef HAVE_EHDR_START
> > >> >> >> >> >>
> > >> >> >> >> >> diff --git a/configure b/configure
> > >> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> > >> >> >> >> >> --- a/configure
> > >> >> >> >> >> +++ b/configure
> > >> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
> > >> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> > >> >> >> >> >> @@ -5871,6 +5896,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
> > >> >> >> >> >> 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],
> > >> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> > >> >> >> >> >> index 546fc26a7b..127ea656c2 100644
> > >> >> >> >> >> --- a/include/libc-symbols.h
> > >> >> >> >> >> +++ b/include/libc-symbols.h
> > >> >> >> >> >> @@ -352,6 +352,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. */
> > >> >> >> >> >> @@ -367,12 +373,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
> > >> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> > >> >> >> >> >> index 12ce41038f..ad0d53bb49 100644
> > >> >> >> >> >> --- a/libio/Makefile
> > >> >> >> >> >> +++ b/libio/Makefile
> > >> >> >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> > >> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> > >> >> >> >> >> $(objpfx)tst-bz24228-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
> > >> >> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> > >> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> > >> >> >> >> >> endif
> > >> >> >> >> >>
> > >> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> > >> >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> >> + $(evaluate-test)
> > >> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> > >> >> >> >> >> + $(compile.c) -o $@
> > >> >> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> > >> >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> >> + $(evaluate-test)
> > >> >> >> >> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
> > >> >> >> >> >> + $(compile.c) -o $@
> > >> >> >> >> >> +
> > >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> > >> >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> >> + $(evaluate-test)
> > >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> > >> >> >> >> >> + $(compile.c) -o $@
> > >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> > >> >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> >> + $(evaluate-test)
> > >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
> > >> >> >> >> >> + $(compile.c) -o $@
> > >> >> >> >> >
> > >> >> >> >> >Please add a separate .c file for each test to get the correct dependency.
> > >> >> >> >>
> > >> >> >> >> Changed this block to:
> > >> >> >> >>
> > >> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> > >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> > >> >> >> >> endif
> > >> >> >> >>
> > >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> > >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> + $(evaluate-test)
> > >> >> >> >> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
> > >> >> >> >> + cp $< $@
> > >> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> > >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> + $(evaluate-test)
> > >> >> >> >> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
> > >> >> >> >> + cp $< $@
> > >> >> >> >> +
> > >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> > >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> + $(evaluate-test)
> > >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> > >> >> >> >> + $(compile.c) -o $@
> > >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> > >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> + $(evaluate-test)
> > >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
> > >> >> >> >> + cp $< $@
> > >> >> >> >> +
> > >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> > >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> + $(evaluate-test)
> > >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
> > >> >> >> >> + cp $< $@
> > >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
> > >> >> >> >> + cmp $^ > $@; \
> > >> >> >> >> + $(evaluate-test)
> > >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
> > >> >> >> >> + cp $< $@
> > >> >> >> >> +
> > >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> > >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> > >> >> >> >> $(common-objpfx)libio/; \
> > >> >> >> >>
> > >> >> >> >
> > >> >> >> >"make clean" doesn't remove the generated files. The standard way in glibc
> > >> >> >> >is to add a *-static.c source.
> > >> >> >>
> > >> >> >> I'll use .INTERMEDIATE and $(eval $(call ..))
> > >> >> >>
> > >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> > >> >> >> index 12ce41038f..a9b44f04df 100644
> > >> >> >> --- a/libio/Makefile
> > >> >> >> +++ b/libio/Makefile
> > >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> > >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> > >> >> >> $(objpfx)tst-bz24228-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
> > >> >> >> @@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> > >> >> >> $(objpfx)tst-wfile-sync.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)
> > >> >> >> +$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
> > >> >> >> + cp $$< $$@
> > >> >> >> +.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
> > >> >> >> +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/; \
> > >> >> >
> > >> >> >There are 2 issues with static tests:
> > >> >> >
> > >> >> >1. A separate static source is needed.
> > >> >>
> > >> >> .INTERMEDIATE perfectly solves the lingering copied source issue.
> > >> >> I don't see lingering libio/tst-cleanup-*.c
> > >> >
> > >> >I was referring to
> > >> >
> > >> >elf/tst-array1-static.c
> > >> >elf/tst-array5-static.c
> > >> >elf/tst-dl-iter-static.c
> > >> >elf/tst-dst-static.c
> > >> >elf/tst-leaks1-static.c
> > >> >elf/tst-libc_dlvsym-static.c
> > >> >elf/tst-linkall-static.c
> > >> >elf/tst-ptrguard1-static.c
> > >> >elf/tst-single_threaded-pthread-static.c
> > >> >elf/tst-single_threaded-static.c
> > >> >elf/tst-stackguard1-static.c
> > >> >elf/tst-tls1-static.c
> > >> >elf/tst-tls2-static.c
> > >> >elf/tst-tls9-static.c
> > >> >elf/tst-tlsalign-extern-static.c
> > >> >elf/tst-tlsalign-static.c
> > >> >gmon/tst-gmon-static.c
> > >> >gmon/tst-profile-static.c
> > >> >localedata/bug-setlocale1-static.c
> > >> >localedata/tst-langinfo-newlocale-static.c
> > >> >localedata/tst-langinfo-setlocale-static.c
> > >> >localedata/tst-langinfo-static.c
> > >> >malloc/tst-malloc-usable-static.c
> > >> >math/test-fpucw-ieee-static.c
> > >> >math/test-fpucw-static.c
> > >> >math/test-signgam-uchar-init-static.c
> > >> >math/test-signgam-uchar-static.c
> > >> >math/test-signgam-uint-init-static.c
> > >> >math/test-signgam-uint-static.c
> > >> >math/test-signgam-ullong-init-static.c
> > >> >math/test-signgam-ullong-static.c
> > >> >nptl/tst-mutex8-static.c
> > >> >nptl/tst-mutexpi8-static.c
> > >> >nptl/tst-sem11-static.c
> > >> >nptl/tst-sem12-static.c
> > >> >nptl/tst-setuid1-static.c
> > >> >nptl/tst-stackguard1-static.c
> > >> >nss/tst-nss-static.c
> > >> >posix/tst-exec-static.c
> > >> >posix/tst-spawn-static.c
> > >> >setjmp/tst-setjmp-static.c
> > >> >
> > >> >> >2. We need to add the static test to both tests and tests-static.
> > >> >>
> > >> >> tests-static suffices. I have checked some tests-static usage in other
> > >> >> directories.
> > >> >
> > >> >There are
> > >> >
> > >> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> > >> > tst-sigsetjmp tst-setjmp-static
> > >> >tests-static := tst-setjmp-static
> > >> >
> > >> >They should be replaced by something like
> > >> >
> > >> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> > >> > tst-sigsetjmp
> > >> >tests-static-add := tst-setjmp-static
> > >>
> > >> Re-checking, the tst-cleanup* targets are in tests-special so `make tests` will build them.
> > >> If a tests-static target is not in tests-internal/tests-special, looks like it needs to be in tests.
> > >>
> > >> As is, I think my usage is correct.
> > >>
> > >
> > >The current glibc convention is to use
> > >
> > >[hjl@gnu-cfl-2 x86-glibc]$ cat elf/tst-tls9-static.c
> > >#include "tst-tls9.c"
> > >[hjl@gnu-cfl-2 x86-glibc]$
> > >
> > >to test both dynamic and static libc. If we want to use a single
> > >source, we should create
> > >a framework to cover all such tests.
> >
> > OK. Dropped cp $< $@ and .INTERMEDIATE
> >
> >
> > From e937ae26a4a9a8ff6b1198f347f0b141a9285305 Mon Sep 17 00:00:00 2001
> > From: Fangrui Song <maskray@google.com>
> > Date: Tue, 6 Apr 2021 14:45:01 -0700
> > Subject: [PATCH] Set the retain attribute on _elf_set_element if CC supports
> > [BZ #27492]
> > MIME-Version: 1.0
> > Content-Type: text/plain; charset=UTF-8
> > Content-Transfer-Encoding: 8bit
> >
> > 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).
> > ---
> > config.h.in | 3 ++
> > configure | 59 ++++++++++++++++++++++
> > configure.ac | 21 ++++++++
> > include/libc-symbols.h | 14 +++--
> > libio/Makefile | 28 ++++++++++
> > libio/tst-cleanup-default-static.c | 1 +
> > libio/tst-cleanup-default.c | 1 +
> > libio/tst-cleanup-nostart-stop-gc-static.c | 1 +
> > libio/tst-cleanup-nostart-stop-gc.c | 1 +
> > libio/tst-cleanup-start-stop-gc-static.c | 1 +
> > libio/tst-cleanup-start-stop-gc.c | 1 +
> > libio/tst-cleanup.c | 34 +++++++++++++
> > libio/tst-cleanup.exp | 1 +
> > 13 files changed, 162 insertions(+), 4 deletions(-)
> > create mode 100644 libio/tst-cleanup-default-static.c
> > create mode 100644 libio/tst-cleanup-default.c
> > create mode 100644 libio/tst-cleanup-nostart-stop-gc-static.c
> > create mode 100644 libio/tst-cleanup-nostart-stop-gc.c
> > create mode 100644 libio/tst-cleanup-start-stop-gc-static.c
> > create mode 100644 libio/tst-cleanup-start-stop-gc.c
> > create mode 100644 libio/tst-cleanup.c
> > create mode 100644 libio/tst-cleanup.exp
> >
> > diff --git a/config.h.in b/config.h.in
> > index ca1547ae67..96a08c7757 100644
> > --- a/config.h.in
> > +++ b/config.h.in
> > @@ -187,6 +187,9 @@
> > /* Define if gcc supports attribute ifunc. */
> > #undef HAVE_GCC_IFUNC
> >
> > +/* Define if CC supports attribute retain. */
> > +#undef HAVE_GNU_RETAIN
> > +
> > /* Define if the linker defines __ehdr_start. */
> > #undef HAVE_EHDR_START
> >
> > diff --git a/configure b/configure
> > index fcf43bf7de..e64b7f8efe 100755
> > --- a/configure
> > +++ b/configure
> > @@ -4105,6 +4105,31 @@ fi
> > $as_echo "$libc_cv_textrel_ifunc" >&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; }
> > @@ -5871,6 +5896,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
> > 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],
> > diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> > index 546fc26a7b..127ea656c2 100644
> > --- a/include/libc-symbols.h
> > +++ b/include/libc-symbols.h
> > @@ -352,6 +352,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. */
> > @@ -367,12 +373,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
> > diff --git a/libio/Makefile b/libio/Makefile
> > index 12ce41038f..ed0ce4ee81 100644
> > --- a/libio/Makefile
> > +++ b/libio/Makefile
> > @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> > tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> > $(objpfx)tst-bz24228-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
> > @@ -224,6 +244,14 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> > $(objpfx)tst-wfile-sync.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/; \
> > diff --git a/libio/tst-cleanup-default-static.c b/libio/tst-cleanup-default-static.c
> > new file mode 100644
> > index 0000000000..c39956e2a8
> > --- /dev/null
> > +++ b/libio/tst-cleanup-default-static.c
> > @@ -0,0 +1 @@
> > +#include "tst-cleanup.c"
> > diff --git a/libio/tst-cleanup-default.c b/libio/tst-cleanup-default.c
> > new file mode 100644
> > index 0000000000..c39956e2a8
> > --- /dev/null
> > +++ b/libio/tst-cleanup-default.c
> > @@ -0,0 +1 @@
> > +#include "tst-cleanup.c"
> > diff --git a/libio/tst-cleanup-nostart-stop-gc-static.c b/libio/tst-cleanup-nostart-stop-gc-static.c
> > new file mode 100644
> > index 0000000000..c39956e2a8
> > --- /dev/null
> > +++ b/libio/tst-cleanup-nostart-stop-gc-static.c
> > @@ -0,0 +1 @@
> > +#include "tst-cleanup.c"
> > diff --git a/libio/tst-cleanup-nostart-stop-gc.c b/libio/tst-cleanup-nostart-stop-gc.c
> > new file mode 100644
> > index 0000000000..c39956e2a8
> > --- /dev/null
> > +++ b/libio/tst-cleanup-nostart-stop-gc.c
> > @@ -0,0 +1 @@
> > +#include "tst-cleanup.c"
> > diff --git a/libio/tst-cleanup-start-stop-gc-static.c b/libio/tst-cleanup-start-stop-gc-static.c
> > new file mode 100644
> > index 0000000000..c39956e2a8
> > --- /dev/null
> > +++ b/libio/tst-cleanup-start-stop-gc-static.c
> > @@ -0,0 +1 @@
> > +#include "tst-cleanup.c"
> > diff --git a/libio/tst-cleanup-start-stop-gc.c b/libio/tst-cleanup-start-stop-gc.c
> > new file mode 100644
> > index 0000000000..c39956e2a8
> > --- /dev/null
> > +++ b/libio/tst-cleanup-start-stop-gc.c
> > @@ -0,0 +1 @@
> > +#include "tst-cleanup.c"
> > diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> > new file mode 100644
> > index 0000000000..837feac164
> > --- /dev/null
> > +++ b/libio/tst-cleanup.c
> > @@ -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);
> > +}
> > diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> > new file mode 100644
> > index 0000000000..ce01362503
> > --- /dev/null
> > +++ b/libio/tst-cleanup.exp
> > @@ -0,0 +1 @@
> > +hello
> > --
> > 2.31.0.208.g409f899ff0-goog
> >
>
> Looks good now? I want to push next week.
Ping...
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v5] Set the retain attribute on _elf_set_element if CC supports [BZ #27492]
2021-04-06 21:46 ` Fangrui Song
2021-04-09 22:36 ` Fāng-ruì Sòng
@ 2021-04-16 13:00 ` H.J. Lu
1 sibling, 0 replies; 40+ messages in thread
From: H.J. Lu @ 2021-04-16 13:00 UTC (permalink / raw)
To: Fangrui Song; +Cc: GNU C Library, Florian Weimer
On Tue, Apr 6, 2021 at 2:46 PM Fangrui Song <maskray@google.com> wrote:
>
>
> On 2021-04-05, H.J. Lu wrote:
> >On Mon, Apr 5, 2021 at 2:03 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2021-04-05, H.J. Lu wrote:
> >> >On Mon, Apr 5, 2021 at 11:17 AM Fangrui Song <maskray@google.com> wrote:
> >> >>
> >> >> On 2021-04-04, H.J. Lu wrote:
> >> >> >On Sat, Apr 3, 2021 at 2:57 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >>
> >> >> >> On 2021-04-03, H.J. Lu wrote:
> >> >> >> >On Sat, Apr 3, 2021 at 11:02 AM Fangrui Song <maskray@google.com> wrote:
> >> >> >> >>
> >> >> >> >>
> >> >> >> >> On 2021-04-02, H.J. Lu wrote:
> >> >> >> >> >On Thu, Apr 1, 2021 at 8:23 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >> >> >>
> >> >> >> >> >> On 2021-04-01, H.J. Lu wrote:
> >> >> >> >> >> >On Wed, Mar 31, 2021 at 6:07 PM Fangrui Song <maskray@google.com> wrote:
> >> >> >> >> >> >>
> >> >> >> >> >> >> 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).
> >> >> >> >> >> >> ---
> >> >> >> >> >> >> Changes in v1 -> v2:
> >> >> >> >> >> >> * Define attribute_used_retain_section
> >> >> >> >> >> >> Changes in v2 -> v3:
> >> >> >> >> >> >> * Use attribute_used_retain instead attribute_used_retain_section
> >> >> >> >> >> >> Changes in v3 -> v4:
> >> >> >> >> >> >> * Add LIBC_LINKER_FEATURE detection for -z start-stop-gc and add tst-cleanup* tests
> >> >> >> >> >> >> Changes in v4 -> v5:
> >> >> >> >> >> >> * Enable -z start-stop-gc tests if both retain and -z start-stop-gc are supported
> >> >> >> >> >> >> * Rename *gcc_retain* to *gnu_retain*
> >> >> >> >> >> >> ---
> >> >> >> >> >> >> config.h.in | 3 +++
> >> >> >> >> >> >> configure | 59 ++++++++++++++++++++++++++++++++++++++++++
> >> >> >> >> >> >> configure.ac | 21 +++++++++++++++
> >> >> >> >> >> >> include/libc-symbols.h | 14 +++++++---
> >> >> >> >> >> >> libio/Makefile | 32 +++++++++++++++++++++++
> >> >> >> >> >> >> libio/tst-cleanup.c | 33 +++++++++++++++++++++++
> >> >> >> >> >> >> libio/tst-cleanup.exp | 1 +
> >> >> >> >> >> >> 7 files changed, 159 insertions(+), 4 deletions(-)
> >> >> >> >> >> >> create mode 100644 libio/tst-cleanup.c
> >> >> >> >> >> >> create mode 100644 libio/tst-cleanup.exp
> >> >> >> >> >> >>
> >> >> >> >> >> >> diff --git a/config.h.in b/config.h.in
> >> >> >> >> >> >> index ca1547ae67..96a08c7757 100644
> >> >> >> >> >> >> --- a/config.h.in
> >> >> >> >> >> >> +++ b/config.h.in
> >> >> >> >> >> >> @@ -187,6 +187,9 @@
> >> >> >> >> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> >> >> >> >> #undef HAVE_GCC_IFUNC
> >> >> >> >> >> >>
> >> >> >> >> >> >> +/* Define if CC supports attribute retain. */
> >> >> >> >> >> >> +#undef HAVE_GNU_RETAIN
> >> >> >> >> >> >> +
> >> >> >> >> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> >> >> >> >> #undef HAVE_EHDR_START
> >> >> >> >> >> >>
> >> >> >> >> >> >> diff --git a/configure b/configure
> >> >> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> >> >> >> >> --- a/configure
> >> >> >> >> >> >> +++ b/configure
> >> >> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> >> >> >> >> @@ -5871,6 +5896,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
> >> >> >> >> >> >> 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],
> >> >> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> >> >> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> >> >> >> >> --- a/include/libc-symbols.h
> >> >> >> >> >> >> +++ b/include/libc-symbols.h
> >> >> >> >> >> >> @@ -352,6 +352,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. */
> >> >> >> >> >> >> @@ -367,12 +373,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
> >> >> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> >> >> >> index 12ce41038f..c9c232ebc2 100644
> >> >> >> >> >> >> --- a/libio/Makefile
> >> >> >> >> >> >> +++ b/libio/Makefile
> >> >> >> >> >> >> @@ -195,6 +195,20 @@ ifeq (yes,$(build-shared))
> >> >> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> >> >> >> $(objpfx)tst-bz24228-mem.out
> >> >> >> >> >> >> endif
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +tests += tst-cleanup-default
> >> >> >> >> >> >> +tests-static += tst-cleanup-default
> >> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-default-cmp.out
> >> >> >> >> >> >
> >> >> >> >> >> >Please make 2 tests, tst-cleanup-default and tst-cleanup-default-static.
> >> >> >> >> >>
> >> >> >> >> >> Added.
> >> >> >> >> >>
> >> >> >> >> >> >> +LDFLAGS-tst-cleanup-default = -Wl,--gc-sections
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +ifeq ($(have-gnu-retain)$(have-z-start-stop-gc),yesyes)
> >> >> >> >> >> >> +tests += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> >> >> >> +tests-static += tst-cleanup-start-stop-gc tst-cleanup-nostart-stop-gc
> >> >> >> >> >> >> +tests-special += $(objpfx)tst-cleanup-start-stop-gc-cmp.out \
> >> >> >> >> >> >> + $(objpfx)tst-cleanup-nostart-stop-gc-cmp.out
> >> >> >> >> >> >
> >> >> >> >> >> >Same here.
> >> >> >> >> >>
> >> >> >> >> >> Added.
> >> >> >> >> >>
> >> >> >> >> >> >> +LDFLAGS-tst-cleanup-start-stop-gc = -Wl,--gc-sections,-z,start-stop-gc
> >> >> >> >> >> >> +LDFLAGS-tst-cleanup-nostart-stop-gc = -Wl,--gc-sections,-z,nostart-stop-gc
> >> >> >> >> >> >> +endif
> >> >> >> >> >> >> endif
> >> >> >> >> >> >>
> >> >> >> >> >> >> include ../Rules
> >> >> >> >> >> >> @@ -224,6 +238,24 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> >> >> >> endif
> >> >> >> >> >> >>
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.o: tst-cleanup.c
> >> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> >>
> >> >> >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> >> >> >> >> $(common-objpfx)libio/; \
> >> >> >> >> >> >> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> >> >> >> >> >> >> new file mode 100644
> >> >> >> >> >> >> index 0000000000..7f0a34a91e
> >> >> >> >> >> >> --- /dev/null
> >> >> >> >> >> >> +++ b/libio/tst-cleanup.c
> >> >> >> >> >> >> @@ -0,0 +1,33 @@
> >> >> >> >> >> >
> >> >> >> >> >> >Please add a comment saying that test --gc-sections.
> >> >> >> >> >>
> >> >> >> >> >> OK, added.
> >> >> >> >> >>
> >> >> >> >> >> >> +/* 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. */
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +#include <stdio.h>
> >> >> >> >> >> >> +#include <stdlib.h>
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +void
> >> >> >> >> >> >> +hook (void)
> >> >> >> >> >> >> +{
> >> >> >> >> >> >> + puts ("hello");
> >> >> >> >> >> >> +}
> >> >> >> >> >> >> +
> >> >> >> >> >> >> +int
> >> >> >> >> >> >> +main (void)
> >> >> >> >> >> >> +{
> >> >> >> >> >> >> + atexit (hook);
> >> >> >> >> >> >> +}
> >> >> >> >> >> >> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> >> >> >> >> >> >> new file mode 100644
> >> >> >> >> >> >> index 0000000000..ce01362503
> >> >> >> >> >> >> --- /dev/null
> >> >> >> >> >> >> +++ b/libio/tst-cleanup.exp
> >> >> >> >> >> >> @@ -0,0 +1 @@
> >> >> >> >> >> >> +hello
> >> >> >> >> >> >> --
> >> >> >> >> >> >> 2.31.0.291.g576ba9dcdaf-goog
> >> >> >> >> >> >>
> >> >> >> >> >> >
> >> >> >> >> >>
> >> >> >> >> >> diff --git a/config.h.in b/config.h.in
> >> >> >> >> >> index ca1547ae67..96a08c7757 100644
> >> >> >> >> >> --- a/config.h.in
> >> >> >> >> >> +++ b/config.h.in
> >> >> >> >> >> @@ -187,6 +187,9 @@
> >> >> >> >> >> /* Define if gcc supports attribute ifunc. */
> >> >> >> >> >> #undef HAVE_GCC_IFUNC
> >> >> >> >> >>
> >> >> >> >> >> +/* Define if CC supports attribute retain. */
> >> >> >> >> >> +#undef HAVE_GNU_RETAIN
> >> >> >> >> >> +
> >> >> >> >> >> /* Define if the linker defines __ehdr_start. */
> >> >> >> >> >> #undef HAVE_EHDR_START
> >> >> >> >> >>
> >> >> >> >> >> diff --git a/configure b/configure
> >> >> >> >> >> index fcf43bf7de..e64b7f8efe 100755
> >> >> >> >> >> --- a/configure
> >> >> >> >> >> +++ b/configure
> >> >> >> >> >> @@ -4105,6 +4105,31 @@ fi
> >> >> >> >> >> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> >> >> >> >> >> @@ -5871,6 +5896,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
> >> >> >> >> >> 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],
> >> >> >> >> >> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> >> >> >> >> >> index 546fc26a7b..127ea656c2 100644
> >> >> >> >> >> --- a/include/libc-symbols.h
> >> >> >> >> >> +++ b/include/libc-symbols.h
> >> >> >> >> >> @@ -352,6 +352,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. */
> >> >> >> >> >> @@ -367,12 +373,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
> >> >> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> >> >> index 12ce41038f..ad0d53bb49 100644
> >> >> >> >> >> --- a/libio/Makefile
> >> >> >> >> >> +++ b/libio/Makefile
> >> >> >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> >> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> >> >> $(objpfx)tst-bz24228-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
> >> >> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> >> >> endif
> >> >> >> >> >>
> >> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-default.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-default-static.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> +
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> >> + $(evaluate-test)
> >> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.o: tst-cleanup.c
> >> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> >
> >> >> >> >> >Please add a separate .c file for each test to get the correct dependency.
> >> >> >> >>
> >> >> >> >> Changed this block to:
> >> >> >> >>
> >> >> >> >> @@ -224,6 +244,39 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> >> $(objpfx)tst-wfile-sync.out: $(gen-locales)
> >> >> >> >> endif
> >> >> >> >>
> >> >> >> >> +$(objpfx)tst-cleanup-default-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-default.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +$(objpfx)tst-cleanup-default-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-default-static.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-default-static.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc.o: tst-cleanup.c
> >> >> >> >> + $(compile.c) -o $@
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-start-stop-gc-static.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-start-stop-gc-static.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static-cmp.out: tst-cleanup.exp $(objpfx)tst-cleanup-nostart-stop-gc-static.out
> >> >> >> >> + cmp $^ > $@; \
> >> >> >> >> + $(evaluate-test)
> >> >> >> >> +$(objpfx)tst-cleanup-nostart-stop-gc-static.c: tst-cleanup.c
> >> >> >> >> + cp $< $@
> >> >> >> >> +
> >> >> >> >> $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
> >> >> >> >> $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' \
> >> >> >> >> $(common-objpfx)libio/; \
> >> >> >> >>
> >> >> >> >
> >> >> >> >"make clean" doesn't remove the generated files. The standard way in glibc
> >> >> >> >is to add a *-static.c source.
> >> >> >>
> >> >> >> I'll use .INTERMEDIATE and $(eval $(call ..))
> >> >> >>
> >> >> >> diff --git a/libio/Makefile b/libio/Makefile
> >> >> >> index 12ce41038f..a9b44f04df 100644
> >> >> >> --- a/libio/Makefile
> >> >> >> +++ b/libio/Makefile
> >> >> >> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> >> >> >> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> >> >> >> $(objpfx)tst-bz24228-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
> >> >> >> @@ -224,6 +244,17 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> >> >> >> $(objpfx)tst-wfile-sync.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)
> >> >> >> +$(objpfx)tst-cleanup-$1.c: tst-cleanup.c
> >> >> >> + cp $$< $$@
> >> >> >> +.INTERMEDIATE: $(objpfx)tst-cleanup-$1.c
> >> >> >> +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/; \
> >> >> >
> >> >> >There are 2 issues with static tests:
> >> >> >
> >> >> >1. A separate static source is needed.
> >> >>
> >> >> .INTERMEDIATE perfectly solves the lingering copied source issue.
> >> >> I don't see lingering libio/tst-cleanup-*.c
> >> >
> >> >I was referring to
> >> >
> >> >elf/tst-array1-static.c
> >> >elf/tst-array5-static.c
> >> >elf/tst-dl-iter-static.c
> >> >elf/tst-dst-static.c
> >> >elf/tst-leaks1-static.c
> >> >elf/tst-libc_dlvsym-static.c
> >> >elf/tst-linkall-static.c
> >> >elf/tst-ptrguard1-static.c
> >> >elf/tst-single_threaded-pthread-static.c
> >> >elf/tst-single_threaded-static.c
> >> >elf/tst-stackguard1-static.c
> >> >elf/tst-tls1-static.c
> >> >elf/tst-tls2-static.c
> >> >elf/tst-tls9-static.c
> >> >elf/tst-tlsalign-extern-static.c
> >> >elf/tst-tlsalign-static.c
> >> >gmon/tst-gmon-static.c
> >> >gmon/tst-profile-static.c
> >> >localedata/bug-setlocale1-static.c
> >> >localedata/tst-langinfo-newlocale-static.c
> >> >localedata/tst-langinfo-setlocale-static.c
> >> >localedata/tst-langinfo-static.c
> >> >malloc/tst-malloc-usable-static.c
> >> >math/test-fpucw-ieee-static.c
> >> >math/test-fpucw-static.c
> >> >math/test-signgam-uchar-init-static.c
> >> >math/test-signgam-uchar-static.c
> >> >math/test-signgam-uint-init-static.c
> >> >math/test-signgam-uint-static.c
> >> >math/test-signgam-ullong-init-static.c
> >> >math/test-signgam-ullong-static.c
> >> >nptl/tst-mutex8-static.c
> >> >nptl/tst-mutexpi8-static.c
> >> >nptl/tst-sem11-static.c
> >> >nptl/tst-sem12-static.c
> >> >nptl/tst-setuid1-static.c
> >> >nptl/tst-stackguard1-static.c
> >> >nss/tst-nss-static.c
> >> >posix/tst-exec-static.c
> >> >posix/tst-spawn-static.c
> >> >setjmp/tst-setjmp-static.c
> >> >
> >> >> >2. We need to add the static test to both tests and tests-static.
> >> >>
> >> >> tests-static suffices. I have checked some tests-static usage in other
> >> >> directories.
> >> >
> >> >There are
> >> >
> >> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> >> > tst-sigsetjmp tst-setjmp-static
> >> >tests-static := tst-setjmp-static
> >> >
> >> >They should be replaced by something like
> >> >
> >> >tests := tst-setjmp jmpbug bug269-setjmp tst-setjmp-fp \
> >> > tst-sigsetjmp
> >> >tests-static-add := tst-setjmp-static
> >>
> >> Re-checking, the tst-cleanup* targets are in tests-special so `make tests` will build them.
> >> If a tests-static target is not in tests-internal/tests-special, looks like it needs to be in tests.
> >>
> >> As is, I think my usage is correct.
> >>
> >
> >The current glibc convention is to use
> >
> >[hjl@gnu-cfl-2 x86-glibc]$ cat elf/tst-tls9-static.c
> >#include "tst-tls9.c"
> >[hjl@gnu-cfl-2 x86-glibc]$
> >
> >to test both dynamic and static libc. If we want to use a single
> >source, we should create
> >a framework to cover all such tests.
>
> OK. Dropped cp $< $@ and .INTERMEDIATE
>
>
> From e937ae26a4a9a8ff6b1198f347f0b141a9285305 Mon Sep 17 00:00:00 2001
> From: Fangrui Song <maskray@google.com>
> Date: Tue, 6 Apr 2021 14:45:01 -0700
> Subject: [PATCH] Set the retain attribute on _elf_set_element if CC supports
> [BZ #27492]
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
>
> 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).
> ---
> config.h.in | 3 ++
> configure | 59 ++++++++++++++++++++++
> configure.ac | 21 ++++++++
> include/libc-symbols.h | 14 +++--
> libio/Makefile | 28 ++++++++++
> libio/tst-cleanup-default-static.c | 1 +
> libio/tst-cleanup-default.c | 1 +
> libio/tst-cleanup-nostart-stop-gc-static.c | 1 +
> libio/tst-cleanup-nostart-stop-gc.c | 1 +
> libio/tst-cleanup-start-stop-gc-static.c | 1 +
> libio/tst-cleanup-start-stop-gc.c | 1 +
> libio/tst-cleanup.c | 34 +++++++++++++
> libio/tst-cleanup.exp | 1 +
> 13 files changed, 162 insertions(+), 4 deletions(-)
> create mode 100644 libio/tst-cleanup-default-static.c
> create mode 100644 libio/tst-cleanup-default.c
> create mode 100644 libio/tst-cleanup-nostart-stop-gc-static.c
> create mode 100644 libio/tst-cleanup-nostart-stop-gc.c
> create mode 100644 libio/tst-cleanup-start-stop-gc-static.c
> create mode 100644 libio/tst-cleanup-start-stop-gc.c
> create mode 100644 libio/tst-cleanup.c
> create mode 100644 libio/tst-cleanup.exp
>
> diff --git a/config.h.in b/config.h.in
> index ca1547ae67..96a08c7757 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -187,6 +187,9 @@
> /* Define if gcc supports attribute ifunc. */
> #undef HAVE_GCC_IFUNC
>
> +/* Define if CC supports attribute retain. */
> +#undef HAVE_GNU_RETAIN
> +
> /* Define if the linker defines __ehdr_start. */
> #undef HAVE_EHDR_START
>
> diff --git a/configure b/configure
> index fcf43bf7de..e64b7f8efe 100755
> --- a/configure
> +++ b/configure
> @@ -4105,6 +4105,31 @@ fi
> $as_echo "$libc_cv_textrel_ifunc" >&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; }
> @@ -5871,6 +5896,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
> 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],
> diff --git a/include/libc-symbols.h b/include/libc-symbols.h
> index 546fc26a7b..127ea656c2 100644
> --- a/include/libc-symbols.h
> +++ b/include/libc-symbols.h
> @@ -352,6 +352,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. */
> @@ -367,12 +373,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
> diff --git a/libio/Makefile b/libio/Makefile
> index 12ce41038f..ed0ce4ee81 100644
> --- a/libio/Makefile
> +++ b/libio/Makefile
> @@ -195,6 +195,26 @@ ifeq (yes,$(build-shared))
> tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
> $(objpfx)tst-bz24228-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
> @@ -224,6 +244,14 @@ $(objpfx)tst_wprintf2.out: $(gen-locales)
> $(objpfx)tst-wfile-sync.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/; \
> diff --git a/libio/tst-cleanup-default-static.c b/libio/tst-cleanup-default-static.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-default-static.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-default.c b/libio/tst-cleanup-default.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-default.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-nostart-stop-gc-static.c b/libio/tst-cleanup-nostart-stop-gc-static.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-nostart-stop-gc-static.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-nostart-stop-gc.c b/libio/tst-cleanup-nostart-stop-gc.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-nostart-stop-gc.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-start-stop-gc-static.c b/libio/tst-cleanup-start-stop-gc-static.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-start-stop-gc-static.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup-start-stop-gc.c b/libio/tst-cleanup-start-stop-gc.c
> new file mode 100644
> index 0000000000..c39956e2a8
> --- /dev/null
> +++ b/libio/tst-cleanup-start-stop-gc.c
> @@ -0,0 +1 @@
> +#include "tst-cleanup.c"
> diff --git a/libio/tst-cleanup.c b/libio/tst-cleanup.c
> new file mode 100644
> index 0000000000..837feac164
> --- /dev/null
> +++ b/libio/tst-cleanup.c
> @@ -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);
> +}
> diff --git a/libio/tst-cleanup.exp b/libio/tst-cleanup.exp
> new file mode 100644
> index 0000000000..ce01362503
> --- /dev/null
> +++ b/libio/tst-cleanup.exp
> @@ -0,0 +1 @@
> +hello
> --
> 2.31.0.208.g409f899ff0-goog
>
LGTM.
Thanks.
--
H.J.
^ permalink raw reply [flat|nested] 40+ messages in thread
end of thread, other threads:[~2021-04-16 13:01 UTC | newest]
Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-15 1:10 [PATCH] Set the retain attribute on _elf_set_element if CC supports [BZ #27492] Fangrui Song
2021-03-15 7:28 ` Florian Weimer
2021-03-15 7:45 ` Fāng-ruì Sòng
2021-03-15 8:13 ` Florian Weimer
2021-03-22 4:00 ` [PATCH v2] " Fangrui Song
2021-03-22 4:24 ` H.J. Lu
2021-03-22 4:40 ` Fangrui Song
2021-03-22 20:28 ` H.J. Lu
2021-03-23 4:14 ` Fangrui Song
2021-03-29 23:11 ` H.J. Lu
2021-03-29 23:24 ` [PATCH v3] " Fangrui Song
2021-03-30 18:17 ` H.J. Lu
2021-03-30 19:17 ` Fāng-ruì Sòng
2021-03-30 19:30 ` H.J. Lu
2021-03-31 4:34 ` Fāng-ruì Sòng
2021-03-31 16:17 ` H.J. Lu
2021-03-31 18:09 ` Fāng-ruì Sòng
2021-03-31 18:57 ` H.J. Lu
2021-03-31 19:39 ` [PATCH v4] " Fangrui Song
2021-03-31 23:38 ` H.J. Lu
2021-04-01 0:02 ` Fangrui Song
2021-04-01 1:00 ` H.J. Lu
2021-04-01 1:06 ` [PATCH v5] " Fangrui Song
2021-04-01 12:52 ` H.J. Lu
2021-04-02 3:23 ` Fangrui Song
2021-04-02 14:14 ` H.J. Lu
2021-04-02 17:09 ` Fangrui Song
2021-04-02 17:33 ` H.J. Lu
2021-04-03 18:02 ` Fangrui Song
2021-04-03 20:47 ` H.J. Lu
2021-04-03 21:57 ` Fangrui Song
2021-04-05 1:55 ` H.J. Lu
2021-04-05 18:17 ` Fangrui Song
2021-04-05 20:35 ` H.J. Lu
2021-04-05 21:03 ` Fangrui Song
2021-04-05 21:58 ` H.J. Lu
2021-04-06 21:46 ` Fangrui Song
2021-04-09 22:36 ` Fāng-ruì Sòng
2021-04-16 3:51 ` Fāng-ruì Sòng
2021-04-16 13:00 ` H.J. Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).