]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/generic/ldsodefs.h
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / generic / ldsodefs.h
index d4cbabab51fd6aa883af5a9273678e5246b23a36..37cab6f06b29335f942d7e1a9d9af20daef36908 100644 (file)
@@ -1,5 +1,5 @@
 /* Run-time dynamic linker data structures for loaded ELF shared objects.
-   Copyright (C) 1995-2009, 2010, 2011, 2012 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
@@ -26,6 +26,7 @@
 #define __need_NULL
 #include <stddef.h>
 #include <string.h>
+#include <stdint.h>
 
 #include <elf.h>
 #include <dlfcn.h>
 #include <link.h>
 #include <dl-lookupcfg.h>
 #include <dl-sysdep.h>
-#include <bits/libc-lock.h>
+#include <libc-lock.h>
 #include <hp-timing.h>
 #include <tls.h>
-#include <kernel-features.h>
 
 __BEGIN_DECLS
 
+#define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
+#define VALIDX(tag)    (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+                        + DT_EXTRANUM + DT_VALTAGIDX (tag))
+#define ADDRIDX(tag)   (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+                        + DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
+
 /* We use this macro to refer to ELF types independent of the native wordsize.
    `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'.  */
 #define ELFW(type)     _ElfW (ELF, __ELF_NATIVE_CLASS, type)
@@ -60,17 +66,25 @@ __BEGIN_DECLS
 /* Result of the lookup functions and how to retrieve the base address.  */
 typedef struct link_map *lookup_t;
 #define LOOKUP_VALUE(map) map
-#define LOOKUP_VALUE_ADDRESS(map) ((map) ? (map)->l_addr : 0)
+#define LOOKUP_VALUE_ADDRESS(map, set) ((set) || (map) ? (map)->l_addr : 0)
+
+/* Calculate the address of symbol REF using the base address from map MAP,
+   if non-NULL.  Don't check for NULL map if MAP_SET is TRUE.  */
+#define SYMBOL_ADDRESS(map, ref, map_set)                              \
+  ((ref) == NULL ? 0                                                   \
+   : (__glibc_unlikely ((ref)->st_shndx == SHN_ABS) ? 0                        \
+      : LOOKUP_VALUE_ADDRESS (map, map_set)) + (ref)->st_value)
 
 /* On some architectures a pointer to a function is not just a pointer
    to the actual code of the function but rather an architecture
    specific descriptor. */
 #ifndef ELF_FUNCTION_PTR_IS_SPECIAL
 # define DL_SYMBOL_ADDRESS(map, ref) \
- (void *) (LOOKUP_VALUE_ADDRESS (map) + ref->st_value)
+ (void *) SYMBOL_ADDRESS (map, ref, false)
 # define DL_LOOKUP_ADDRESS(addr) ((ElfW(Addr)) (addr))
-# define DL_DT_INIT_ADDRESS(map, start) (start)
-# define DL_DT_FINI_ADDRESS(map, start) (start)
+# define DL_CALL_DT_INIT(map, start, argc, argv, env) \
+ ((init_t) (start)) (argc, argv, env)
+# define DL_CALL_DT_FINI(map, start) ((fini_t) (start)) ()
 #endif
 
 /* On some architectures dladdr can't use st_size of all symbols this way.  */
@@ -81,11 +95,22 @@ typedef struct link_map *lookup_t;
        || (ADDR) < (L)->l_addr + (SYM)->st_value + (SYM)->st_size)     \
    && ((MATCHSYM) == NULL || (MATCHSYM)->st_value < (SYM)->st_value))
 
+/* According to the ELF gABI no STV_HIDDEN or STV_INTERNAL symbols are
+   expected to be present in dynamic symbol tables as they should have
+   been either removed or converted to STB_LOCAL binding by the static
+   linker.  However some GNU binutils versions produce such symbols in
+   some cases.  To prevent such symbols present in a buggy binary from
+   preempting global symbols we filter them out with this predicate.  */
+static __always_inline bool
+dl_symbol_visibility_binds_local_p (const ElfW(Sym) *sym)
+{
+  return (ELFW(ST_VISIBILITY) (sym->st_other) == STV_HIDDEN
+         || ELFW(ST_VISIBILITY) (sym->st_other) == STV_INTERNAL);
+}
+
 /* Unmap a loaded object, called by _dl_close (). */
 #ifndef DL_UNMAP_IS_SPECIAL
-# define DL_UNMAP(map) \
- __munmap ((void *) (map)->l_map_start,                                              \
-          (map)->l_map_end - (map)->l_map_start)
+# define DL_UNMAP(map) _dl_unmap_segments (map)
 #endif
 
 /* By default we do not need special support to initialize DSOs loaded
@@ -100,13 +125,23 @@ typedef struct link_map *lookup_t;
    satisfied by any symbol in the executable.  Some architectures do
    not support copy relocations.  In this case we define the macro to
    zero so that the code for handling them gets automatically optimized
-   out.  */
+   out.  ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA means address of protected
+   data defined in the shared library may be external, i.e., due to copy
+   relocation.  */
 #define ELF_RTYPE_CLASS_PLT 1
 #ifndef DL_NO_COPY_RELOCS
 # define ELF_RTYPE_CLASS_COPY 2
 #else
 # define ELF_RTYPE_CLASS_COPY 0
 #endif
