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

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

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

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

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

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Diffstat (limited to 'include')
-rw-r--r--include/libc-symbols.h14
1 files changed, 10 insertions, 4 deletions
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