update to 2.17
[platform/upstream/glibc.git] / csu / libc-start.c
index 80b672f..0afa7c0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2006, 2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2015 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
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
+#include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <ldsodefs.h>
-#include <bp-start.h>
-#include <bp-sym.h>
+#include <exit-thread.h>
 
 extern void __libc_init_first (int argc, char **argv, char **envp);
+#ifndef SHARED
+extern void __libc_csu_irel (void);
+#endif
 
 extern int __libc_multiple_libcs;
 
@@ -36,6 +38,12 @@ extern void __pthread_initialize_minimal (void);
    in thread local area.  */
 uintptr_t __stack_chk_guard attribute_relro;
 # endif
+# ifndef  THREAD_SET_POINTER_GUARD
+/* Only exported for architectures that don't store the pointer guard
+   value in thread local area.  */
+uintptr_t __pointer_chk_guard_local
+       attribute_relro attribute_hidden __attribute__ ((nocommon));
+# endif
 #endif
 
 #ifdef HAVE_PTR_NTHREADS
@@ -44,6 +52,39 @@ uintptr_t __stack_chk_guard attribute_relro;
 #endif
 
 
+#ifndef SHARED
+# include <link.h>
+# include <dl-irel.h>
+
+# ifdef ELF_MACHINE_IRELA
+#  define IREL_T       ElfW(Rela)
+#  define IPLT_START   __rela_iplt_start
+#  define IPLT_END     __rela_iplt_end
+#  define IREL         elf_irela
+# elif defined ELF_MACHINE_IREL
+#  define IREL_T       ElfW(Rel)
+#  define IPLT_START   __rel_iplt_start
+#  define IPLT_END     __rel_iplt_end
+#  define IREL         elf_irel
+# endif
+
+static void
+apply_irel (void)
+{
+# ifdef IREL
+  /* We use weak references for these so that we'll still work with a linker
+     that doesn't define them.  Such a linker doesn't support IFUNC at all
+     and so uses won't work, but a statically-linked program that doesn't
+     use any IFUNC symbols won't have a problem.  */
+  extern const IREL_T IPLT_START[] __attribute__ ((weak));
+  extern const IREL_T IPLT_END[] __attribute__ ((weak));
+  for (const IREL_T *ipltent = IPLT_START; ipltent < IPLT_END; ++ipltent)
+    IREL (ipltent);
+# endif
+}
+#endif
+
+
 #ifdef LIBC_START_MAIN
 # ifdef LIBC_START_DISABLE_INLINE
 #  define STATIC static
@@ -52,7 +93,7 @@ uintptr_t __stack_chk_guard attribute_relro;
 # endif
 #else
 # define STATIC
-# define LIBC_START_MAIN BP_SYM (__libc_start_main)
+# define LIBC_START_MAIN __libc_start_main
 #endif
 
 #ifdef MAIN_AUXVEC_ARG
@@ -67,14 +108,14 @@ uintptr_t __stack_chk_guard attribute_relro;
 STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
                                         MAIN_AUXVEC_DECL),
                            int argc,
-                           char *__unbounded *__unbounded ubp_av,
+                           char **argv,
 #ifdef LIBC_START_MAIN_AUXVEC_ARG
-                           ElfW(auxv_t) *__unbounded auxvec,
+                           ElfW(auxv_t) *auxvec,
 #endif
                            __typeof (main) init,
                            void (*fini) (void),
                            void (*rtld_fini) (void),
-                           void *__unbounded stack_end)
+                           void *stack_end)
      __attribute__ ((noreturn));
 
 
@@ -83,29 +124,23 @@ STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
    finalizers were called in more than one place.  */
 STATIC int
 LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
-                int argc, char *__unbounded *__unbounded ubp_av,
+                int argc, char **argv,
 #ifdef LIBC_START_MAIN_AUXVEC_ARG
-                ElfW(auxv_t) *__unbounded auxvec,
+                ElfW(auxv_t) *auxvec,
 #endif
                 __typeof (main) init,
                 void (*fini) (void),