+/* If DL_EXTERN_PROTECTED_DATA is defined, address of protected data
+   defined in the shared library may be external, i.e., due to copy
+   relocation.   */
+#ifdef DL_EXTERN_PROTECTED_DATA
+# define ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA 4
+#else
+# define ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA 0
+#endif
 
 /* ELF uses the PF_x macros to specify the segment permissions, mmap
    uses PROT_xxx.  In most cases the three macros have the values 1, 2,
@@ -121,6 +156,11 @@ typedef struct link_map *lookup_t;
    | ((PROT_WRITE | PROT_EXEC) << (PF_W | PF_X) * 4)                         \
    | ((PROT_READ | PROT_WRITE | PROT_EXEC) << ((PF_R | PF_W | PF_X) * 4)))
 
+/* The filename itself, or the main program name, if available.  */
+#define DSO_FILENAME(name) ((name)[0] ? (name)                               \
+                           : (rtld_progname ?: "<main program>"))
+
+#define RTLD_PROGNAME (rtld_progname ?: "<program name unknown>")
 
 /* For the version handling we need an array with only names and their
    hash values.  */
@@ -182,26 +222,6 @@ enum allowmask
   };
 
 
-/* Type for list of auditing interfaces.  */
-struct La_i86_regs;
-struct La_i86_retval;
-struct La_x86_64_regs;
-struct La_x86_64_retval;
-struct La_ppc32_regs;
-struct La_ppc32_retval;
-struct La_ppc64_regs;
-struct La_ppc64_retval;
-struct La_sh_regs;
-struct La_sh_retval;
-struct La_s390_32_regs;
-struct La_s390_32_retval;
-struct La_s390_64_regs;
-struct La_s390_64_retval;
-struct La_sparc32_regs;
-struct La_sparc32_retval;
-struct La_sparc64_regs;
-struct La_sparc64_retval;
-
 struct audit_ifaces
 {
   void (*activity) (uintptr_t *, unsigned int);
@@ -217,98 +237,12 @@ struct audit_ifaces
   };
   union
   {
-    Elf32_Addr (*i86_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
-                                   uintptr_t *, struct La_i86_regs *,
-                                   unsigned int *, const char *name,
-                                   long int *framesizep);
-    Elf64_Addr (*x86_64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
-                                      uintptr_t *, struct La_x86_64_regs *,
-                                      unsigned int *, const char *name,
-                                      long int *framesizep);
-    Elf32_Addr (*x32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
-                                   uintptr_t *, struct La_x32_regs *,
-                                   unsigned int *, const char *name,
-                                   long int *framesizep);
-    Elf32_Addr (*ppc32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
-                                     uintptr_t *, struct La_ppc32_regs *,
-                                     unsigned int *, const char *name,
-                                     long int *framesizep);
-    Elf64_Addr (*ppc64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
-                                     uintptr_t *, struct La_ppc64_regs *,
-                                     unsigned int *, const char *name,
-                                     long int *framesizep);
-    uintptr_t (*sh_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
-                                 uintptr_t *, const struct La_sh_regs *,
-                                 unsigned int *, const char *name,
-                                 long int *framesizep);
-    Elf32_Addr (*s390_32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
-                                       uintptr_t *, struct La_s390_32_regs *,
-                                       unsigned int *, const char *name,
-                                       long int *framesizep);
-    Elf64_Addr (*s390_64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
-                                       uintptr_t *, struct La_s390_64_regs *,
-                                       unsigned int *, const char *name,
-                                       long int *framesizep);
-    Elf32_Addr (*sparc32_gnu_pltenter) (Elf32_Sym *, unsigned int,
-                                       uintptr_t *, uintptr_t *,
-                                       const struct La_sparc32_regs *,
-                                       unsigned int *, const char *name,
-                                       long int *framesizep);
-    Elf64_Addr (*sparc64_gnu_pltenter) (Elf64_Sym *, unsigned int,
-                                       uintptr_t *, uintptr_t *,
-                                       const struct La_sparc64_regs *,
-                                       unsigned int *, const char *name,
-                                       long int *framesizep);
 #ifdef ARCH_PLTENTER_MEMBERS
     ARCH_PLTENTER_MEMBERS;
 #endif
   };
   union
   {
-    unsigned int (*i86_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
-                                    uintptr_t *, const struct La_i86_regs *,
-                                    struct La_i86_retval *, const char *);
-    unsigned int (*x86_64_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
-                                       uintptr_t *,
-                                       const struct La_x86_64_regs *,
-                                       struct La_x86_64_retval *,
-                                       const char *);
-    unsigned int (*x32_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
-                                    uintptr_t *,
-                                    const struct La_x32_regs *,
-                                    struct La_x86_64_retval *,
-                                    const char *);
-    unsigned int (*ppc32_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
-                                      uintptr_t *,
-                                      const struct La_ppc32_regs *,
-                                      struct La_ppc32_retval *, const char *);
-    unsigned int (*ppc64_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
-                                      uintptr_t *,
-                                      const struct La_ppc64_regs *,
-                                      struct La_ppc64_retval *, const char *);
-    unsigned int (*sh_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
-                                   uintptr_t *, const struct La_sh_regs *,
-                                   struct La_sh_retval *, const char *);
-    unsigned int (*s390_32_gnu_pltexit) (Elf32_Sym *, unsigned int,
-                                        uintptr_t *, uintptr_t *,
-                                        const struct La_s390_32_regs *,
-                                        struct La_s390_32_retval *,
-                                        const char *);
-    unsigned int (*s390_64_gnu_pltexit) (Elf64_Sym *, unsigned int,
-                                        uintptr_t *, uintptr_t *,
-                                        const struct La_s390_64_regs *,
-                                        struct La_s390_64_retval *,
-                                        const char *);
-    unsigned int (*sparc32_gnu_pltexit) (Elf32_Sym *, unsigned int,
-                                        uintptr_t *, uintptr_t *,
-                                        const struct La_sparc32_regs *,
-                                        struct La_sparc32_retval *,
-                                        const char *);
-    unsigned int (*sparc64_gnu_pltexit) (Elf64_Sym *, unsigned int,
-                                        uintptr_t *, uintptr_t *,
-                                        const struct La_sparc32_regs *,
-                                        struct La_sparc32_retval *,
-                                        const char *);
 #ifdef ARCH_PLTEXIT_MEMBERS
     ARCH_PLTEXIT_MEMBERS;
 #endif
@@ -321,11 +255,14 @@ struct audit_ifaces
 
 /* Test whether given NAME matches any of the names of the given object.  */
 extern int _dl_name_match_p (const char *__name, const struct link_map *__map)
-     internal_function;
+     attribute_hidden;
 
 /* Compute next higher prime number.  */
 extern unsigned long int _dl_higher_prime_number (unsigned long int n)
-     internal_function;
+     attribute_hidden;
+
+/* A stripped down strtoul-like implementation.  */
+uint64_t _dl_strtoul (const char *, char **) attribute_hidden;
 
 /* Function used as argument for `_dl_receive_error' function.  The
    arguments are the error code, error string, and the objname the
@@ -346,7 +283,7 @@ typedef void (*receiver_fct) (int, const char *, const char *);
 # define GL(name) _##name
 #else
 # define EXTERN
-# ifdef IS_IN_rtld
+# if IS_IN (rtld)
 #  define GL(name) _rtld_local._##name
 # else
 #  define GL(name) _rtld_global._##name
@@ -378,7 +315,7 @@ struct rtld_global
     /* Search table for unique objects.  */
     struct unique_sym_table
     {
-      __rtld_lock_recursive_t lock;
+      __rtld_lock_define_recursive (, lock)
       struct unique_sym
       {
        uint32_t hashval;
@@ -415,7 +352,7 @@ struct rtld_global
   /* The object to be initialized first.  */
   EXTERN struct link_map *_dl_initfirst;
 
-#if HP_TIMING_AVAIL || HP_SMALL_TIMING_AVAIL
+#if HP_SMALL_TIMING_AVAIL
   /* Start time on CPU clock.  */
   EXTERN hp_timing_t _dl_cpuclock_offset;
 #endif
@@ -430,10 +367,6 @@ struct rtld_global
   /* List of search directories.  */
   EXTERN struct r_search_path_elem *_dl_all_dirs;
 
-#ifdef _LIBC_REENTRANT
-  EXTERN void **(*_dl_error_catch_tsd) (void) __attribute__ ((const));
-#endif
-
   /* Structure describing the dynamic linker itself.  We need to
      reserve memory for the data the audit libraries need.  */
   EXTERN struct link_map _dl_rtld_map;
@@ -447,10 +380,17 @@ struct rtld_global
   EXTERN void (*_dl_rtld_unlock_recursive) (void *);
 #endif
 
+  /* Get architecture specific definitions.  */
+#define PROCINFO_DECL
+#ifndef PROCINFO_CLASS
+# define PROCINFO_CLASS EXTERN
+#endif
+#include <dl-procruntime.c>
+
   /* If loading a shared object requires that we make the stack executable
      when it was not, we do it by calling this function.
      It returns an errno code or zero on success.  */
-  EXTERN int (*_dl_make_stack_executable_hook) (void **) internal_function;
+  EXTERN int (*_dl_make_stack_executable_hook) (void **);
 
   /* Prevailing state of the stack, PF_X indicating it's executable.  */
   EXTERN ElfW(Word) _dl_stack_flags;
@@ -502,10 +442,13 @@ struct rtld_global
     size_t count;
     void *list[50];
   } *_dl_scope_free_list;
+#if !THREAD_GSCOPE_IN_TCB
+  EXTERN int _dl_thread_gscope_count;
+#endif
 #ifdef SHARED
 };
 # define __rtld_global_attribute__
-# ifdef IS_IN_rtld
+# if IS_IN (rtld)
 #  ifdef HAVE_SDATA_SECTION
 #   define __rtld_local_attribute__ \
            __attribute__ ((visibility ("hidden"), section (".sdata")))
@@ -524,7 +467,7 @@ extern struct rtld_global _rtld_global __rtld_global_attribute__;
 #ifndef SHARED
 # define GLRO(name) _##name
 #else
-# ifdef IS_IN_rtld
+# if IS_IN (rtld)
 #  define GLRO(name) _rtld_local_ro._##name
 # else
 #  define GLRO(name) _rtld_global_ro._##name
@@ -558,6 +501,9 @@ struct rtld_global_ro
   /* Cached value of `getpagesize ()'.  */
   EXTERN size_t _dl_pagesize;
 
+  /* Do we read from ld.so.cache?  */
+  EXTERN int _dl_inhibit_cache;
+
   /* Copy of the content of `_dl_main_searchlist' at startup time.  */
   EXTERN struct r_scope_elem _dl_initial_searchlist;
 
@@ -589,14 +535,17 @@ struct rtld_global_ro
   /* Mask for hardware capabilities that are available.  */
   EXTERN uint64_t _dl_hwcap;
 
+#if !HAVE_TUNABLES
   /* Mask for important hardware capabilities we honour. */
   EXTERN uint64_t _dl_hwcap_mask;
+#endif
 
-  /* Get architecture specific definitions.  */
-#define PROCINFO_DECL
-#ifndef PROCINFO_CLASS
-# define PROCINFO_CLASS EXTERN
+#ifdef HAVE_AUX_VECTOR
+  /* Pointer to the auxv list supplied to the program at startup.  */
+  EXTERN ElfW(auxv_t) *_dl_auxv;
 #endif
+
+  /* Get architecture specific definitions.  */
 #include <dl-procinfo.c>
 
   /* Names of shared object for which the RPATH should be ignored.  */
@@ -619,20 +568,19 @@ struct rtld_global_ro
   /* Map of shared object to be prelink traced.  */
   EXTERN struct link_map *_dl_trace_prelink_map;
 
-  /* All search directories defined at startup.  */
+  /* All search directories defined at startup.  This is assigned a
+     non-NULL pointer by the ld.so startup code (after initialization
+     to NULL), so this can also serve as an indicator whether a copy
+     of ld.so is initialized and active.  See the rtld_active function
+     below.  */
   EXTERN struct r_search_path_elem *_dl_init_all_dirs;
 
-#if HP_TIMING_AVAIL || HP_SMALL_TIMING_AVAIL
-  /* Overhead of a high-precision timing measurement.  */
-  EXTERN hp_timing_t _dl_hp_timing_overhead;
-#endif
-
 #ifdef NEED_DL_SYSINFO
   /* Syscall handling improvements.  This is very specific to x86.  */
   EXTERN uintptr_t _dl_sysinfo;
 #endif
 
-#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO
+#ifdef NEED_DL_SYSINFO_DSO
   /* The vsyscall page is a virtual DSO pre-mapped by the kernel.
      This points to its ELF header.  */
   EXTERN const ElfW(Ehdr) *_dl_sysinfo_dso;
@@ -642,6 +590,10 @@ struct rtld_global_ro
   EXTERN struct link_map *_dl_sysinfo_map;
 #endif
 
+  /* Mask for more hardware capabilities that are available on some
+     platforms.  */
+  EXTERN uint64_t _dl_hwcap2;
+
 #ifdef SHARED
   /* We add a function table to _rtld_global which is then used to
      call the function instead of going through the PLT.  The result
@@ -649,19 +601,11 @@ struct rtld_global_ro
      PLT relocations in libc.so.  */
   void (*_dl_debug_printf) (const char *, ...)
        __attribute__ ((__format__ (__printf__, 1, 2)));
-  int (internal_function *_dl_catch_error) (const char **, const char **,
-                                           bool *, void (*) (void *), void *);
-  void (internal_function *_dl_signal_error) (int, const char *, const char *,
-                                             const char *);
   void (*_dl_mcount) (ElfW(Addr) frompc, ElfW(Addr) selfpc);
-  lookup_t (internal_function *_dl_lookup_symbol_x) (const char *,
-                                                    struct link_map *,
-                                                    const ElfW(Sym) **,
-                                                    struct r_scope_elem *[],
-                                                    const struct r_found_version *,
-                                                    int, int,
-                                                    struct link_map *);
-  int (*_dl_check_caller) (const void *, enum allowmask);
+  lookup_t (*_dl_lookup_symbol_x) (const char *, struct link_map *,
+                                  const ElfW(Sym) **, struct r_scope_elem *[],
+                                  const struct r_found_version *, int, int,
+                                  struct link_map *);
   void *(*_dl_open) (const char *file, int mode, const void *caller_dlopen,
                     Lmid_t nsid, int argc, char *argv[], char *env[]);
   void (*_dl_close) (void *map);
@@ -673,12 +617,9 @@ struct rtld_global_ro
   /* List of auditing interfaces.  */
   struct audit_ifaces *_dl_audit;
   unsigned int _dl_naudit;
-
-  /* 0 if internal pointer values should not be guarded, 1 if they should.  */
-  EXTERN int _dl_pointer_guard;
 };
 # define __rtld_global_attribute__
