/* Support macros for making weak and strong aliases for symbols,
and for using symbol sets and linker warnings with GNU ld.
- Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ Copyright (C) 1995-2019 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
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ <https://www.gnu.org/licenses/>. */
#ifndef _LIBC_SYMBOLS_H
#define _LIBC_SYMBOLS_H 1
# define ASM_LINE_SEP ;
#endif
+#ifndef __attribute_copy__
+/* Provide an empty definition when cdefs.h is not included. */
+# define __attribute_copy__(arg)
+#endif
+
#ifndef __ASSEMBLER__
/* GCC understands weak symbols and aliases; use its interface where
possible, instead of embedded assembly language. */
/* Define ALIASNAME as a strong alias for NAME. */
# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
# define _strong_alias(name, aliasname) \
- extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+ extern __typeof (name) aliasname __attribute__ ((alias (#name))) \
+ __attribute_copy__ (name);
/* This comes between the return type and function name in
a function definition to make that definition weak. */
If weak aliases are not available, this defines a strong alias. */
# define weak_alias(name, aliasname) _weak_alias (name, aliasname)
# define _weak_alias(name, aliasname) \
- extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
+ extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))) \
+ __attribute_copy__ (name);
/* Same as WEAK_ALIAS, but mark symbol as hidden. */
# define weak_hidden_alias(name, aliasname) \
_weak_hidden_alias (name, aliasname)
# define _weak_hidden_alias(name, aliasname) \
extern __typeof (name) aliasname \
- __attribute__ ((weak, alias (#name), __visibility__ ("hidden")));
+ __attribute__ ((weak, alias (#name), __visibility__ ("hidden"))) \
+ __attribute_copy__ (name);
/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */
# define weak_extern(symbol) _weak_extern (weak symbol)
#endif /* __ASSEMBLER__ */
-/* On some platforms we can make internal function calls (i.e., calls of
- functions not exported) a bit faster by using a different calling
- convention. */
-#ifndef internal_function
-# define internal_function /* empty */
-#endif
-
/* Determine the return address. */
#define RETURN_ADDRESS(nr) \
__builtin_extract_return_addr (__builtin_return_address (nr))
static const char __evoke_link_warning_##symbol[] \
__attribute__ ((used, section (".gnu.warning." #symbol __sec_comment))) \
= msg;
-#define libc_freeres_ptr(decl) \
- __make_section_unallocated ("__libc_freeres_ptrs, \"aw\", %nobits") \
- decl __attribute__ ((section ("__libc_freeres_ptrs" __sec_comment)))
-#define __libc_freeres_fn_section \
- __attribute__ ((section ("__libc_freeres_fn")))
-
-#define libc_freeres_fn(name) \
- static void name (void) __attribute_used__ __libc_freeres_fn_section; \
- text_set_element (__libc_subfreeres, name); \
- static void name (void)
/* A canned warning for sysdeps/stub functions. */
#define stub_warning(name) \
for linking")
#endif
+/* Resource Freeing Hooks:
+
+ Normally a process exits and the OS cleans up any allocated
+ memory. However, when tooling like mtrace or valgrind is monitoring
+ the process we need to free all resources that are part of the
+ process in order to provide the consistency required to track
+ memory leaks.
+
+ A single public API exists and is __libc_freeres(), and this is used
+ by applications like valgrind to freee resouces.
+
+ There are 3 cases:
+
+ (a) __libc_freeres
+
+ In this case all you need to do is define the freeing routine:
+
+ foo.c:
+ libfoo_freeres_fn (foo_freeres)
+ {
+ complex_free (mem);
+ }
+
+ This ensures the function is called at the right point to free
+ resources.
+
+ (b) __libc_freeres_ptr
+
+ The framework for (a) iterates over the list of pointers-to-free
+ in (b) and frees them.
+
+ foo.c:
+ libc_freeres_ptr (static char *foo_buffer);
+
+ Freeing these resources alaways happens last and is equivalent
+ to registering a function that does 'free (foo_buffer)'.
+
+ (c) Explicit lists of free routines to call or objects to free.
+
+ It is the intended goal to remove (a) and (b) which have some
+ non-determinism based on link order, and instead use explicit
+ lists of functions and frees to resolve cleanup ordering issues
+ and make it easy to debug and maintain.
+
+ As of today the following subsystems use (c):
+
+ Per-thread cleanup:
+ * malloc/thread-freeres.c
+
+ libdl cleanup:
+ * dlfcn/dlfreeres.c
+
+ libpthread cleanup:
+ * nptl/nptlfreeres.c
+
+ So if you need any shutdown routines to run you should add them
+ directly to the appropriate subsystem's shutdown list. */
+
+/* Resource pointers to free in libc.so. */
+#define libc_freeres_ptr(decl) \
+ __make_section_unallocated ("__libc_freeres_ptrs, \"aw\", %nobits") \
+ decl __attribute__ ((section ("__libc_freeres_ptrs" __sec_comment)))
+
+/* Resource freeing functions from libc.so go in this section. */
+#define __libc_freeres_fn_section \
+ __attribute__ ((section ("__libc_freeres_fn")))
+
+/* Resource freeing functions for libc.so. */
+#define libc_freeres_fn(name) \
+ static void name (void) __attribute_used__ __libc_freeres_fn_section; \
+ text_set_element (__libc_subfreeres, name); \
+ static void name (void)
+
/* Declare SYMBOL to be TYPE (`function' or `object') of SIZE bytes
alias to ORIGINAL, when the assembler supports such declarations
(such as in ELF).
# define __hidden_asmname1(prefix, name) __hidden_asmname2(prefix, name)
# define __hidden_asmname2(prefix, name) #prefix name
# define __hidden_ver1(local, internal, name) \
- extern __typeof (name) __EI_##name __asm__(__hidden_asmname (#internal)); \
- extern __typeof (name) __EI_##name \
- __attribute__((alias (__hidden_asmname (#local))))
+ __hidden_ver2 (, local, internal, name)
+# define __hidden_ver2(thread, local, internal, name) \
+ extern thread __typeof (name) __EI_##name \
+ __asm__(__hidden_asmname (#internal)); \
+ extern thread __typeof (name) __EI_##name \
+ __attribute__((alias (__hidden_asmname (#local)))) \
+ __attribute_copy__ (name)
# define hidden_ver(local, name) __hidden_ver1(local, __GI_##name, name);
# define hidden_data_ver(local, name) hidden_ver(local, name)
# define hidden_def(name) __hidden_ver1(__GI_##name, name, name);
# define hidden_data_def(name) hidden_def(name)
+# define hidden_tls_def(name) \
+ __hidden_ver2 (__thread, __GI_##name, name, name);
# define hidden_weak(name) \
__hidden_ver1(__GI_##name, name, name) __attribute__((weak));
# define hidden_data_weak(name) hidden_weak(name)
# define __hidden_nolink1(local, internal, name, version) \
__hidden_nolink2 (local, internal, name, version)
# define __hidden_nolink2(local, internal, name, version) \
- extern __typeof (name) internal __attribute__ ((alias (#local))); \
+ extern __typeof (name) internal __attribute__ ((alias (#local))) \
+ __attribute_copy__ (name); \
__hidden_nolink3 (local, internal, #name "@" #version)
# define __hidden_nolink3(local, internal, vername) \
__asm__ (".symver " #internal ", " vername);
# define hidden_weak(name) hidden_def (name)
# define hidden_ver(local, name) strong_alias (local, __GI_##name)
# define hidden_data_def(name) strong_data_alias (name, __GI_##name)
+# define hidden_tls_def(name) hidden_data_def (name)
# define hidden_data_weak(name) hidden_data_def (name)
# define hidden_data_ver(local, name) strong_data_alias (local, __GI_##name)
# define HIDDEN_JUMPTARGET(name) __GI_##name
# endif
#else
# ifndef __ASSEMBLER__
-# define hidden_proto(name, attrs...)
-# define hidden_tls_proto(name, attrs...)
+# if !defined SHARED && IS_IN (libc) && !defined LIBC_NONSHARED \
+ && (!defined PIC || !defined NO_HIDDEN_EXTERN_FUNC_IN_PIE) \
+ && !defined NO_HIDDEN
+# define __hidden_proto_hiddenattr(attrs...) \
+ __attribute__ ((visibility ("hidden"), ##attrs))
+# define hidden_proto(name, attrs...) \
+ __hidden_proto (name, , name, ##attrs)
+# define hidden_tls_proto(name, attrs...) \
+ __hidden_proto (name, __thread, name, ##attrs)
+# define __hidden_proto(name, thread, internal, attrs...) \
+ extern thread __typeof (name) name __hidden_proto_hiddenattr (attrs);
+# else
+# define hidden_proto(name, attrs...)
+# define hidden_tls_proto(name, attrs...)
+# endif
# else
# define HIDDEN_JUMPTARGET(name) JUMPTARGET(name)
# endif /* Not __ASSEMBLER__ */
# define hidden_ver(local, name)
# define hidden_data_weak(name)
# define hidden_data_def(name)
+# define hidden_tls_def(name)
# define hidden_data_ver(local, name)
# define hidden_nolink(name, lib, version)
#endif
# endif
# define libc_hidden_ver(local, name) hidden_ver (local, name)
# define libc_hidden_data_def(name) hidden_data_def (name)
+# define libc_hidden_tls_def(name) hidden_tls_def (name)
# define libc_hidden_data_weak(name) hidden_data_weak (name)
# define libc_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define libc_hidden_weak(name)
# define libc_hidden_ver(local, name)
# define libc_hidden_data_def(name)
+# define libc_hidden_tls_def(name)
# define libc_hidden_data_weak(name)
# define libc_hidden_data_ver(local, name)
#endif
-#if IS_IN (rtld)
+#if IS_IN (rtld) && !defined NO_RTLD_HIDDEN
# define rtld_hidden_proto(name, attrs...) hidden_proto (name, ##attrs)
# define rtld_hidden_tls_proto(name, attrs...) hidden_tls_proto (name, ##attrs)
# define rtld_hidden_def(name) hidden_def (name)
# define rtld_hidden_weak(name) hidden_weak (name)
# define rtld_hidden_ver(local, name) hidden_ver (local, name)
# define rtld_hidden_data_def(name) hidden_data_def (name)
+# define rtld_hidden_tls_def(name) hidden_tls_def (name)
# define rtld_hidden_data_weak(name) hidden_data_weak (name)
# define rtld_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define rtld_hidden_weak(name)
# define rtld_hidden_ver(local, name)
# define rtld_hidden_data_def(name)
+# define rtld_hidden_tls_def(name)
# define rtld_hidden_data_weak(name)
# define rtld_hidden_data_ver(local, name)
#endif
# define libm_hidden_weak(name) hidden_weak (name)
# define libm_hidden_ver(local, name) hidden_ver (local, name)
# define libm_hidden_data_def(name) hidden_data_def (name)
+# define libm_hidden_tls_def(name) hidden_tls_def (name)
# define libm_hidden_data_weak(name) hidden_data_weak (name)
# define libm_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define libm_hidden_weak(name)
# define libm_hidden_ver(local, name)
# define libm_hidden_data_def(name)
+# define libm_hidden_tls_def(name)
# define libm_hidden_data_weak(name)
# define libm_hidden_data_ver(local, name)
#endif
# define libmvec_hidden_weak(name) hidden_weak (name)
# define libmvec_hidden_ver(local, name) hidden_ver (local, name)
# define libmvec_hidden_data_def(name) hidden_data_def (name)
+# define libmvec_hidden_tls_def(name) hidden_tls_def (name)
# define libmvec_hidden_data_weak(name) hidden_data_weak (name)
# define libmvec_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define libmvec_hidden_weak(name)
# define libmvec_hidden_ver(local, name)
# define libmvec_hidden_data_def(name)
+# define libmvec_hidden_tls_def(name)
# define libmvec_hidden_data_weak(name)
# define libmvec_hidden_data_ver(local, name)
#endif
# define libresolv_hidden_weak(name) hidden_weak (name)
# define libresolv_hidden_ver(local, name) hidden_ver (local, name)
# define libresolv_hidden_data_def(name) hidden_data_def (name)
+# define libresolv_hidden_tls_def(name) hidden_tls_def (name)
# define libresolv_hidden_data_weak(name) hidden_data_weak (name)
# define libresolv_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define libresolv_hidden_weak(name)
# define libresolv_hidden_ver(local, name)
# define libresolv_hidden_data_def(name)
+# define libresolv_hidden_tls_def(name)
# define libresolv_hidden_data_weak(name)
# define libresolv_hidden_data_ver(local, name)
#endif
# define librt_hidden_weak(name) hidden_weak (name)
# define librt_hidden_ver(local, name) hidden_ver (local, name)
# define librt_hidden_data_def(name) hidden_data_def (name)
+# define librt_hidden_tls_def(name) hidden_tls_def (name)
# define librt_hidden_data_weak(name) hidden_data_weak (name)
# define librt_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define librt_hidden_weak(name)
# define librt_hidden_ver(local, name)
# define librt_hidden_data_def(name)
+# define librt_hidden_tls_def(name)
# define librt_hidden_data_weak(name)
# define librt_hidden_data_ver(local, name)
#endif
# define libdl_hidden_weak(name) hidden_weak (name)
# define libdl_hidden_ver(local, name) hidden_ver (local, name)
# define libdl_hidden_data_def(name) hidden_data_def (name)
+# define libdl_hidden_tls_def(name) hidden_tls_def (name)
# define libdl_hidden_data_weak(name) hidden_data_weak (name)
# define libdl_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define libdl_hidden_weak(name)
# define libdl_hidden_ver(local, name)
# define libdl_hidden_data_def(name)
+# define libdl_hidden_tls_def(name)
# define libdl_hidden_data_weak(name)
# define libdl_hidden_data_ver(local, name)
#endif
# define libnss_files_hidden_weak(name) hidden_weak (name)
# define libnss_files_hidden_ver(local, name) hidden_ver (local, name)
# define libnss_files_hidden_data_def(name) hidden_data_def (name)
+# define libnss_files_hidden_tls_def(name) hidden_tls_def (name)
# define libnss_files_hidden_data_weak(name) hidden_data_weak (name)
# define libnss_files_hidden_data_ver(local, name) hidden_data_ver(local, name)
#else
# define libnss_files_hidden_weak(name)
# define libnss_files_hidden_ver(local, name)
# define libnss_files_hidden_data_def(name)
+# define libnss_files_hidden_tls_def(name)
# define libnss_files_hidden_data_weak(name)
# define libnss_files_hidden_data_ver(local, name)
#endif
# define libnsl_hidden_weak(name) hidden_weak (name)
# define libnsl_hidden_ver(local, name) hidden_ver (local, name)
# define libnsl_hidden_data_def(name) hidden_data_def (name)
+# define libnsl_hidden_tls_def(name) hidden_tls_def (name)
# define libnsl_hidden_data_weak(name) hidden_data_weak (name)
# define libnsl_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define libnsl_hidden_weak(name)
# define libnsl_hidden_ver(local, name)
# define libnsl_hidden_data_def(name)
+# define libnsl_hidden_tls_def(name)
# define libnsl_hidden_data_weak(name)
# define libnsl_hidden_data_ver(local, name)
#endif
# define libnss_nisplus_hidden_weak(name) hidden_weak (name)
# define libnss_nisplus_hidden_ver(local, name) hidden_ver (local, name)
# define libnss_nisplus_hidden_data_def(name) hidden_data_def (name)
+# define libnss_nisplus_hidden_tls_def(name) hidden_tls_def (name)
# define libnss_nisplus_hidden_data_weak(name) hidden_data_weak (name)
# define libnss_nisplus_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define libnss_nisplus_hidden_weak(name)
# define libnss_nisplus_hidden_ver(local, name)
# define libnss_nisplus_hidden_data_def(name)
+# define libnss_nisplus_hidden_tls_def(name)
# define libnss_nisplus_hidden_data_weak(name)
# define libnss_nisplus_hidden_data_ver(local, name)
#endif
# define libutil_hidden_weak(name) hidden_weak (name)
# define libutil_hidden_ver(local, name) hidden_ver (local, name)
# define libutil_hidden_data_def(name) hidden_data_def (name)
+# define libutil_hidden_tls_def(name) hidden_tls_def (name)
# define libutil_hidden_data_weak(name) hidden_data_weak (name)
# define libutil_hidden_data_ver(local, name) hidden_data_ver (local, name)
#else
# define libutil_hidden_weak(name)
# define libutil_hidden_ver(local, name)
# define libutil_hidden_data_def(name)
+# define libutil_hidden_tls_def(name)
# define libutil_hidden_data_weak(name)
# define libutil_hidden_data_ver(local, name)
#endif
/* Helper / base macros for indirect function symbols. */
#define __ifunc_resolver(type_name, name, expr, arg, init, classifier) \
- classifier inhibit_stack_protector void *name##_ifunc (arg) \
+ classifier inhibit_stack_protector \
+ __typeof (type_name) *name##_ifunc (arg) \
{ \
init (); \
__typeof (type_name) *res = expr; \
# define __ifunc(type_name, name, expr, arg, init) \
extern __typeof (type_name) name; \
- void *name##_ifunc (arg) __asm__ (#name); \
+ __typeof (type_name) *name##_ifunc (arg) __asm__ (#name); \
__ifunc_resolver (type_name, name, expr, arg, init,) \
__asm__ (".type " #name ", %gnu_indirect_function");