[RFC,4/6] Mark various functions as __TEXT_STARTUP and __TEXT_EXIT

Message ID 20230515144815.3939017-5-bugaevc@gmail.com
State New
Headers
Series .text.subsections for some questionable benefit |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
redhat-pt-bot/TryBot-still_applies warning Patch no longer applies to master

Commit Message

Sergey Bugaev May 15, 2023, 2:48 p.m. UTC
  The few functions that are only used during exiting (exit, _exit,
quick_exit, _hurd_exit, __run_exit_handlers, _dl_fini, various freemem
functions, and some others) are marked __TEXT_EXIT. The many functions
that are only used on startup are marked __TEXT_STARTUP.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
 csu/check_fds.c                               |  4 +-
 csu/init-first.c                              |  2 +-
 csu/libc-start.c                              |  8 ++--
 csu/libc-tls.c                                |  4 +-
 elf/dl-call-libc-early-init.c                 |  2 +-
 elf/dl-find_object.c                          |  4 +-
 elf/dl-fini.c                                 |  2 +-
 elf/dl-init.c                                 |  2 +-
 elf/dl-libc.c                                 |  2 +-
 elf/dl-libc_freeres.c                         |  2 +-
 elf/dl-load.c                                 |  2 +-
 elf/dl-minimal-malloc.c                       |  8 ++--
 elf/dl-minimal.c                              |  6 +--
 elf/dl-origin.c                               |  2 +-
 elf/dl-reloc-static-pie.c                     |  2 +-
 elf/dl-sort-maps.c                            |  2 +-
 elf/dl-support.c                              |  4 +-
 elf/dl-tls.c                                  |  2 +-
 elf/dl-tls_init_tp.c                          |  4 +-
 elf/dl-tunables.c                             | 18 +++----
 elf/dl-usage.c                                |  6 +--
 elf/libc_early_init.c                         |  2 +-
 elf/rtld.c                                    | 42 ++++++++--------
 hurd/hurdinit.c                               |  6 +--
 hurd/hurdstartup.c                            |  2 +-
 hurd/lookup-retry.c                           |  3 ++
 iconv/gconv_cache.c                           |  2 +-
 iconv/gconv_conf.c                            |  2 +-
 iconv/gconv_db.c                              |  4 +-
 iconv/gconv_dl.c                              |  2 +-
 intl/dcigettext.c                             |  2 +-
 intl/finddomain.c                             |  2 +-
 intl/localealias.c                            |  2 +-
 libio/genops.c                                |  4 +-
 mach/mach_init.c                              |  2 +-
 mach/mig-reply.c                              |  2 +-
 malloc/set-freeres.c                          |  2 +-
 misc/fstab.c                                  |  2 +-
 misc/init-misc.c                              |  2 +-
 nptl/pthread_mutex_conf.c                     |  8 ++--
 nscd/nscd_getgr_r.c                           |  2 +-
 nscd/nscd_gethst_r.c                          |  2 +-
 nscd/nscd_getpw_r.c                           |  2 +-
 nscd/nscd_getserv_r.c                         |  2 +-
 nscd/nscd_netgroup.c                          |  2 +-
 nss/nss_action.c                              |  2 +-
 nss/nss_database.c                            |  2 +-
 nss/nss_module.c                              |  2 +-
 posix/_exit.c                                 |  2 +-
 posix/regcomp.c                               |  2 +-
 posix/register-atfork.c                       |  2 +-
 resolv/gai_misc.c                             |  2 +-
 resolv/resolv_conf.c                          |  2 +-
 rt/aio_misc.c                                 |  2 +-
 stdio-common/reg-modifier.c                   |  2 +-
 stdlib/exit.c                                 |  4 +-
 stdlib/fmtmsg.c                               |  2 +-
 stdlib/quick_exit.c                           |  2 +-
 stdlib/setenv.c                               |  2 +-
 sunrpc/clnt_perr.c                            |  2 +-
 sysdeps/aarch64/dl-machine.h                  |  2 +-
 sysdeps/alpha/dl-machine.h                    |  2 +-
 sysdeps/arm/dl-machine.h                      |  2 +-
 sysdeps/csky/dl-machine.h                     |  2 +-
 sysdeps/generic/dl-call_tls_init_tp.h         |  2 +-
 sysdeps/hppa/dl-machine.h                     |  2 +-
 sysdeps/i386/dl-machine.h                     |  2 +-
 sysdeps/mach/hurd/_exit.c                     |  4 +-
 sysdeps/mach/hurd/dl-sysdep.c                 | 48 +++++++++----------
 sysdeps/mach/hurd/i386/tls.h                  |  2 +-
 sysdeps/mach/hurd/mig-reply.c                 |  2 +-
 sysdeps/mach/hurd/x86/init-first.c            | 12 ++---
 sysdeps/mach/hurd/x86_64/tls.h                |  2 +-
 sysdeps/mips/dl-machine.h                     |  2 +-
 sysdeps/nptl/dl-mutex.c                       |  2 +-
 sysdeps/nptl/dl-tls_init_tp.c                 |  4 +-
 sysdeps/nptl/pthread_early_init.h             |  2 +-
 sysdeps/or1k/dl-machine.h                     |  2 +-
 sysdeps/posix/getaddrinfo.c                   |  2 +-
 sysdeps/powerpc/cpu-features.c                |  2 +-
 sysdeps/powerpc/powerpc32/dl-machine.h        |  2 +-
 sysdeps/powerpc/powerpc64/dl-machine.h        |  2 +-
 sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h |  2 +-
 sysdeps/s390/cpu-features.c                   |  4 +-
 sysdeps/s390/s390-32/dl-machine.h             |  2 +-
 sysdeps/s390/s390-64/dl-hwcap-check.h         |  2 +-
 sysdeps/s390/s390-64/dl-machine.h             |  2 +-
 sysdeps/sh/dl-machine.h                       |  2 +-
 sysdeps/unix/sysv/linux/_exit.c               |  2 +-
 .../unix/sysv/linux/aarch64/cpu-features.c    |  4 +-
 sysdeps/unix/sysv/linux/check_pf.c            |  2 +-
 sysdeps/unix/sysv/linux/dl-sysdep.c           |  8 ++--
 sysdeps/unix/sysv/linux/x86/cpu-features.c    |  2 +-
 sysdeps/x86/cpu-features.c                    | 10 ++--
 sysdeps/x86/cpu-tunables.c                    |  6 +--
 sysdeps/x86/dl-cacheinfo.h                    | 14 +++---
 sysdeps/x86/dl-get-cpu-features.c             |  2 +-
 sysdeps/x86_64/dl-machine.h                   |  2 +-
 time/tzset.c                                  |  2 +-
 99 files changed, 199 insertions(+), 196 deletions(-)
  

Patch

diff --git a/csu/check_fds.c b/csu/check_fds.c
index 59565f92..e4a80856 100644
--- a/csu/check_fds.c
+++ b/csu/check_fds.c
@@ -36,7 +36,7 @@ 
 
 /* Should other OSes (e.g., Hurd) have different versions which can
    be written in a better way?  */