-                void (*rtld_fini) (void), void *__unbounded stack_end)
+                void (*rtld_fini) (void), void *stack_end)
 {
-#if __BOUNDED_POINTERS__
-  char **argv;
-#else
-# define argv ubp_av
-#endif
-
   /* Result of the 'main' function.  */
   int result;
 
   __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
 
 #ifndef SHARED
-  char *__unbounded *__unbounded ubp_ev = &ubp_av[argc + 1];
+  char **ev = &argv[argc + 1];
 
-  INIT_ARGV_and_ENVIRON;
+  __environ = ev;
 
   /* Store the lowest stack address.  This is done in ld.so if this is
      the code for the DSO.  */
@@ -115,16 +150,34 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
   /* First process the auxiliary vector since we need to find the
      program header to locate an eventually present PT_TLS entry.  */
 #  ifndef LIBC_START_MAIN_AUXVEC_ARG
-  ElfW(auxv_t) *__unbounded auxvec;
+  ElfW(auxv_t) *auxvec;
   {
-    char *__unbounded *__unbounded evp = ubp_ev;
+    char **evp = ev;
     while (*evp++ != NULL)
       ;
-    auxvec = (ElfW(auxv_t) *__unbounded) evp;
+    auxvec = (ElfW(auxv_t) *) evp;
   }
 #  endif
   _dl_aux_init (auxvec);
+  if (GL(dl_phdr) == NULL)
 # endif
+    {
+      /* Starting from binutils-2.23, the linker will define the
+         magic symbol __ehdr_start to point to our own ELF header
+         if it is visible in a segment that also includes the phdrs.
+         So we can set up _dl_phdr and _dl_phnum even without any
+         information from auxv.  */
+
+      extern const ElfW(Ehdr) __ehdr_start
+       __attribute__ ((weak, visibility ("hidden")));
+      if (&__ehdr_start != NULL)
+        {
+          assert (__ehdr_start.e_phentsize == sizeof *GL(dl_phdr));
+          GL(dl_phdr) = (const void *) &__ehdr_start + __ehdr_start.e_phoff;
+          GL(dl_phnum) = __ehdr_start.e_phnum;
+        }
+    }
+
 # ifdef DL_SYSDEP_OSCHECK
   if (!__libc_multiple_libcs)
     {
@@ -134,6 +187,9 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
     }
 # endif
 
+  /* Perform IREL{,A} relocations.  */
+  apply_irel ();
+
   /* Initialize the thread library at least a bit since the libgcc
      functions are using thread functions if these are available and
      we need to setup errno.  */
@@ -146,10 +202,20 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 # else
   __stack_chk_guard = stack_chk_guard;
 # endif
+
+  /* Set up the pointer guard value.  */
+  uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
+                                                        stack_chk_guard);
+# ifdef THREAD_SET_POINTER_GUARD
+  THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+# else
+  __pointer_chk_guard_local = pointer_chk_guard;
+# endif
+
 #endif
 
   /* Register the destructor of the dynamic linker if there is any.  */
-  if (__builtin_expect (rtld_fini != NULL, 1))
+  if (__glibc_likely (rtld_fini != NULL))
     __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
 
 #ifndef SHARED
@@ -180,7 +246,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 
 #ifdef SHARED
   /* Auditing checkpoint: we have a new object.  */
-  if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
     {
       struct audit_ifaces *afct = GLRO(dl_audit);
       struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
@@ -195,17 +261,20 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 #endif
 
 #ifdef SHARED
-  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
     GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
 #endif
 
+#ifndef SHARED
+  _dl_debug_initialize (0, LM_ID_BASE);
+#endif
 #ifdef HAVE_CLEANUP_JMP_BUF
   /* Memory for the cancellation buffer.  */
   struct pthread_unwind_buf unwind_buf;
 
   int not_first_call;
   not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
-  if (__builtin_expect (! not_first_call, 1))
+  if (__glibc_likely (! not_first_call))
     {
       struct pthread *self = THREAD_SELF;
 
@@ -234,7 +303,9 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
       result = 0;
 # ifdef SHARED
       unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
+#  ifdef PTR_DEMANGLE
       PTR_DEMANGLE (ptr);
+#  endif
 # else
       extern unsigned int __nptl_nthreads __attribute ((weak));
       unsigned int *const ptr = &__nptl_nthreads;
@@ -242,7 +313,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 
       if (! atomic_decrement_and_test (ptr))
        /* Not much left to do but to exit the thread, not the process.  */
-       __exit_thread (0);
+       __exit_thread ();
     }
 #else
   /* Nothing fancy, just call the function.  */