-# ifdef IS_IN_rtld
+# if IS_IN (rtld)
 #  define __rtld_local_attribute__ __attribute__ ((visibility ("hidden")))
 extern struct rtld_global_ro _rtld_local_ro
     attribute_relro __rtld_local_attribute__;
@@ -695,16 +636,15 @@ extern const struct rtld_global_ro _rtld_global_ro
 #endif
 #undef EXTERN
 
-#ifdef IS_IN_rtld
-/* This is the initial value of GL(dl_error_catch_tsd).
-   A non-TLS libpthread will change it.  */
-extern void **_dl_initial_error_catch_tsd (void) __attribute__ ((const))
-     attribute_hidden;
+#ifndef SHARED
+/* dl-support.c defines these and initializes them early on.  */
+extern const ElfW(Phdr) *_dl_phdr;
+extern size_t _dl_phnum;
 #endif
 
 /* This is the initial value of GL(dl_make_stack_executable_hook).
    A threads library can change it.  */
-extern int _dl_make_stack_executable (void **stack_endp) internal_function;
+extern int _dl_make_stack_executable (void **stack_endp);
 rtld_hidden_proto (_dl_make_stack_executable)
 
 /* Variable pointing to the end of the stack (or close to it).  This value
@@ -712,7 +652,11 @@ rtld_hidden_proto (_dl_make_stack_executable)
    might use the variable which results in copy relocations on some
    platforms.  But this does not matter, ld.so can always use the local
    copy.  */