-static void
+static void __TEXT_STARTUP
 check_one_fd (int fd, int mode)
 {
   if (__builtin_expect (__fcntl64_nocancel (fd, F_GETFD), 0) == -1
@@ -83,7 +83,7 @@  check_one_fd (int fd, int mode)
 }
 
 
-void
+void __TEXT_STARTUP
 __libc_check_standard_fds (void)
 {
   /* Check all three standard file descriptors.  The O_NOFOLLOW flag
diff --git a/csu/init-first.c b/csu/init-first.c
index 4544eb6d..de1fd749 100644
--- a/csu/init-first.c
+++ b/csu/init-first.c
@@ -34,7 +34,7 @@  int __libc_argc attribute_hidden;
 char **__libc_argv attribute_hidden;
 
 
-void
+void __TEXT_STARTUP
 __libc_init_first (int argc, char **argv, char **envp)
 {
 #ifdef SHARED
diff --git a/csu/libc-start.c b/csu/libc-start.c
index c3bb6d09..2be7b491 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -72,7 +72,7 @@  uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
 #  define IREL		elf_irel
 # endif
 
-static void
+static void __TEXT_STARTUP
 apply_irel (void)
 {
 # ifdef IREL
@@ -121,7 +121,7 @@  apply_irel (void)
 #ifdef SHARED
 /* Initialization for dynamic executables.  Find the main executable
    link map and run its init functions.  */
-static void
+static void __TEXT_STARTUP
 call_init (int argc, char **argv, char **env)
 {
   /* Obtain the main map of the executable.  */
@@ -169,7 +169,7 @@  extern void _fini (void);
 
 /* Initialization for static executables.  There is no dynamic
    segment, so we access the symbols directly.  */
-static void
+static void __TEXT_STARTUP
 call_init (int argc, char **argv, char **envp)
 {
   /* For static executables, preinit happens right before init.  */
@@ -230,7 +230,7 @@  STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
    For dynamically linked executables, the dynamic segment is used to
    locate constructors and destructors.  For statically linked
    executables, the relevant symbols are access directly.  */
-STATIC int
+STATIC int __TEXT_STARTUP
 LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 		 int argc, char **argv,
 #ifdef LIBC_START_MAIN_AUXVEC_ARG
diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index cdf6442c..ec68de0e 100644
--- a/csu/libc-tls.c
+++ b/csu/libc-tls.c
@@ -86,7 +86,7 @@  init_slotinfo (void)
   GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo;
 }
 
-static void
+static void __TEXT_STARTUP
 init_static_tls (size_t memsz, size_t align)
 {
   /* That is the size of the TLS memory for this object.  */
@@ -102,7 +102,7 @@  init_static_tls (size_t memsz, size_t align)
   GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
 }
 
-void
+void __TEXT_STARTUP
 __libc_setup_tls (void)
 {
   void *tlsblock;
diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c
index 144a7442..927c3099 100644
--- a/elf/dl-call-libc-early-init.c
+++ b/elf/dl-call-libc-early-init.c
@@ -22,7 +22,7 @@ 
 #include <link.h>
 #include <stddef.h>
 
-void
+void __TEXT_STARTUP
 _dl_call_libc_early_init (struct link_map *libc_map, _Bool initial)
 {
   /* There is nothing to do if we did not actually load libc.so.  */
diff --git a/elf/dl-find_object.c b/elf/dl-find_object.c
index 2ced2f35..90ef5d3b 100644
--- a/elf/dl-find_object.c
+++ b/elf/dl-find_object.c
@@ -469,7 +469,7 @@  rtld_hidden_def (_dl_find_object)
    sizes from the initial loaded mappings.  Second to fill in the
    bases and infos arrays with the (still unsorted) data.  Returns the
    number of loaded (non-nodelete) mappings.  */
-static size_t
+static size_t __TEXT_STARTUP
 _dlfo_process_initial (void)
 {
   struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
@@ -556,7 +556,7 @@  _dlfo_sort_mappings (struct dl_find_object_internal *objects, size_t size)
     }
 }
 
-void
+void __TEXT_STARTUP
 _dl_find_object_init (void)
 {
   /* Cover the main mapping.  */
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 9acb64f4..d8c1bacd 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -21,7 +21,7 @@ 
 #include <ldsodefs.h>
 #include <elf-initfini.h>
 
-void
+void __TEXT_EXIT
 _dl_fini (void)
 {
   /* Lots of fun ahead.  We have to call the destructors for all still
diff --git a/elf/dl-init.c b/elf/dl-init.c
index 5b073259..1acad014 100644
--- a/elf/dl-init.c
+++ b/elf/dl-init.c
@@ -72,7 +72,7 @@  call_init (struct link_map *l, int argc, char **argv, char **env)
 }
 
 
-void
+void __TEXT_STARTUP
 _dl_init (struct link_map *main_map, int argc, char **argv, char **env)
 {
   ElfW(Dyn) *preinit_array = main_map->l_info[DT_PREINIT_ARRAY];
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index c12e52f3..c7993e4a 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -256,7 +256,7 @@  free_slotinfo (struct dtv_slotinfo_list **elemp)
 }
 
 
-void
+void __TEXT_EXIT
 __dl_libc_freemem (void)
 {
   struct link_map *l;
diff --git a/elf/dl-libc_freeres.c b/elf/dl-libc_freeres.c
index d6d824ac..8f600cfa 100644
--- a/elf/dl-libc_freeres.c
+++ b/elf/dl-libc_freeres.c
@@ -19,7 +19,7 @@ 
 #include <ldsodefs.h>
 #include <dl-find_object.h>
 
-void
+void __TEXT_EXIT
 __rtld_libc_freeres (void)
 {
   _dl_find_object_freeres ();
diff --git a/elf/dl-load.c b/elf/dl-load.c
index d15cad2d..b5eed23a 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -699,7 +699,7 @@  cache_rpath (struct link_map *l,
 }
 
 
-void
+void __TEXT_STARTUP
 _dl_init_paths (const char *llp, const char *source,
 		const char *glibc_hwcaps_prepend,
 		const char *glibc_hwcaps_mask)
diff --git a/elf/dl-minimal-malloc.c b/elf/dl-minimal-malloc.c
index 27549645..5ee80163 100644
--- a/elf/dl-minimal-malloc.c
+++ b/elf/dl-minimal-malloc.c
@@ -30,7 +30,7 @@ 
 static void *alloc_ptr, *alloc_end, *alloc_last_block;
 
 /* Allocate an aligned memory block.  */
-void *
+void * __TEXT_STARTUP
 __minimal_malloc (size_t n)
 {
   if (alloc_end == 0)
@@ -73,7 +73,7 @@  __minimal_malloc (size_t n)
 /* We use this function occasionally since the real implementation may
    be optimized when it can assume the memory it returns already is
    set to NUL.  */
-void *
+void * __TEXT_STARTUP
 __minimal_calloc (size_t nmemb, size_t size)
 {
   /* New memory from the trivial malloc above is always already cleared.
@@ -90,7 +90,7 @@  __minimal_calloc (size_t nmemb, size_t size)
 }
 
 /* This will rarely be called.  */
-void
+void __TEXT_STARTUP
 __minimal_free (void *ptr)
 {
   /* We can free only the last block allocated.  */
@@ -104,7 +104,7 @@  __minimal_free (void *ptr)
 }
 
 /* This is only called with the most recent block returned by malloc.  */
-void *
+void * __TEXT_STARTUP
 __minimal_realloc (void *ptr, size_t n)
 {
   if (ptr == NULL)
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
index dc267519..88f91aa4 100644
--- a/elf/dl-minimal.c
+++ b/elf/dl-minimal.c
@@ -37,7 +37,7 @@  __typeof (free) *__rtld_free attribute_relro;
 __typeof (malloc) *__rtld_malloc attribute_relro;
 __typeof (realloc) *__rtld_realloc attribute_relro;
 
-void
+void __TEXT_STARTUP
 __rtld_malloc_init_stubs (void)
 {
   __rtld_calloc = &__minimal_calloc;
@@ -55,7 +55,7 @@  __rtld_malloc_is_complete (void)
 }
 
 /* Lookup NAME at VERSION in the scope of MATCH.  */
-static void *
+static void * __TEXT_STARTUP
 lookup_malloc_symbol (struct link_map *main_map, const char *name,
 		      struct r_found_version *version)
 {
@@ -71,7 +71,7 @@  lookup_malloc_symbol (struct link_map *main_map, const char *name,
   return _dl_sym_post (result, ref, value, 0, main_map);
 }
 
-void
+void __TEXT_STARTUP
 __rtld_malloc_init_real (struct link_map *main_map)
 {
   /* We cannot use relocations and initializers for this because the
diff --git a/elf/dl-origin.c b/elf/dl-origin.c
index 114a207d..47fdc4ec 100644
--- a/elf/dl-origin.c
+++ b/elf/dl-origin.c
@@ -24,7 +24,7 @@ 
 #include <dl-dst.h>
 
 
-const char *
+const char * __TEXT_STARTUP
 _dl_get_origin (void)
 {
   char *result = (char *) -1;
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
index a143ee5a..c31a9b05 100644
--- a/elf/dl-reloc-static-pie.c
+++ b/elf/dl-reloc-static-pie.c
@@ -32,7 +32,7 @@ 
 
 /* Relocate static executable with PIE.  */
 
-void
+void __TEXT_STARTUP
 _dl_relocate_static_pie (void)
 {
   struct link_map *main_map = _dl_get_dl_main_map ();
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index 5616c8a6..d4b9a343 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -285,7 +285,7 @@  _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
     }
 }
 
-void
+void __TEXT_STARTUP
 _dl_sort_maps_init (void)
 {
   int32_t algorithm = TUNABLE_GET (glibc, rtld, dynamic_sort, int32_t, NULL);
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 32259991..8c5a4e54 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -231,7 +231,7 @@  __rtld_lock_define_initialized_recursive (, _dl_load_tls_lock)
 
 int _dl_clktck;
 
-void
+void __TEXT_STARTUP
 _dl_aux_init (ElfW(auxv_t) *av)
 {
 #ifdef NEED_DL_SYSINFO
@@ -269,7 +269,7 @@  _dl_aux_init (ElfW(auxv_t) *av)
 #endif
 
 
-void
+void __TEXT_STARTUP
 _dl_non_dynamic_init (void)
 {
   _dl_main_map.l_origin = _dl_get_origin ();
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 5e198499..c04fd3d9 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -92,7 +92,7 @@  tls_static_surplus (int nns, int opt_tls)
 /* Calculate the size of the static TLS surplus, when the given
    number of audit modules are loaded.  Must be called after the
    number of audit modules is known and before static TLS allocation.  */
-void
+void __TEXT_STARTUP
 _dl_tls_static_surplus_init (size_t naudit)
 {
   size_t nns, opt_tls;
diff --git a/elf/dl-tls_init_tp.c b/elf/dl-tls_init_tp.c
index e2c50580..42f65d55 100644
--- a/elf/dl-tls_init_tp.c
+++ b/elf/dl-tls_init_tp.c
@@ -33,7 +33,7 @@  rtld_lock_default_unlock_recursive (void *lock)
 }
 #endif
 
-void
+void __TEXT_STARTUP
 __tls_pre_init_tp (void)
 {
 #if !PTHREAD_IN_LIBC
@@ -47,7 +47,7 @@  __tls_pre_init_tp (void)
 #endif
 }
 
-void
+void __TEXT_STARTUP
 __tls_init_tp (void)
 {
 }
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index 62b7332d..71416a0a 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -38,7 +38,7 @@ 
 
 #include <not-errno.h>
 
-static char *
+static char * __TEXT_STARTUP
 tunables_strdup (const char *in)
 {
   size_t i = 0;
@@ -58,7 +58,7 @@  tunables_strdup (const char *in)
   return out;
 }
 
-static char **
+static char ** __TEXT_STARTUP
 get_next_env (char **envp, char **name, size_t *namelen, char **val,
 	      char ***prev_envp)
 {
@@ -86,7 +86,7 @@  get_next_env (char **envp, char **name, size_t *namelen, char **val,
   return NULL;
 }
 
-static void
+static void __TEXT_STARTUP
 do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
 		       const tunable_num_t *minp,
 		       const tunable_num_t *maxp)
@@ -133,7 +133,7 @@  do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
 
 /* Validate range of the input value and initialize the tunable CUR if it looks
    good.  */
-static void
+static void __TEXT_STARTUP
 tunable_initialize (tunable_t *cur, const char *strval)
 {
   tunable_val_t val;
@@ -145,7 +145,7 @@  tunable_initialize (tunable_t *cur, const char *strval)
   do_tunable_update_val (cur, &val, NULL, NULL);
 }
 
-void
+void __TEXT_STARTUP
 __tunable_set_val (tunable_id_t id, tunable_val_t *valp, tunable_num_t *minp,
 		   tunable_num_t *maxp)
 {
@@ -159,7 +159,7 @@  __tunable_set_val (tunable_id_t id, tunable_val_t *valp, tunable_num_t *minp,
    environment variable value for GLIBC_TUNABLES.  VALSTRING is the original
    environment variable string which we use to make NULL terminated values so
    that we don't have to allocate memory again for it.  */
-static void
+static void __TEXT_STARTUP
 parse_tunables (char *tunestr, char *valstring)
 {
   if (tunestr == NULL || *tunestr == '\0')
@@ -255,7 +255,7 @@  parse_tunables (char *tunestr, char *valstring)
    for setuid binaries.  We use the special version of access() to avoid
    setting ERRNO, which is a TLS variable since TLS has not yet been set
    up.  */
-static __always_inline void
+static __always_inline void __TEXT_STARTUP
 maybe_enable_malloc_check (void)
 {
   tunable_id_t id = TUNABLE_ENUM_NAME (glibc, malloc, check);
@@ -266,7 +266,7 @@  maybe_enable_malloc_check (void)
 /* Initialize the tunables list from the environment.  For now we only use the
    ENV_ALIAS to find values.  Later we will also use the tunable names to find
    values.  */
-void
+void __TEXT_STARTUP
 __tunables_init (char **envp)
 {
   char *envname = NULL;
@@ -343,7 +343,7 @@  __tunables_init (char **envp)
     }
 }
 
-void
+void __TEXT_STARTUP
 __tunables_print (void)
 {
   for (int i = 0; i < array_length (tunable_list); i++)
diff --git a/elf/dl-usage.c b/elf/dl-usage.c
index 98f0b0d0..369f3b2c 100644
--- a/elf/dl-usage.c
+++ b/elf/dl-usage.c
@@ -25,7 +25,7 @@ 
 #include <dl-procinfo.h>
 #include <dl-hwcaps.h>
 
-void
+void __TEXT_STARTUP
 _dl_usage (const char *argv0, const char *wrong_option)
 {
   if (wrong_option != NULL)
@@ -36,7 +36,7 @@  _dl_usage (const char *argv0, const char *wrong_option)
   _exit (EXIT_FAILURE);
 }
 
-void
+void __TEXT_STARTUP
 _dl_version (void)
 {
   _dl_printf ("\
@@ -164,7 +164,7 @@  print_hwcaps_subdirectories (const struct dl_main_state *state)
 No subdirectories of glibc-hwcaps directories are searched.\n");
 }
 
-void
+void __TEXT_STARTUP
 _dl_help (const char *argv0, struct dl_main_state *state)
 {
   _dl_printf ("\
diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
index e54d2bb9..7ce7cbdb 100644
--- a/elf/libc_early_init.c
+++ b/elf/libc_early_init.c
@@ -28,7 +28,7 @@ 
 _Bool __libc_initial;
 #endif
 
-void
+void __TEXT_STARTUP
 __libc_early_init (_Bool initial)
 {
   /* Initialize ctype data.  */
diff --git a/elf/rtld.c b/elf/rtld.c
index c1e383b0..5f26ceba 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -199,7 +199,7 @@  audit_list_init (struct audit_list *list)
   list->current_tail = NULL;
 }
 
-static void
+static void __TEXT_STARTUP
 audit_list_add_string (struct audit_list *list, const char *string)
 {
   /* Empty strings do not load anything.  */
@@ -217,7 +217,7 @@  audit_list_add_string (struct audit_list *list, const char *string)
     list->current_tail = string;
 }
 
-static void
+static void __TEXT_STARTUP
 audit_list_add_dynamic_tag (struct audit_list *list, struct link_map *main_map,
 			    unsigned int tag)
 {
@@ -227,7 +227,7 @@  audit_list_add_dynamic_tag (struct audit_list *list, struct link_map *main_map,
     audit_list_add_string (list, strtab + info->d_un.d_val);
 }
 
-static const char *
+static const char * __TEXT_STARTUP
 audit_list_next (struct audit_list *list)
 {
   if (list->current_tail == NULL)
@@ -274,7 +274,7 @@  audit_list_next (struct audit_list *list)
 
 /* Count audit modules before they are loaded so GLRO(dl_naudit)
    is not yet usable.  */
-static size_t
+static size_t __TEXT_STARTUP
 audit_list_count (struct audit_list *list)
 {
   /* Restore the audit_list iterator state at the end.  */
@@ -289,7 +289,7 @@  audit_list_count (struct audit_list *list)
   return naudit;
 }
 
-static void
+static void __TEXT_STARTUP
 dl_main_state_init (struct dl_main_state *state)
 {
   audit_list_init (&state->audit_list);
@@ -444,10 +444,10 @@  RTLD_START
    this function is not inlined (see below).  */
 
 #ifdef DONT_USE_BOOTSTRAP_MAP
-static inline ElfW(Addr) __attribute__ ((always_inline))
+static inline ElfW(Addr) __attribute__ ((always_inline)) __TEXT_STARTUP
 _dl_start_final (void *arg)
 #else
-static ElfW(Addr) __attribute__ ((noinline))
+static ElfW(Addr) __attribute__ ((noinline)) __TEXT_STARTUP
 _dl_start_final (void *arg, struct dl_start_final_info *info)
 #endif
 {
@@ -513,7 +513,7 @@  _dl_start_final (void *arg, struct dl_start_final_info *info)
 # define bootstrap_map info.l
 #endif
 
-static ElfW(Addr) __attribute_used__
+static ElfW(Addr) __attribute_used__ __TEXT_STARTUP
 _dl_start (void *arg)
 {
 #ifdef DONT_USE_BOOTSTRAP_MAP
@@ -730,7 +730,7 @@  match_version (const char *string, struct link_map *map)
 
 bool __rtld_tls_init_tp_called;
 
-static void *
+static void * __TEXT_STARTUP
 init_tls (size_t naudit)
 {
   /* Number of elements in the static TLS block.  */
@@ -800,7 +800,7 @@  cannot allocate TLS data structures for initial thread\n");
   return tcbp;
 }
 
-static unsigned int
+static unsigned int __TEXT_STARTUP
 do_preload (const char *fname, struct link_map *main_map, const char *where)
 {
   const char *objname;
@@ -831,7 +831,7 @@  ERROR: ld.so: object '%s' from %s cannot be preloaded (%s): ignored.\n",
   return 0;
 }
 
-static void
+static void __TEXT_STARTUP
 security_init (void)
 {
   /* Set up the stack checker's canary.  */
@@ -864,7 +864,7 @@  security_init (void)
    (If the binary is running setuid all elements containing a '/' are
    ignored since it is insecure.)  Return the number of preloads
    performed.   Ditto for --preload command argument.  */
-unsigned int
+unsigned int __TEXT_STARTUP
 handle_preload_list (const char *preloadlist, struct link_map *main_map,
 		     const char *where)
 {
@@ -898,7 +898,7 @@  handle_preload_list (const char *preloadlist, struct link_map *main_map,
 /* Called if the audit DSO cannot be used: if it does not have the
    appropriate interfaces, or it expects a more recent version library
    version than what the dynamic linker provides.  */
-static void
+static void __TEXT_STARTUP
 unload_audit_module (struct link_map *map, int original_tls_idx)
 {
 #ifndef NDEBUG
@@ -927,7 +927,7 @@  ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 }
 
 /* Load one audit module.  */
-static void
+static void __TEXT_STARTUP
 load_audit_module (const char *name, struct audit_ifaces **last_audit)
 {
   int original_tls_idx = GL(dl_tls_max_dtv_idx);
@@ -1045,7 +1045,7 @@  ERROR: audit interface '%s' requires version %d (maximum supported version %d);
 }
 
 /* Load all audit modules.  */
-static void
+static void __TEXT_STARTUP
 load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
 {
   struct audit_ifaces *last_audit = NULL;
@@ -1069,7 +1069,7 @@  load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
 
 /* Check if the executable is not actualy dynamically linked, and
    invoke it directly in that case.  */
-static void
+static void __TEXT_STARTUP
 rtld_chain_load (struct link_map *main_map, char *argv0)
 {
   /* The dynamic loader run against itself.  */
@@ -1108,7 +1108,7 @@  rtld_chain_load (struct link_map *main_map, char *argv0)
 
 /* Called to complete the initialization of the link map for the main
    executable.  Returns true if there is a PT_INTERP segment.  */
-static bool
+static bool __TEXT_STARTUP
 rtld_setup_main_map (struct link_map *main_map)
 {
   /* This have already been filled in right after _dl_new_object, or
@@ -1292,7 +1292,7 @@  rtld_setup_main_map (struct link_map *main_map)
    entry point.  The ld.so processed skip_args arguments and bumped
    _dl_argv and _dl_argc accordingly.  Those arguments are removed from
    argv here.  */
-static void
+static void __TEXT_STARTUP
 _dl_start_args_adjust (int skip_args)
 {
   void **sp = (void **) (_dl_argv - skip_args - 1);
@@ -1344,7 +1344,7 @@  _dl_start_args_adjust (int skip_args)
 #endif
 }
 
-static void
+static void __TEXT_STARTUP
 dl_main (const ElfW(Phdr) *phdr,
 	 ElfW(Word) phnum,
 	 ElfW(Addr) *user_entry,
@@ -2430,7 +2430,7 @@  print_missing_version (int errcode __attribute__ ((unused)),
 
 /* Process the string given as the parameter which explains which debugging
    options are enabled.  */
-static void
+static void __TEXT_STARTUP
 process_dl_debug (struct dl_main_state *state, const char *dl_debug)
 {
   /* When adding new entries make sure that the maximal length of a name
@@ -2535,7 +2535,7 @@  a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
     }
 }
 
-static void
+static void __TEXT_STARTUP
 process_envvars (struct dl_main_state *state)
 {
   char **runp = _environ;
diff --git a/hurd/hurdinit.c b/hurd/hurdinit.c
index d0c7a831..f8e2f16c 100644
--- a/hurd/hurdinit.c
+++ b/hurd/hurdinit.c
@@ -65,7 +65,7 @@  __typeof (_hurd_proc_init) _hurd_new_proc_init;	/* below */
 
    PORTARRAY and INTARRAY are vm_deallocate'd.  */
 
-void
+void __TEXT_STARTUP
 _hurd_init (int flags, char **argv,
 	    mach_port_t *portarray, size_t portarraysize,
 	    int *intarray, size_t intarraysize)
@@ -121,7 +121,7 @@  _hurd_init (int flags, char **argv,
 }
 libc_hidden_def (_hurd_init)
 
-void
+void __TEXT_STARTUP
 _hurd_libc_proc_init (char **argv)
 {
   if (_hurd_portarray)
@@ -160,7 +160,7 @@  int _hide_arguments, _hide_environment;
 /* Do startup handshaking with the proc server just installed in _hurd_ports.
    Call _hurdsig_init to set up signal processing.  */
 
-void
+void __TEXT_STARTUP
 _hurd_new_proc_init (char **argv,
 		     const int *intarray, size_t intarraysize)
 {
diff --git a/hurd/hurdstartup.c b/hurd/hurdstartup.c
index 6af0205a..346c38c0 100644
--- a/hurd/hurdstartup.c
+++ b/hurd/hurdstartup.c
@@ -44,7 +44,7 @@  extern void __mach_init (void);
    port, and the base address and size of the preallocated stack.  */
 
 
-void
+void __TEXT_STARTUP
 _hurd_startup (void **argptr, void (*main) (intptr_t *data))
 {
   error_t err;
diff --git a/hurd/lookup-retry.c b/hurd/lookup-retry.c
index 62f94bbc..763a6ffc 100644
--- a/hurd/lookup-retry.c
+++ b/hurd/lookup-retry.c
@@ -43,6 +43,9 @@  lookup_error (error_t error)
     }
 }
 
+#if IS_IN (rtld)
+__TEXT_STARTUP
+#endif
 error_t
 __hurd_file_name_lookup_retry (error_t (*use_init_port)
 				 (int which, error_t (*operate) (file_t)),
diff --git a/iconv/gconv_cache.c b/iconv/gconv_cache.c
index c8d972c8..c034cc66 100644
--- a/iconv/gconv_cache.c
+++ b/iconv/gconv_cache.c
@@ -450,7 +450,7 @@  __gconv_release_cache (struct __gconv_step *steps, size_t nsteps)
 
 
 /* Free all resources if necessary.  */
-void
+void __TEXT_EXIT
 __gconv_cache_freemem (void)
 {
   if (cache_malloced)
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
index c76011d6..69d883ae 100644
--- a/iconv/gconv_conf.c
+++ b/iconv/gconv_conf.c
@@ -530,7 +530,7 @@  __gconv_load_conf (void)
 
 
 /* Free all resources if necessary.  */
-void
+void __TEXT_EXIT
 __gconv_conf_freemem (void)
 {
   if (__gconv_path_elem != NULL && __gconv_path_elem != &empty_path_elem)
diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c
index 0ee80762..8044d14c 100644
--- a/iconv/gconv_db.c
+++ b/iconv/gconv_db.c
@@ -792,7 +792,7 @@  __gconv_close_transform (struct __gconv_step *steps, size_t nsteps)
 
 
 /* Free the modules mentioned.  */
-static void
+static void __TEXT_EXIT
 free_modules_db (struct gconv_module *node)
 {
   if (node->left != NULL)
@@ -811,7 +811,7 @@  free_modules_db (struct gconv_module *node)
 
 
 /* Free all resources if necessary.  */
-void
+void __TEXT_EXIT
 __gconv_db_freemem (void)
 {
   /* First free locale memory.  This needs to be done before freeing
diff --git a/iconv/gconv_dl.c b/iconv/gconv_dl.c
index cb51568e..8c30f401 100644
--- a/iconv/gconv_dl.c
+++ b/iconv/gconv_dl.c
@@ -196,7 +196,7 @@  do_release_all (void *nodep)
   free (obj);
 }
 
-void
+void __TEXT_EXIT
 __gconv_dl_freemem (void)
 {
   __tdestroy (loaded, do_release_all);
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index 7886ac95..103c44f7 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -1667,7 +1667,7 @@  mempcpy (void *dest, const void *src, size_t n)
 #ifdef _LIBC
 /* If we want to free all resources we have to do some work at
    program's end.  */
-void
+void __TEXT_EXIT
 __intl_freemem (void)
 {
   void *old;
diff --git a/intl/finddomain.c b/intl/finddomain.c
index 6a8b239a..2f00c898 100644
--- a/intl/finddomain.c
+++ b/intl/finddomain.c
@@ -185,7 +185,7 @@  out:
 #ifdef _LIBC
 /* This is called from iconv/gconv_db.c's free_mem, as locales must
    be freed before freeing gconv steps arrays.  */
-void
+void __TEXT_EXIT
 _nl_finddomain_subfreeres (void)
 {
   struct loaded_l10nfile *runp = _nl_loaded_domains;
diff --git a/intl/localealias.c b/intl/localealias.c
index ea4f48b5..98b2e492 100644
--- a/intl/localealias.c
+++ b/intl/localealias.c
@@ -436,7 +436,7 @@  alias_compare (const struct alias_map *map1, const struct alias_map *map2)
 #endif
 }
 
-void
+void __TEXT_EXIT
 __libc_localealias_freemem (void)
 {
   free (string_space);
diff --git a/libio/genops.c b/libio/genops.c
index 71313127..806e1c0f 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -844,7 +844,7 @@  _IO_unbuffer_all (void)
 #endif
 }
 
-void
+void __TEXT_EXIT
 __libio_freemem (void)
 {
   dealloc_buffers = true;
@@ -858,7 +858,7 @@  __libio_freemem (void)
 }
 
 
-int
+int __TEXT_EXIT
 _IO_cleanup (void)
 {
   /* We do *not* want locking.  Some threads might use streams but
diff --git a/mach/mach_init.c b/mach/mach_init.c
index 42b9cacf..61e19917 100644
--- a/mach/mach_init.c
+++ b/mach/mach_init.c
@@ -30,7 +30,7 @@  weak_alias (__vm_page_size, vm_page_size)
 # include NDR_DEF_HEADER
 #endif
 
-void
+void __TEXT_STARTUP
 __mach_init (void)
 {
   kern_return_t err;
diff --git a/mach/mig-reply.c b/mach/mig-reply.c
index ce2059bf..a8bb63e5 100644
--- a/mach/mig-reply.c
+++ b/mach/mig-reply.c
@@ -44,7 +44,7 @@  __mig_dealloc_reply_port (void)
 
 /* Called at startup with CPROC == NULL.  cthreads has a different version
    of this function that is sometimes called with a `cproc_t' pointer.  */
-void
+void __TEXT_STARTUP
 __mig_init (void *cproc)
 {
   if (cproc == 0)
diff --git a/malloc/set-freeres.c b/malloc/set-freeres.c
index 1aab34b5..68c499f2 100644
--- a/malloc/set-freeres.c
+++ b/malloc/set-freeres.c
@@ -74,7 +74,7 @@ 
     free (__ptr);
 #endif
 
-void
+void __TEXT_EXIT
 __libc_freeres (void)
 {
   /* This function might be called from different places.  So better
diff --git a/misc/fstab.c b/misc/fstab.c
index ea4afc7d..9493a634 100644
--- a/misc/fstab.c
+++ b/misc/fstab.c
@@ -177,7 +177,7 @@  fstab_convert (struct fstab_state *state)
 
 /* Make sure the memory is freed if the programs ends while in
    memory-debugging mode and something actually was allocated.  */
-void
+void __TEXT_EXIT
 __libc_fstab_freemem (void)
 {
   char *buffer;
diff --git a/misc/init-misc.c b/misc/init-misc.c
index 32eb92d5..adb0ee2b 100644
--- a/misc/init-misc.c
+++ b/misc/init-misc.c
@@ -25,7 +25,7 @@  weak_alias (__progname_full, program_invocation_name)
 weak_alias (__progname, program_invocation_short_name)
 
 
-void
+void __TEXT_STARTUP
 __init_misc (int argc, char **argv, char **envp)
 {
   if (argv && argv[0])
diff --git a/nptl/pthread_mutex_conf.c b/nptl/pthread_mutex_conf.c
index 65178997..0a3a4f46 100644
--- a/nptl/pthread_mutex_conf.c
+++ b/nptl/pthread_mutex_conf.c
@@ -32,25 +32,25 @@  struct mutex_config __mutex_aconf =
 };
 libc_hidden_data_def (__mutex_aconf)
 
-static void
+static void __TEXT_STARTUP
 TUNABLE_CALLBACK (set_mutex_spin_count) (tunable_val_t *valp)
 {
   __mutex_aconf.spin_count = (int32_t) (valp)->numval;
 }
 
-static void
+static void __TEXT_STARTUP
 TUNABLE_CALLBACK (set_stack_cache_size) (tunable_val_t *valp)
 {
   __nptl_stack_cache_maxsize = valp->numval;
 }
 
-static void
+static void __TEXT_STARTUP
 TUNABLE_CALLBACK (set_stack_hugetlb) (tunable_val_t *valp)
 {
   __nptl_stack_hugetlb = (int32_t) valp->numval;
 }
 
-void
+void __TEXT_STARTUP
 __pthread_tunables_init (void)
 {
   TUNABLE_GET (mutex_spin_count, int32_t,
diff --git a/nscd/nscd_getgr_r.c b/nscd/nscd_getgr_r.c
index 07e89401..7f359990 100644
--- a/nscd/nscd_getgr_r.c
+++ b/nscd/nscd_getgr_r.c
@@ -68,7 +68,7 @@  libc_locked_map_ptr (,__gr_map_handle) attribute_hidden;
 /* Note that we only free the structure if necessary.  The memory
    mapping is not removed since it is not visible to the malloc
    handling.  */
-void
+void __TEXT_EXIT
 __nscd_gr_map_freemem (void)
 {
   if (__gr_map_handle.mapped != NO_MAPPING)
diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c
index c6a6247f..dc31c874 100644
--- a/nscd/nscd_gethst_r.c
+++ b/nscd/nscd_gethst_r.c
@@ -81,7 +81,7 @@  libc_locked_map_ptr (, __hst_map_handle) attribute_hidden;
 /* Note that we only free the structure if necessary.  The memory
    mapping is not removed since it is not visible to the malloc
    handling.  */
-void
+void __TEXT_EXIT
 __nscd_hst_map_freemem (void)
 {
   if (__hst_map_handle.mapped != NO_MAPPING)
diff --git a/nscd/nscd_getpw_r.c b/nscd/nscd_getpw_r.c
index 17d9753f..feb60b78 100644
--- a/nscd/nscd_getpw_r.c
+++ b/nscd/nscd_getpw_r.c
@@ -67,7 +67,7 @@  libc_locked_map_ptr (static, map_handle);
 /* Note that we only free the structure if necessary.  The memory
    mapping is not removed since it is not visible to the malloc
    handling.  */
-void
+void __TEXT_EXIT
 __nscd_pw_map_freemem (void)
 {
   if (map_handle.mapped != NO_MAPPING)
diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c
index 1458c6ca..5ff826b0 100644
--- a/nscd/nscd_getserv_r.c
+++ b/nscd/nscd_getserv_r.c
@@ -62,7 +62,7 @@  libc_locked_map_ptr (, __serv_map_handle) attribute_hidden;
 /* Note that we only free the structure if necessary.  The memory
    mapping is not removed since it is not visible to the malloc
    handling.  */
-void
+void __TEXT_EXIT
 __nscd_serv_map_freemem (void)
 {
   if (__serv_map_handle.mapped != NO_MAPPING)
diff --git a/nscd/nscd_netgroup.c b/nscd/nscd_netgroup.c
index 6f4c383a..b9adc009 100644
--- a/nscd/nscd_netgroup.c
+++ b/nscd/nscd_netgroup.c
@@ -31,7 +31,7 @@  libc_locked_map_ptr (static, map_handle);
 /* Note that we only free the structure if necessary.  The memory
    mapping is not removed since it is not visible to the malloc
    handling.  */
-void
+void __TEXT_EXIT
 __nscd_group_map_freemem (void)
 {
   if (map_handle.mapped != NO_MAPPING)
diff --git a/nss/nss_action.c b/nss/nss_action.c
index 447c219c..67f03e18 100644
--- a/nss/nss_action.c
+++ b/nss/nss_action.c
@@ -102,7 +102,7 @@  __nss_action_allocate (struct nss_action *actions, size_t count)
   return result;
 }
 
-void
+void __TEXT_EXIT
 __nss_action_freeres (void)
 {
   struct nss_action_list_wrapper *current = nss_actions;
diff --git a/nss/nss_database.c b/nss/nss_database.c
index 2edcab4b..09c021c2 100644
--- a/nss/nss_database.c
+++ b/nss/nss_database.c
@@ -495,7 +495,7 @@  __nss_database_get_noreload (enum nss_database db)
   return result;
 }
 
-void
+void __TEXT_EXIT
 __nss_database_freeres (void)
 {
   free (global_database_state);
diff --git a/nss/nss_module.c b/nss/nss_module.c
index 487e513d..6d915c08 100644
--- a/nss/nss_module.c
+++ b/nss/nss_module.c
@@ -416,7 +416,7 @@  __nss_module_disable_loading (void)
   __libc_lock_unlock (nss_module_list_lock);
 }
 
-void
+void __TEXT_EXIT
 __nss_module_freeres (void)
 {
   struct nss_module *current = nss_module_list;
diff --git a/posix/_exit.c b/posix/_exit.c
index 6635c117..667558a6 100644
--- a/posix/_exit.c
+++ b/posix/_exit.c
@@ -21,7 +21,7 @@ 
 /* The function `_exit' should take a status argument and simply
    terminate program execution, using the low-order 8 bits of the
    given integer as status.  */
-void
+void __TEXT_EXIT
 _exit (int status)
 {
   status &= 0xff;
diff --git a/posix/regcomp.c b/posix/regcomp.c
index 12650714..57c19df6 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -710,7 +710,7 @@  re_comp (const char *s)
 }
 
 #ifdef _LIBC
-void
+void __TEXT_EXIT
 __libc_regcomp_freemem (void)
 {
   __regfree (&re_comp_buf);
diff --git a/posix/register-atfork.c b/posix/register-atfork.c
index 14ebc258..2258ceee 100644
--- a/posix/register-atfork.c
+++ b/posix/register-atfork.c
@@ -217,7 +217,7 @@  __run_postfork_handlers (enum __run_fork_handler_type who, _Bool do_locking,
 }
 
 
-void
+void __TEXT_EXIT
 __libc_atfork_freemem (void)
 {
   lll_lock (atfork_lock, LLL_PRIVATE);
diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c
index 9e3b1d29..00658172 100644
--- a/resolv/gai_misc.c
+++ b/resolv/gai_misc.c
@@ -437,7 +437,7 @@  handle_requests (void *arg)
 #if !PTHREAD_IN_LIBC
 __attribute__ ((__destructor__)) static
 #endif
-void
+void __TEXT_EXIT
 __gai_freemem (void)
 {
   size_t row;
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
index 0ef66d49..562cb6aa 100644
--- a/resolv/resolv_conf.c
+++ b/resolv/resolv_conf.c
@@ -654,7 +654,7 @@  __resolv_conf_detach (struct __res_state *resp)
 }
 
 /* Deallocate the global data.  */
-void
+void __TEXT_EXIT
 __libc_resolv_conf_freemem (void)
 {
   /* No locking because this function is supposed to be called when
diff --git a/rt/aio_misc.c b/rt/aio_misc.c
index 4b850b1a..af86a9f5 100644
--- a/rt/aio_misc.c
+++ b/rt/aio_misc.c
@@ -697,7 +697,7 @@  handle_fildes_io (void *arg)
 #if !PTHREAD_IN_LIBC
 __attribute__ ((__destructor__)) static
 #endif
-void
+void __TEXT_EXIT
 __aio_freemem (void)
 {
   size_t row;
diff --git a/stdio-common/reg-modifier.c b/stdio-common/reg-modifier.c
index a52022d1..309ccb76 100644
--- a/stdio-common/reg-modifier.c
+++ b/stdio-common/reg-modifier.c
@@ -183,7 +183,7 @@  __handle_registered_modifier_wc (const unsigned int **format,
 }
 
 
-void
+void __TEXT_EXIT
 __libc_printf_freemem (void)
 {
   if (__printf_modifier_table != NULL)
diff --git a/stdlib/exit.c b/stdlib/exit.c
index d6c188b7..f628f397 100644
--- a/stdlib/exit.c
+++ b/stdlib/exit.c
@@ -32,7 +32,7 @@  bool __exit_funcs_done = false;
    in the reverse of the order in which they were registered
    perform stdio cleanup, and terminate program execution with STATUS.  */
 void
-attribute_hidden
+attribute_hidden __TEXT_EXIT
 __run_exit_handlers (int status, struct exit_function_list **listp,
 		     bool run_list_atexit, bool run_dtors)
 {
@@ -135,7 +135,7 @@  __run_exit_handlers (int status, struct exit_function_list **listp,
 }
 
 
-void
+void __TEXT_EXIT
 exit (int status)
 {
   __run_exit_handlers (status, &__exit_funcs, true, true);
diff --git a/stdlib/fmtmsg.c b/stdlib/fmtmsg.c
index 3d9a0edf..ce821807 100644
--- a/stdlib/fmtmsg.c
+++ b/stdlib/fmtmsg.c
@@ -361,7 +361,7 @@  __addseverity (int severity, const char *string)
 weak_alias (__addseverity, addseverity)
 
 
-void
+void __TEXT_EXIT
 __libc_fmtmsg_freemem (void)
 {
   struct severity_info *runp = severity_list;
diff --git a/stdlib/quick_exit.c b/stdlib/quick_exit.c
index 838d4658..bda33f71 100644
--- a/stdlib/quick_exit.c
+++ b/stdlib/quick_exit.c
@@ -24,7 +24,7 @@ 
 #include <shlib-compat.h>
 #include "exit.h"
 
-void
+void __TEXT_EXIT
 __new_quick_exit (int status)
 {
   /* The new quick_exit, following C++11 18.5.12, does not run object
diff --git a/stdlib/setenv.c b/stdlib/setenv.c
index ba5257d3..1fbbe701 100644
--- a/stdlib/setenv.c
+++ b/stdlib/setenv.c
@@ -323,7 +323,7 @@  clearenv (void)
   return 0;
 }
 #ifdef _LIBC
-void
+void __TEXT_EXIT
 __libc_setenv_freemem (void)
 {
   /* Remove all traces.  */
diff --git a/sunrpc/clnt_perr.c b/sunrpc/clnt_perr.c
index c3d13722..cfe91db3 100644
--- a/sunrpc/clnt_perr.c
+++ b/sunrpc/clnt_perr.c
@@ -389,7 +389,7 @@  auth_errmsg (enum auth_stat stat)
 }
 
 
-void
+void __TEXT_EXIT
 __rpc_freemem (void)
 {
   free (buf);
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
index 4170b926..95ba835b 100644
--- a/sysdeps/aarch64/dl-machine.h
+++ b/sysdeps/aarch64/dl-machine.h
@@ -120,7 +120,7 @@  elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
 
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index ed5389e3..5e748d2c 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -205,7 +205,7 @@  _dl_start_user:							\n\
  *    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
 	if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h
index d720c02c..3825ec56 100644
--- a/sysdeps/arm/dl-machine.h
+++ b/sysdeps/arm/dl-machine.h
@@ -194,7 +194,7 @@  _dl_start_user:\n\
    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/csky/dl-machine.h b/sysdeps/csky/dl-machine.h
index 07a4b678..6bbe5427 100644
--- a/sysdeps/csky/dl-machine.h
+++ b/sysdeps/csky/dl-machine.h
@@ -161,7 +161,7 @@  _dl_start_user:\n\
    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/generic/dl-call_tls_init_tp.h b/sysdeps/generic/dl-call_tls_init_tp.h
index 34f0959f..f053e07e 100644
--- a/sysdeps/generic/dl-call_tls_init_tp.h
+++ b/sysdeps/generic/dl-call_tls_init_tp.h
@@ -25,7 +25,7 @@  _startup_fatal_tls_error (void)
   _startup_fatal ("Fatal glibc error: Cannot allocate TLS block\n");
 }
 
-static inline void
+static inline void __TEXT_STARTUP
 call_tls_init_tp (void *addr)
 {
   if (!TLS_INIT_TP (addr))
diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h
index 4e6e70b3..7af13bba 100644
--- a/sysdeps/hppa/dl-machine.h
+++ b/sysdeps/hppa/dl-machine.h
@@ -525,7 +525,7 @@  asm (									\
  *    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
 	if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 18749f2e..d64494e7 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -200,7 +200,7 @@  _dl_start_user:\n\
    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
 #if IS_IN (rtld)
diff --git a/sysdeps/mach/hurd/_exit.c b/sysdeps/mach/hurd/_exit.c
index 80cfe532..e7ad58a7 100644
--- a/sysdeps/mach/hurd/_exit.c
+++ b/sysdeps/mach/hurd/_exit.c
@@ -21,7 +21,7 @@ 
 #include <sysdep.h>
 #include <sys/wait.h>
 
-void
+void __TEXT_EXIT
 _hurd_exit (int status)
 {
   if (_hurd_ports != NULL)
@@ -46,7 +46,7 @@  _hurd_exit (int status)
     }
 }
 
-void
+void __TEXT_EXIT
 _exit (int status)
 {
   _hurd_exit (W_EXITCODE (status, 0));
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index 01a16570..af1ae142 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -68,7 +68,7 @@  void *_dl_random attribute_relro = NULL;
 struct hurd_startup_data *_dl_hurd_data;
 
 
-ElfW(Addr)
+ElfW(Addr) __TEXT_STARTUP
 _dl_sysdep_start (void **start_argptr,
 		  void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phent,
 				   ElfW(Addr) *user_entry,
@@ -232,7 +232,7 @@  _dl_sysdep_start (void **start_argptr,
   abort ();
 }
 
-void
+void __TEXT_STARTUP
 _dl_sysdep_start_cleanup (void)
 {
   /* Deallocate the reply port and task port rights acquired by
@@ -261,7 +261,7 @@  _dl_sysdep_start_cleanup (void)
 
 /* Open FILE_NAME and return a Hurd I/O for it in *PORT, or return an
    error.  If STAT is non-zero, stat the file into that stat buffer.  */
-static error_t
+static error_t __TEXT_STARTUP
 open_file (const char *file_name, int flags,
 	   mach_port_t *port, struct stat64 *stat)
 {
@@ -318,7 +318,7 @@  open_file (const char *file_name, int flags,
 check_no_hidden(__open);
 check_no_hidden (__open64);
 check_no_hidden (__open_nocancel);
-int weak_function
+int weak_function __TEXT_STARTUP
 __open (const char *file_name, int mode, ...)
 {
   mach_port_t port;
@@ -333,7 +333,7 @@  weak_alias (__open, __open_nocancel)
 
 check_no_hidden(__close);
 check_no_hidden(__close_nocancel);
-int weak_function
+int weak_function __TEXT_STARTUP
 __close (int fd)
 {
   if (fd != (int) MACH_PORT_NULL)
@@ -344,7 +344,7 @@  weak_alias (__close, __close_nocancel)
 
 check_no_hidden(__pread64);
 check_no_hidden(__pread64_nocancel);
-__ssize_t weak_function
+__ssize_t weak_function __TEXT_STARTUP
 __pread64 (int fd, void *buf, size_t nbytes, off64_t offset)
 {
   error_t err;
@@ -370,7 +370,7 @@  weak_alias (__pread64, __pread64_nocancel)
 
 check_no_hidden(__read);
 check_no_hidden(__read_nocancel);
-__ssize_t weak_function
+__ssize_t weak_function __TEXT_STARTUP
 __read (int fd, void *buf, size_t nbytes)
 {
   return __pread64 (fd, buf, nbytes, -1);
@@ -380,7 +380,7 @@  weak_alias (__read, __read_nocancel)
 
 check_no_hidden(__write);
 check_no_hidden(__write_nocancel);
-__ssize_t weak_function
+__ssize_t weak_function __TEXT_STARTUP
 __write (int fd, const void *buf, size_t nbytes)
 {
   error_t err;
@@ -399,7 +399,7 @@  libc_hidden_weak (__write)
 
 /* This is only used for printing messages (see dl-misc.c).  */
 check_no_hidden(__writev);
-__ssize_t weak_function
+__ssize_t weak_function __TEXT_STARTUP
 __writev (int fd, const struct iovec *iov, int niov)
 {
   if (fd >= _hurd_init_dtablesize)
@@ -433,7 +433,7 @@  __writev (int fd, const struct iovec *iov, int niov)
 }
 
 check_no_hidden(__libc_lseek64);
-off64_t weak_function
+off64_t weak_function __TEXT_STARTUP
 __libc_lseek64 (int fd, off64_t offset, int whence)
 {
   error_t err;
@@ -446,7 +446,7 @@  __libc_lseek64 (int fd, off64_t offset, int whence)
 }
 
 check_no_hidden(__mmap);
-void *weak_function
+void *weak_function __TEXT_STARTUP
 __mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
 {
   error_t err;
@@ -516,7 +516,7 @@  __mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
 }
 
 check_no_hidden(__fstat64);
-int weak_function
+int weak_function __TEXT_STARTUP
 __fstat64 (int fd, struct stat64 *buf)
 {
   error_t err;
@@ -530,7 +530,7 @@  __fstat64 (int fd, struct stat64 *buf)
 libc_hidden_def (__fstat64)
 
 check_no_hidden(__stat64);
-int weak_function
+int weak_function __TEXT_STARTUP
 __stat64 (const char *file, struct stat64 *buf)
 {
   error_t err;
@@ -551,20 +551,20 @@  libc_hidden_def (__stat64)
    stub will always fail, which means that malloc-debugging is always
    disabled for SUID binaries.  */
 check_no_hidden(__access);
-int weak_function
+int weak_function __TEXT_STARTUP
 __access (const char *file, int type)
 {
   errno = ENOSYS;
   return -1;
 }
 check_no_hidden(__access_noerrno);
-int weak_function
+int weak_function __TEXT_STARTUP
 __access_noerrno (const char *file, int type)
 {
   return -1;
 }
 
-int
+int __TEXT_STARTUP
 __rtld_execve (const char *file_name, char *const argv[],
                char *const envp[])
 {
@@ -670,7 +670,7 @@  out:
 }
 
 check_no_hidden(__getpid);
-pid_t weak_function
+pid_t weak_function __TEXT_STARTUP
 __getpid (void)
 {
   pid_t pid, ppid;
@@ -694,7 +694,7 @@  strong_alias (__getpid, __GI___getpid)
    reusing getcwd.c's code but using our special lookup function as in
    `open', above.)  */
 check_no_hidden(__getcwd);
-char *weak_function
+char *weak_function __TEXT_STARTUP
 __getcwd (char *buf, size_t size)
 {
   errno = ENOSYS;
@@ -704,7 +704,7 @@  __getcwd (char *buf, size_t size)
 /* This is used by dl-tunables.c to strdup strings.  We can just make this a
    mere allocation.  */
 check_no_hidden(__sbrk);
-void *weak_function
+void *weak_function __TEXT_STARTUP
 __sbrk (intptr_t increment)
 {
   vm_address_t addr;
@@ -715,7 +715,7 @@  __sbrk (intptr_t increment)
 
 /* This is only used by hurdlookup for the /dev/fd/nnn magic.
  * We avoid pulling the whole libc implementation, and we can keep this hidden.  */
-unsigned long int weak_function
+unsigned long int weak_function __TEXT_STARTUP
 __strtoul_internal (const char *nptr, char **endptr, int base, int group)
 {
   assert (base == 0 || base == 10);
@@ -729,7 +729,7 @@  strong_alias (__strtoul_internal, __GI___strtoul_internal)
 strong_alias (__strtoul_internal, __GI_____strtoul_internal)
 
 check_no_hidden(_exit);
-void weak_function attribute_hidden
+void weak_function attribute_hidden __TEXT_EXIT
 _exit (int status)
 {
   __proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC],
@@ -780,7 +780,7 @@  strong_alias (abort, __GI___assert_perror_fail)
    weak, the real defn in libc.so will override it if we are linked into
    the user program (-ldl).  */
 
-error_t weak_function
+error_t weak_function __TEXT_STARTUP
 _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
 			 mach_msg_option_t option,
 			 mach_msg_size_t send_size,
@@ -794,14 +794,14 @@  _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
 }
 
 
-void
+void __TEXT_STARTUP
 _dl_show_auxv (void)
 {
   /* There is nothing to print.  Hurd has no auxiliary vector.  */
 }
 
 
-void weak_function
+void weak_function __TEXT_STARTUP
 _dl_init_first (void *p)
 {
   /* This no-op definition only gets used if libc is not linked in.  */
diff --git a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h
index e124fb10..8029b2db 100644
--- a/sysdeps/mach/hurd/i386/tls.h
+++ b/sysdeps/mach/hurd/i386/tls.h
@@ -135,7 +135,7 @@  __LIBC_NO_TLS (void)
 /* Code to initially initialize the thread pointer.  This might need
    special attention since 'errno' is not yet available and if the
    operation can cause a failure 'errno' must not be touched.  */
-static inline bool __attribute__ ((unused))
+static inline bool __attribute__ ((unused)) __TEXT_STARTUP
 _hurd_tls_init (tcbhead_t *tcb, bool full)
 {
   HURD_TLS_DESC_DECL (desc, tcb);
diff --git a/sysdeps/mach/hurd/mig-reply.c b/sysdeps/mach/hurd/mig-reply.c
index 7ea001df..c582b9d3 100644
--- a/sysdeps/mach/hurd/mig-reply.c
+++ b/sysdeps/mach/hurd/mig-reply.c
@@ -98,7 +98,7 @@  weak_alias (__mig_put_reply_port, mig_put_reply_port)
 /* Called at startup with STACK == NULL.  When per-thread variables are set
    up, this is called again with STACK set to the new stack being switched
    to, where per-thread variables should be set up.  */
-void
+void __TEXT_STARTUP
 __mig_init (void *stack)
 {
   /* Do nothing.  */
diff --git a/sysdeps/mach/hurd/x86/init-first.c b/sysdeps/mach/hurd/x86/init-first.c
index d74a3c86..772fcfab 100644
--- a/sysdeps/mach/hurd/x86/init-first.c
+++ b/sysdeps/mach/hurd/x86/init-first.c
@@ -49,7 +49,7 @@  DEFINE_HOOK (_hurd_preinit_hook, (void));
 
 /* We call this once the Hurd magic is all set up and we are ready to be a
    Posixoid program.  This does the same things the generic version does.  */
-static void
+static void __TEXT_STARTUP
 posixland_init (int argc, char **argv, char **envp)
 {
   /* Now we have relocations etc. we can start signals etc.  */
@@ -82,7 +82,7 @@  posixland_init (int argc, char **argv, char **envp)
   __init_misc (argc, argv, envp);
 }
 
-static void
+static void __TEXT_STARTUP
 init (void **data)
 {
   int argc = (int) (uintptr_t) *data;
@@ -147,7 +147,7 @@  init (void **data)
 }
 
 /* Do the first essential initializations that must precede all else.  */
-static inline void
+static inline void __TEXT_STARTUP
 first_init (void)
 {
   /* Initialize data structures so we can do RPCs.  */
@@ -167,7 +167,7 @@  first_init (void)
    initialization of the shared C library before normal initializers
    expecting a Posixoid environment can run.  */
 
-void
+void __TEXT_STARTUP
 _dl_init_first (void *data)
 {
   first_init ();
@@ -182,7 +182,7 @@  _dl_init_first (void *data)
    the only thing that really matters!!  */
 strong_alias (posixland_init, _init);
 
-void
+void __TEXT_STARTUP
 __libc_init_first (int argc, char **argv, char **envp)
 {
   /* Everything was done in the shared library initializer, _init.  */
@@ -195,7 +195,7 @@  strong_alias (posixland_init, __libc_init_first);
 /* XXX This is all a crock and I am not happy with it.
    This poorly-named function is called by static-start.S,
    which should not exist at all.  */
-void
+void __TEXT_STARTUP
 inhibit_stack_protector
 _hurd_stack_setup (void)
 {
diff --git a/sysdeps/mach/hurd/x86_64/tls.h b/sysdeps/mach/hurd/x86_64/tls.h
index 1274723a..d724767a 100644
--- a/sysdeps/mach/hurd/x86_64/tls.h
+++ b/sysdeps/mach/hurd/x86_64/tls.h
@@ -172,7 +172,7 @@  _hurd_tls_new (thread_t child, tcbhead_t *tcb)
 extern unsigned char __libc_tls_initialized;
 #  define __LIBC_NO_TLS() __builtin_expect (!__libc_tls_initialized, 0)
 
-static inline bool __attribute__ ((unused))
+static inline bool __attribute__ ((unused)) __TEXT_STARTUP
 _hurd_tls_init (tcbhead_t *tcb, bool full)
 {
   error_t err;
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index f1b3effe..a08e526a 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -391,7 +391,7 @@  do {									\
    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/nptl/dl-mutex.c b/sysdeps/nptl/dl-mutex.c
index 415df854..ad99d819 100644
--- a/sysdeps/nptl/dl-mutex.c
+++ b/sysdeps/nptl/dl-mutex.c
@@ -25,7 +25,7 @@ 
 __typeof (pthread_mutex_lock) *___rtld_mutex_lock attribute_relro;
 __typeof (pthread_mutex_unlock) *___rtld_mutex_unlock attribute_relro;
 
-void
+void __TEXT_STARTUP
 __rtld_mutex_init (void)
 {
   /* There is an implicit assumption here that the lock counters are
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
index 50dc7788..3198ef48 100644
--- a/sysdeps/nptl/dl-tls_init_tp.c
+++ b/sysdeps/nptl/dl-tls_init_tp.c
@@ -48,7 +48,7 @@  const unsigned int __rseq_flags;
 const unsigned int __rseq_size attribute_relro;
 const ptrdiff_t __rseq_offset attribute_relro;
 
-void
+void __TEXT_STARTUP
 __tls_pre_init_tp (void)
 {
   /* The list data structures are not consistent until
@@ -63,7 +63,7 @@  __tls_pre_init_tp (void)
 #endif
 }
 
-void
+void __TEXT_STARTUP
 __tls_init_tp (void)
 {
   struct pthread *pd = THREAD_SELF;
diff --git a/sysdeps/nptl/pthread_early_init.h b/sysdeps/nptl/pthread_early_init.h
index f1a3b65d..ef722292 100644
--- a/sysdeps/nptl/pthread_early_init.h
+++ b/sysdeps/nptl/pthread_early_init.h
@@ -24,7 +24,7 @@ 
 #include <pthread_mutex_conf.h>
 #include <sys/resource.h>
 
-static inline void
+static inline void __TEXT_STARTUP
 __pthread_early_init (void)
 {
   /* Determine the default allowed stack size.  This is the size used
diff --git a/sysdeps/or1k/dl-machine.h b/sysdeps/or1k/dl-machine.h
index b6707b96..d0d0f152 100644
--- a/sysdeps/or1k/dl-machine.h
+++ b/sysdeps/or1k/dl-machine.h
@@ -142,7 +142,7 @@  elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 0356b622..633b14f7 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -1761,7 +1761,7 @@  check_gaiconf_mtime (const struct __stat64_t64 *st)
 #endif
 
 
-void
+void __TEXT_EXIT
 __libc_getaddrinfo_freemem (void)
 {
   if (labels != default_labels)
diff --git a/sysdeps/powerpc/cpu-features.c b/sysdeps/powerpc/cpu-features.c
index 0ef3cf89..81601adf 100644
--- a/sysdeps/powerpc/cpu-features.c
+++ b/sysdeps/powerpc/cpu-features.c
@@ -20,7 +20,7 @@ 
 #include <cpu-features.h>
 #include <elf/dl-tunables.h>
 
-static inline void
+static inline void __TEXT_STARTUP
 init_cpu_features (struct cpu_features *cpu_features)
 {
   /* Default is to use aligned memory access on optimized function unless
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index a4cad758..076d9f8d 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -153,7 +153,7 @@  __elf_preferred_address(struct link_map *loader, size_t maplength,
 #ifdef SHARED
 # define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   __tcb_parse_hwcap_and_convert_at_platform ();
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 9b8943bc..a69ad0ed 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -293,7 +293,7 @@  BODY_PREFIX "_dl_start_user:\n"						\
 #if defined(SHARED) && IS_IN (rtld)
 # define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   __tcb_parse_hwcap_and_convert_at_platform ();
diff --git a/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h b/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
index e0ec3ba4..e5c9e742 100644
--- a/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
+++ b/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
@@ -22,7 +22,7 @@ 
 #include <gcc-macros.h>
 #include <ldsodefs.h>
 
-static inline void
+static inline void __TEXT_STARTUP
 dl_hwcap_check (void)
 {
 #ifdef GCCMACRO_ARCH_PWR9
diff --git a/sysdeps/s390/cpu-features.c b/sysdeps/s390/cpu-features.c
index 39f8c23a..b7b56f8d 100644
--- a/sysdeps/s390/cpu-features.c
+++ b/sysdeps/s390/cpu-features.c
@@ -27,7 +27,7 @@  extern __typeof (memcmp) MEMCMP_DEFAULT;
   (DEST_PTR)->hwcap = (SRC_PTR)->hwcap;			\
   (DEST_PTR)->stfle_bits[0] = (SRC_PTR)->stfle_bits[0];
 
-static void
+static void __TEXT_STARTUP
 TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
 {
   /* The current IFUNC selection is always using the most recent
@@ -203,7 +203,7 @@  TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
     & cpu_features_orig.stfle_bits[0];
 }
 
-static inline void
+static inline void __TEXT_STARTUP
 init_cpu_features (struct cpu_features *cpu_features)
 {
   /* Fill cpu_features as passed by kernel and machine.  */
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h
index 100a3e05..cf784ed8 100644
--- a/sysdeps/s390/s390-32/dl-machine.h
+++ b/sysdeps/s390/s390-32/dl-machine.h
@@ -239,7 +239,7 @@  _dl_start_user:\n\
    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/s390/s390-64/dl-hwcap-check.h b/sysdeps/s390/s390-64/dl-hwcap-check.h
index 0994779a..b05c24f0 100644
--- a/sysdeps/s390/s390-64/dl-hwcap-check.h
+++ b/sysdeps/s390/s390-64/dl-hwcap-check.h
@@ -22,7 +22,7 @@ 
 #include <gcc-macros.h>
 #include <ldsodefs.h>
 
-static inline void
+static inline void __TEXT_STARTUP
 dl_hwcap_check (void)
 {
 #if defined __ARCH__
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
index 9fabb097..6ab736c3 100644
--- a/sysdeps/s390/s390-64/dl-machine.h
+++ b/sysdeps/s390/s390-64/dl-machine.h
@@ -215,7 +215,7 @@  _dl_start_user:\n\
    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h
index 0e4eac42..f9492678 100644
--- a/sysdeps/sh/dl-machine.h
+++ b/sysdeps/sh/dl-machine.h
@@ -209,7 +209,7 @@  __fpscr_values:\n\
    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
diff --git a/sysdeps/unix/sysv/linux/_exit.c b/sysdeps/unix/sysv/linux/_exit.c
index 74d478a4..3392a2f0 100644
--- a/sysdeps/unix/sysv/linux/_exit.c
+++ b/sysdeps/unix/sysv/linux/_exit.c
@@ -22,7 +22,7 @@ 
 #include <abort-instr.h>
 
 
-void
+void __TEXT_EXIT
 _exit (int status)
 {
   while (1)
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
index dc09c1c8..612691cb 100644
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
@@ -49,7 +49,7 @@  static struct cpu_list cpu_list[] = {
       {"generic", 	 0x0}
 };
 
-static uint64_t
+static uint64_t __TEXT_STARTUP
 get_midr_from_mcpu (const char *mcpu)
 {
   for (int i = 0; i < sizeof (cpu_list) / sizeof (struct cpu_list); i++)
@@ -59,7 +59,7 @@  get_midr_from_mcpu (const char *mcpu)
   return UINT64_MAX;
 }
 
-static inline void
+static inline void __TEXT_STARTUP
 init_cpu_features (struct cpu_features *cpu_features)
 {
   register uint64_t midr = UINT64_MAX;
diff --git a/sysdeps/unix/sysv/linux/check_pf.c b/sysdeps/unix/sysv/linux/check_pf.c
index 2b0b8b63..7fc85816 100644
--- a/sysdeps/unix/sysv/linux/check_pf.c
+++ b/sysdeps/unix/sysv/linux/check_pf.c
@@ -377,7 +377,7 @@  __check_pf (bool *seen_ipv4, bool *seen_ipv6,
 }
 
 /* Free the cache if it has been allocated.  */
-void
+void __TEXT_EXIT
 __check_pf_freemem (void)
 {
   if (cache)
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c
index 1b3dd869..fe9d46e0 100644
--- a/sysdeps/unix/sysv/linux/dl-sysdep.c
+++ b/sysdeps/unix/sysv/linux/dl-sysdep.c
@@ -72,7 +72,7 @@  struct dl_main_arguments
 
 /* Separate function, so that dl_main can be called without the large
    array on the stack.  */
-static void
+static void __TEXT_STARTUP
 _dl_sysdep_parse_arguments (void **start_argptr,
 			    struct dl_main_arguments *args)
 {
@@ -95,7 +95,7 @@  _dl_sysdep_parse_arguments (void **start_argptr,
   args->user_entry = auxv_values[AT_ENTRY];
 }
 
-ElfW(Addr)
+ElfW(Addr) __TEXT_STARTUP
 _dl_sysdep_start (void **start_argptr,
 		  void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
 				   ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
@@ -142,12 +142,12 @@  _dl_sysdep_start (void **start_argptr,
   return dl_main_args.user_entry;
 }
 
-void
+void __TEXT_STARTUP
 _dl_sysdep_start_cleanup (void)
 {
 }
 
-void
+void __TEXT_STARTUP
 _dl_show_auxv (void)
 {
   char buf[64];
diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
index 41e76006..d86bc833 100644
--- a/sysdeps/unix/sysv/linux/x86/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c
@@ -30,7 +30,7 @@  get_cet_status (void)
 }
 
 # ifndef SHARED
-static inline void
+static inline void __TEXT_STARTUP
 x86_setup_tls (void)
 {
   __libc_setup_tls ();
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
index 5bff8ec0..27cce9cc 100644
--- a/sysdeps/x86/cpu-features.c
+++ b/sysdeps/x86/cpu-features.c
@@ -28,7 +28,7 @@  extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
   attribute_hidden;
 
 #ifdef __LP64__
-static void
+static void __TEXT_STARTUP
 TUNABLE_CALLBACK (set_prefer_map_32bit_exec) (tunable_val_t *valp)
 {
   if (valp->numval)
@@ -46,7 +46,7 @@  extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *)
 # include <dl-cet.h>
 #endif
 
-static void
+static void __TEXT_STARTUP
 update_active (struct cpu_features *cpu_features)
 {
   /* Copy the cpuid bits to active bits for CPU featuress whose usability
@@ -318,7 +318,7 @@  update_active (struct cpu_features *cpu_features)
   cpu_features->isa_1 = get_isa_level (cpu_features);
 }
 
-static void
+static void __TEXT_STARTUP
 get_extended_indices (struct cpu_features *cpu_features)
 {
   unsigned int eax, ebx, ecx, edx;
@@ -343,7 +343,7 @@  get_extended_indices (struct cpu_features *cpu_features)
 	     cpu_features->features[CPUID_INDEX_80000008].cpuid.edx);
 }
 
-static void
+static void __TEXT_STARTUP
 get_common_indices (struct cpu_features *cpu_features,
 		    unsigned int *family, unsigned int *model,
 		    unsigned int *extended_model, unsigned int *stepping)
@@ -417,7 +417,7 @@  _Static_assert (((index_arch_Fast_Unaligned_Load
 		     == index_arch_Fast_Copy_Backward)),
 		"Incorrect index_arch_Fast_Unaligned_Load");
 
-static inline void
+static inline void __TEXT_STARTUP
 init_cpu_features (struct cpu_features *cpu_features)
 {
   unsigned int ebx, ecx, edx;
diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
index 0d4f3285..8d9bcd40 100644
--- a/sysdeps/x86/cpu-tunables.c
+++ b/sysdeps/x86/cpu-tunables.c
@@ -86,7 +86,7 @@  extern __typeof (memcmp) DEFAULT_MEMCMP;
     }
 
 attribute_hidden
-void
+void __TEXT_STARTUP
 TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
 {
   /* The current IFUNC selection is based on microbenchmarks in glibc.
@@ -287,7 +287,7 @@  TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
 
 #if CET_ENABLED
 attribute_hidden
-void
+void __TEXT_STARTUP
 TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
 {
   if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
@@ -300,7 +300,7 @@  TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
 }
 
 attribute_hidden
-void
+void __TEXT_STARTUP
 TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *valp)
 {
   if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0)
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
index ec88945b..a58ccd73 100644
--- a/sysdeps/x86/dl-cacheinfo.h
+++ b/sysdeps/x86/dl-cacheinfo.h
@@ -98,7 +98,7 @@  static const struct intel_02_cache_info
 
 #define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known [0]))
 
-static int
+static int __TEXT_STARTUP
 intel_02_known_compare (const void *p1, const void *p2)
 {
   const struct intel_02_cache_info *i1;
@@ -115,7 +115,7 @@  intel_02_known_compare (const void *p1, const void *p2)
 
 
 static long int
-__attribute__ ((noinline))
+__attribute__ ((noinline)) __TEXT_STARTUP
 intel_check_word (int name, unsigned int value, bool *has_level_2,
 		  bool *no_level_2_or_3,
 		  const struct cpu_features *cpu_features)
@@ -246,7 +246,7 @@  intel_check_word (int name, unsigned int value, bool *has_level_2,
 }
 
 
-static long int __attribute__ ((noinline))
+static long int __attribute__ ((noinline)) __TEXT_STARTUP
 handle_intel (int name, const struct cpu_features *cpu_features)
 {
   unsigned int maxidx = cpu_features->basic.max_cpuid;
@@ -310,7 +310,7 @@  handle_intel (int name, const struct cpu_features *cpu_features)
 }
 
 
-static long int __attribute__ ((noinline))
+static long int __attribute__ ((noinline)) __TEXT_STARTUP
 handle_amd (int name)
 {
   unsigned int eax;
@@ -356,7 +356,7 @@  handle_amd (int name)
 }
 
 
-static long int __attribute__ ((noinline))
+static long int __attribute__ ((noinline)) __TEXT_STARTUP
 handle_zhaoxin (int name)
 {
   unsigned int eax;
@@ -406,7 +406,7 @@  handle_zhaoxin (int name)
   return 0;
 }
 
-static void
+static void __TEXT_STARTUP
 get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr,
                 long int core)
 {
@@ -623,7 +623,7 @@  intel_bug_no_cache_info:
   *threads_ptr = threads;
 }
 
-static void
+static void __TEXT_STARTUP
 dl_init_cacheinfo (struct cpu_features *cpu_features)
 {
   /* Find out what brand of processor.  */
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 5e3bb04d..598d30bb 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -32,7 +32,7 @@  extern void __x86_cpu_features (void) attribute_hidden;
 void (*const __x86_cpu_features_p) (void) attribute_hidden
   = __x86_cpu_features;
 
-void
+void __TEXT_STARTUP
 _dl_x86_init_cpu_features (void)
 {
   struct cpu_features *cpu_features = __get_cpu_features ();
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
index 9ea2a708..34eb865e 100644
--- a/sysdeps/x86_64/dl-machine.h
+++ b/sysdeps/x86_64/dl-machine.h
@@ -197,7 +197,7 @@  _dl_start_user:\n\
    _dl_sysdep_start.  */
 #define DL_PLATFORM_INIT dl_platform_init ()
 
-static inline void __attribute__ ((unused))
+static inline void __attribute__ ((unused)) __TEXT_STARTUP
 dl_platform_init (void)
 {
 #if IS_IN (rtld)
diff --git a/time/tzset.c b/time/tzset.c
index 8c740a4e..e666f974 100644
--- a/time/tzset.c
+++ b/time/tzset.c
@@ -610,7 +610,7 @@  __tz_convert (__time64_t timer, int use_localtime, struct tm *tp)
 }
 
 
-void
+void __TEXT_EXIT
 __libc_tzset_freemem (void)
 {
   while (tzstring_list != NULL)