-extern void *__libc_stack_end attribute_relro;
+extern void *__libc_stack_end
+#ifndef LIBC_STACK_END_NOT_RELRO
+     attribute_relro
+#endif
+     ;
 rtld_hidden_proto (__libc_stack_end)
 
 /* Parameters passed to the dynamic linker.  */
@@ -722,23 +666,25 @@ extern char **_dl_argv
      attribute_relro
 #endif
      ;
-#ifdef IS_IN_rtld
-extern char **_dl_argv_internal attribute_hidden
+rtld_hidden_proto (_dl_argv)
+#if IS_IN (rtld)
+extern unsigned int _dl_skip_args attribute_hidden
+# ifndef DL_ARGV_NOT_RELRO
+     attribute_relro
+# endif
+     ;
+extern unsigned int _dl_skip_args_internal attribute_hidden
 # ifndef DL_ARGV_NOT_RELRO
      attribute_relro
 # endif
      ;
-# define rtld_progname (INTUSE(_dl_argv)[0])
-#else
-# define rtld_progname _dl_argv[0]
 #endif
+#define rtld_progname _dl_argv[0]
 
 /* Flag set at startup and cleared when the last initializer has run.  */
 extern int _dl_starting_up;
 weak_extern (_dl_starting_up)
-#ifdef IS_IN_rtld
-extern int _dl_starting_up_internal attribute_hidden;
-#endif
+rtld_hidden_proto (_dl_starting_up)
 
 /* Random data provided by the kernel.  */
 extern void *_dl_random attribute_hidden attribute_relro;
@@ -757,14 +703,25 @@ extern void _dl_debug_printf (const char *fmt, ...)
    interpreted as for a `printf' call.  All the lines buf the first
    start with a tag showing the PID.  */
 extern void _dl_debug_printf_c (const char *fmt, ...)
-     __attribute__ ((__format__ (__printf__, 1, 2)));
+     __attribute__ ((__format__ (__printf__, 1, 2))) attribute_hidden;
 
 
 /* Write a message on the specified descriptor FD.  The parameters are
    interpreted as for a `printf' call.  */
+#if IS_IN (rtld) || !defined (SHARED)
 extern void _dl_dprintf (int fd, const char *fmt, ...)
      __attribute__ ((__format__ (__printf__, 2, 3)))
      attribute_hidden;
+#else
+__attribute__ ((always_inline, __format__ (__printf__, 2, 3)))
+static inline void
+_dl_dprintf (int fd, const char *fmt, ...)
+{
+  /* Use local declaration to avoid includign <stdio.h>.  */
+  extern int __dprintf(int fd, const char *format, ...) attribute_hidden;
+  __dprintf (fd, fmt, __builtin_va_arg_pack ());
+}
+#endif
 
 /* Write a message on the specified descriptor standard output.  The
    parameters are interpreted as for a `printf' call.  */
@@ -787,29 +744,118 @@ extern void _dl_dprintf (int fd, const char *fmt, ...)
   while (1)
 
 
-/* This function is called by all the internal dynamic linker functions
-   when they encounter an error.  ERRCODE is either an `errno' code or
-   zero; OBJECT is the name of the problematical shared object, or null if
-   it is a general problem; ERRSTRING is a string describing the specific
-   problem.  */
+/* An exception raised by the _dl_signal_error function family and
+   caught by _dl_catch_error function family.  Exceptions themselves
+   are copied as part of the raise operation, but the strings are
+   not.  */
+struct dl_exception
+{
+  const char *objname;
+  const char *errstring;
+
+  /* This buffer typically stores both objname and errstring
+     above.  */
+  char *message_buffer;
+};
+
+/* Creates a new exception.  This calls malloc; if allocation fails,
+   dummy values are inserted.  OBJECT is the name of the problematical
+   shared object, or null if its a general problem.  ERRSTRING is a
+   string describing the specific problem.  */
+void _dl_exception_create (struct dl_exception *, const char *object,
+                          const char *errstring)
+  __attribute__ ((nonnull (1, 3)));
+rtld_hidden_proto (_dl_exception_create)
+
+/* Like _dl_exception_create, but create errstring from a format
+   string FMT.  Currently, only "%s" and "%%" are supported as format
+   directives.  */
+void _dl_exception_create_format (struct dl_exception *, const char *objname,
+                                 const char *fmt, ...)
+  __attribute__ ((nonnull (1, 3), format (printf, 3, 4)));
+rtld_hidden_proto (_dl_exception_create_format)
+
+/* Deallocate the exception, freeing allocated buffers (if
+   possible).  */
+void _dl_exception_free (struct dl_exception *)
+  __attribute__ ((nonnull (1)));
+rtld_hidden_proto (_dl_exception_free)
+
+/* This function is called by all the internal dynamic linker
+   functions when they encounter an error.  ERRCODE is either an
+   `errno' code or zero; it specifies the return value of
+   _dl_catch_error.  OCCASION is included in the error message if the
+   process is terminated immediately.  */
+void _dl_signal_exception (int errcode, struct dl_exception *,
+                          const char *occasion)
+  __attribute__ ((__noreturn__));
+libc_hidden_proto (_dl_signal_exception)
+
+/* Like _dl_signal_exception, but creates the exception first.  */
 extern void _dl_signal_error (int errcode, const char *object,
-                             const char *occurred, const char *errstring)
-     internal_function __attribute__ ((__noreturn__)) attribute_hidden;
+                             const char *occasion, const char *errstring)
+     __attribute__ ((__noreturn__));
+libc_hidden_proto (_dl_signal_error)
+
+/* Like _dl_signal_exception, but may return when called in the
+   context of _dl_receive_error.  This is only used during ld.so
+   bootstrap.  In static and profiled builds, this is equivalent to
+   _dl_signal_exception.  */
+#if IS_IN (rtld)
+extern void _dl_signal_cexception (int errcode, struct dl_exception *,
+                                  const char *occasion) attribute_hidden;
+#else
+__attribute__ ((always_inline))
+static inline void
+_dl_signal_cexception (int errcode, struct dl_exception *exception,
+                      const char *occasion)
+{
+  _dl_signal_exception (errcode, exception, occasion);
+}
+#endif
 
-/* Like _dl_signal_error, but may return when called in the context of
-   _dl_receive_error.  */
+/* See _dl_signal_cexception above.  */
+#if IS_IN (rtld)
 extern void _dl_signal_cerror (int errcode, const char *object,
-                              const char *occation, const char *errstring)
-     internal_function;
+                              const char *occasion, const char *errstring)
+     attribute_hidden;
+#else
+__attribute__ ((always_inline))
+static inline void
+_dl_signal_cerror (int errcode, const char *object,
+                              const char *occasion, const char *errstring)
+{
+  _dl_signal_error (errcode, object, occasion, errstring);
+}
+#endif
 
 /* Call OPERATE, receiving errors from `dl_signal_cerror'.  Unlike
    `_dl_catch_error' the operation is resumed after the OPERATE
    function returns.
    ARGS is passed as argument to OPERATE.  */
 extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
-                              void *args)
-     internal_function;
-
+                              void *args) attribute_hidden;
+
+/* Call OPERATE, catching errors from `_dl_signal_error' and related
+   functions.  If there is no error, *ERRSTRING is set to null.  If
+   there is an error, *ERRSTRING is set to a string constructed from
+   the strings passed to _dl_signal_error, and the error code passed
+   is the return value and *OBJNAME is set to the object name which
+   experienced the problems.  ERRSTRING if nonzero points to a
+   malloc'ed string which the caller has to free after use.  ARGS is
+   passed as argument to OPERATE.  MALLOCEDP is set to true only if
+   the returned string is allocated using the libc's malloc.  */
+extern int _dl_catch_error (const char **objname, const char **errstring,
+                           bool *mallocedp, void (*operate) (void *),
+                           void *args);
+libc_hidden_proto (_dl_catch_error)
+
+/* Call OPERATE (ARGS).  If no error occurs, set *EXCEPTION to zero.
+   Otherwise, store a copy of the raised exception in *EXCEPTION,
+   which has to be freed by _dl_exception_free.  */
+int _dl_catch_exception (struct dl_exception *exception,
+                        void (*operate) (void *), void *args);
+libc_hidden_proto (_dl_catch_exception)
 
 /* Open the shared object NAME and map in its segments.
    LOADER's DT_RPATH is used in searching for NAME.
@@ -817,8 +863,7 @@ extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
 extern struct link_map *_dl_map_object (struct link_map *loader,
                                        const char *name,
                                        int type, int trace_mode, int mode,
-                                       Lmid_t nsid)
-     internal_function attribute_hidden;
+                                       Lmid_t nsid) attribute_hidden;
 
 /* Call _dl_map_object on the dependencies of MAP, and set up
    MAP->l_searchlist.  PRELOADS points to a vector of NPRELOADS previously
@@ -828,11 +873,10 @@ extern void _dl_map_object_deps (struct link_map *map,
                                 struct link_map **preloads,
                                 unsigned int npreloads, int trace_mode,
                                 int open_mode)
-     internal_function attribute_hidden;
+     attribute_hidden;
 
 /* Cache the locations of MAP's hash table.  */
-extern void _dl_setup_hash (struct link_map *map)
-     internal_function attribute_hidden;
+extern void _dl_setup_hash (struct link_map *map) attribute_hidden;
 
 
 /* Collect the directories in the search path for LOADER's dependencies.
@@ -841,8 +885,7 @@ extern void _dl_setup_hash (struct link_map *map)
    by a previous call with COUNTING set, and SI must point to SI->dls_size
    bytes to be used in filling in the result.  */
 extern void _dl_rtld_di_serinfo (struct link_map *loader,
-                                Dl_serinfo *si, bool counting)
-     internal_function;
+                                Dl_serinfo *si, bool counting);
 
 
 /* Search loaded objects' symbol tables for a definition of the symbol
@@ -873,22 +916,18 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef,
                                     const struct r_found_version *version,
                                     int type_class, int flags,
                                     struct link_map *skip_map)
-     internal_function attribute_hidden;
-
+     attribute_hidden;
 
-/* Look up symbol NAME in MAP's scope and return its run-time address.  */
-extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name)
-     internal_function;
 
 /* Add the new link_map NEW to the end of the namespace list.  */
 extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
-     internal_function attribute_hidden;
+     attribute_hidden;
 
 /* Allocate a `struct link_map' for a new object being loaded.  */
 extern struct link_map *_dl_new_object (char *realname, const char *libname,
                                        int type, struct link_map *loader,
                                        int mode, Lmid_t nsid)
-     internal_function attribute_hidden;
+     attribute_hidden;
 
 /* Relocate the given object (if it hasn't already been).
    SCOPE is passed to _dl_lookup_symbol in symbol lookups.
@@ -899,46 +938,43 @@ extern void _dl_relocate_object (struct link_map *map,
      attribute_hidden;
 
 /* Protect PT_GNU_RELRO area.  */
-extern void _dl_protect_relro (struct link_map *map)
-     internal_function attribute_hidden;
+extern void _dl_protect_relro (struct link_map *map) attribute_hidden;
 
 /* Call _dl_signal_error with a message about an unhandled reloc type.
    TYPE is the result of ELFW(R_TYPE) (r_info), i.e. an R_<CPU>_* value.
    PLT is nonzero if this was a PLT reloc; it just affects the message.  */
 extern void _dl_reloc_bad_type (struct link_map *map,
                                unsigned int type, int plt)
-     internal_function __attribute__ ((__noreturn__));
+     attribute_hidden __attribute__ ((__noreturn__));
 
 /* Resolve conflicts if prelinking.  */
 extern void _dl_resolve_conflicts (struct link_map *l,
                                   ElfW(Rela) *conflict,
-                                  ElfW(Rela) *conflictend);
+                                  ElfW(Rela) *conflictend)
+     attribute_hidden;
 
 /* Check the version dependencies of all objects available through
    MAP.  If VERBOSE print some more diagnostics.  */
 extern int _dl_check_all_versions (struct link_map *map, int verbose,
-                                  int trace_mode)
-     internal_function;
+                                  int trace_mode) attribute_hidden;
 
 /* Check the version dependencies for MAP.  If VERBOSE print some more
    diagnostics.  */
 extern int _dl_check_map_versions (struct link_map *map, int verbose,
-                                  int trace_mode)
-     internal_function;
+                                  int trace_mode) attribute_hidden;
 
 /* Initialize the object in SCOPE by calling the constructors with
    ARGC, ARGV, and ENV as the parameters.  */
 extern void _dl_init (struct link_map *main_map, int argc, char **argv,
-                     char **env) internal_function attribute_hidden;
+                     char **env) attribute_hidden;
 
 /* Call the finalizer functions of all shared objects whose
    initializer functions have completed.  */
-extern void _dl_fini (void) internal_function;
+extern void _dl_fini (void) attribute_hidden;
 
 /* Sort array MAPS according to dependencies of the contained objects.  */
-extern void _dl_sort_fini (struct link_map **maps, size_t nmaps, char *used,
-                          Lmid_t ns)
-     internal_function;
+extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
+                          char *used, bool for_fini) attribute_hidden;
 
 /* The dynamic linker calls this function before and having changing
    any shared object mappings.  The `r_state' member of `struct r_debug'
@@ -951,19 +987,18 @@ rtld_hidden_proto (_dl_debug_state)
    argument is the run-time load address of the dynamic linker, to be put
    in the `r_ldbase' member.  Returns the address of the structure.  */
 extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
-     internal_function;
+     attribute_hidden;
 
 /* Initialize the basic data structure for the search paths.  */
-extern void _dl_init_paths (const char *library_path) internal_function;
+extern void _dl_init_paths (const char *library_path) attribute_hidden;
 
 /* Gather the information needed to install the profiling tables and start
    the timers.  */
-extern void _dl_start_profile (void) internal_function attribute_hidden;
+extern void _dl_start_profile (void) attribute_hidden;
 
 /* The actual functions used to keep book on the calls.  */
 extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
-extern void _dl_mcount_internal (ElfW(Addr) frompc, ElfW(Addr) selfpc)
-     attribute_hidden;
+rtld_hidden_proto (_dl_mcount)
 
 /* This function is simply a wrapper around the _dl_mcount function
    which does not require a FROMPC parameter since this is the
@@ -971,23 +1006,22 @@ extern void _dl_mcount_internal (ElfW(Addr) frompc, ElfW(Addr) selfpc)
 extern void _dl_mcount_wrapper (void *selfpc);
 
 /* Show the members of the auxiliary array passed up from the kernel.  */
-extern void _dl_show_auxv (void) internal_function;
+extern void _dl_show_auxv (void) attribute_hidden;
 
 /* Return all environment variables starting with `LD_', one after the
    other.  */
-extern char *_dl_next_ld_env_entry (char ***position) internal_function;
+extern char *_dl_next_ld_env_entry (char ***position) attribute_hidden;
 
 /* Return an array with the names of the important hardware capabilities.  */
 extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform,
                                                        size_t paltform_len,
                                                        size_t *sz,
                                                        size_t *max_capstrlen)
-     internal_function;
+     attribute_hidden;
 
 /* Look up NAME in ld.so.cache and return the file name stored there,
-   or null if none is found.  */
-extern const char *_dl_load_cache_lookup (const char *name)
-     internal_function;
+   or null if none is found.  Caller must free returned string.  */
+extern char *_dl_load_cache_lookup (const char *name) attribute_hidden;
 
 /* If the system does not support MAP_COPY we cannot leave the file open
    all the time since this would create problems when the file is replaced.
@@ -999,8 +1033,7 @@ extern void _dl_unload_cache (void) attribute_hidden;
    most convenient manner available.  *SIZEP gets the size of the
    file.  On error MAP_FAILED is returned.  */
 extern void *_dl_sysdep_read_whole_file (const char *file, size_t *sizep,
-                                        int prot)
-     internal_function attribute_hidden;
+                                        int prot) attribute_hidden;
 
 /* System-specific function to do initial startup for the dynamic linker.
    After this, file access calls and getenv must work.  This is responsible
@@ -1013,42 +1046,57 @@ extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
                                                     ElfW(auxv_t) *auxv))
      attribute_hidden;
 
-extern void _dl_sysdep_start_cleanup (void)
-     internal_function attribute_hidden;
+extern void _dl_sysdep_start_cleanup (void) attribute_hidden;
 
 
 /* Determine next available module ID.  */
-extern size_t _dl_next_tls_modid (void) internal_function attribute_hidden;
+extern size_t _dl_next_tls_modid (void) attribute_hidden;
+
+/* Count the modules with TLS segments.  */
+extern size_t _dl_count_modids (void) attribute_hidden;
 
 /* Calculate offset of the TLS blocks in the static TLS block.  */
-extern void _dl_determine_tlsoffset (void) internal_function attribute_hidden;
+extern void _dl_determine_tlsoffset (void) attribute_hidden;
 
-/* Set up the data structures for TLS, when they were not set up at startup.
-   Returns nonzero on malloc failure.
-   This is called from _dl_map_object_from_fd or by libpthread.  */
-extern int _dl_tls_setup (void) internal_function;
-rtld_hidden_proto (_dl_tls_setup)
+#ifndef SHARED
+/* Set up the TCB for statically linked applications.  This is called
+   early during startup because we always use TLS (for errno and the
+   stack protector, among other things).  */
+void __libc_setup_tls (void);
+
+# if ENABLE_STATIC_PIE
+/* Relocate static executable with PIE.  */
+extern void _dl_relocate_static_pie (void) attribute_hidden;
+
+/* Get a pointer to _dl_main_map.  */
+extern struct link_map * _dl_get_dl_main_map (void)
+  __attribute__ ((visibility ("hidden")));
+# else
+#  define _dl_relocate_static_pie()
+# endif
+#endif
+
+/* Initialization of libpthread for statically linked applications.
+   If libpthread is not linked in, this is an empty function.  */
+void __pthread_initialize_minimal (void) weak_function;
 
 /* Allocate memory for static TLS block (unless MEM is nonzero) and dtv.  */
-extern void *_dl_allocate_tls (void *mem) internal_function;
+extern void *_dl_allocate_tls (void *mem);
 rtld_hidden_proto (_dl_allocate_tls)
 
 /* Get size and alignment requirements of the static TLS block.  */
-extern void _dl_get_tls_static_info (size_t *sizep, size_t *alignp)
-     internal_function;
+extern void _dl_get_tls_static_info (size_t *sizep, size_t *alignp);
 
-extern void _dl_allocate_static_tls (struct link_map *map)
-     internal_function attribute_hidden;
+extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden;
 
 /* These are internal entry points to the two halves of _dl_allocate_tls,
    only used within rtld.c itself at startup time.  */
-extern void *_dl_allocate_tls_storage (void)
-     internal_function attribute_hidden;
-extern void *_dl_allocate_tls_init (void *) internal_function;
+extern void *_dl_allocate_tls_storage (void) attribute_hidden;
+extern void *_dl_allocate_tls_init (void *);
 rtld_hidden_proto (_dl_allocate_tls_init)
 
 /* Deallocate memory allocated with _dl_allocate_tls.  */
-extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb) internal_function;
+extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb);
 rtld_hidden_proto (_dl_deallocate_tls)
 
 extern void _dl_nothread_init_static_tls (struct link_map *) attribute_hidden;
@@ -1057,15 +1105,11 @@ extern void _dl_nothread_init_static_tls (struct link_map *) attribute_hidden;
 extern const char *_dl_get_origin (void) attribute_hidden;
 
 /* Count DSTs.  */
-extern size_t _dl_dst_count (const char *name, int is_path) attribute_hidden;
+extern size_t _dl_dst_count (const char *name) attribute_hidden;
 
 /* Substitute DST values.  */
 extern char *_dl_dst_substitute (struct link_map *l, const char *name,
-                                char *result, int is_path) attribute_hidden;
-
-/* Check validity of the caller.  */
-extern int _dl_check_caller (const void *caller, enum allowmask mask)
-     attribute_hidden;
+                                char *result) attribute_hidden;
 
 /* Open the shared object NAME, relocate it, and run its initializer if it
    hasn't already been run.  MODE is as for `dlopen' (see <dlfcn.h>).  If
@@ -1084,17 +1128,45 @@ extern void _dl_add_to_slotinfo (struct link_map  *l) attribute_hidden;
 
 /* Update slot information data for at least the generation of the
    module with the given index.  */
-extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid);
+extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid)
+     attribute_hidden;
 
 /* Look up the module's TLS block as for __tls_get_addr,
    but never touch anything.  Return null if it's not allocated yet.  */
 extern void *_dl_tls_get_addr_soft (struct link_map *l) attribute_hidden;
 
 extern int _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
-     internal_function attribute_hidden;
+     attribute_hidden;
 
 /* Show show of an object.  */
-extern void _dl_show_scope (struct link_map *new, int from);
+extern void _dl_show_scope (struct link_map *new, int from)
+     attribute_hidden;
+
+extern struct link_map *_dl_find_dso_for_object (const ElfW(Addr) addr);
+rtld_hidden_proto (_dl_find_dso_for_object)
+
+/* Initialization which is normally done by the dynamic linker.  */
+extern void _dl_non_dynamic_init (void)
+     attribute_hidden;
+
+/* Used by static binaries to check the auxiliary vector.  */
+extern void _dl_aux_init (ElfW(auxv_t) *av)
+     attribute_hidden;
+
+/* Return true if the ld.so copy in this namespace is actually active
+   and working.  If false, the dl_open/dlfcn hooks have to be used to
+   call into the outer dynamic linker (which happens after static
+   dlopen).  */
+#ifdef SHARED
+static inline bool
+rtld_active (void)
+{
+  /* The default-initialized variable does not have a non-zero
+     dl_init_all_dirs member, so this allows us to recognize an
+     initialized and active ld.so copy.  */
+  return GLRO(dl_init_all_dirs) != NULL;
+}
+#endif
 
 __END_DECLS