(linenum→info "unix/slp.c:2238")

glibc/2.7/csu/libc-start.c

    1: /* Copyright (C) 1998-2006, 2007 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3: 
    4:    The GNU C Library is free software; you can redistribute it and/or
    5:    modify it under the terms of the GNU Lesser General Public
    6:    License as published by the Free Software Foundation; either
    7:    version 2.1 of the License, or (at your option) any later version.
    8: 
    9:    The GNU C Library is distributed in the hope that it will be useful,
   10:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12:    Lesser General Public License for more details.
   13: 
   14:    You should have received a copy of the GNU Lesser General Public
   15:    License along with the GNU C Library; if not, write to the Free
   16:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   17:    02111-1307 USA.  */
   18: 
   19: #include <stdlib.h>
   20: #include <stdio.h>
   21: #include <unistd.h>
   22: #include <ldsodefs.h>
   23: #include <bp-start.h>
   24: #include <bp-sym.h>
   25: 
   26: extern void __libc_init_first (int argc, char **argv, char **envp);
   27: 
   28: extern int __libc_multiple_libcs;
   29: 
   30: #include <tls.h>
   31: #ifndef SHARED
   32: # include <dl-osinfo.h>
   33: extern void __pthread_initialize_minimal (void);
   34: # ifndef THREAD_SET_STACK_GUARD
   35: /* Only exported for architectures that don't store the stack guard canary
   36:    in thread local area.  */
   37: uintptr_t __stack_chk_guard attribute_relro;
   38: # endif
   39: #endif
   40: 
   41: #ifdef HAVE_PTR_NTHREADS
   42: /* We need atomic operations.  */
   43: # include <atomic.h>
   44: #endif
   45: 
   46: 
   47: #ifdef LIBC_START_MAIN
   48: # ifdef LIBC_START_DISABLE_INLINE
   49: #  define STATIC static
   50: # else
   51: #  define STATIC static inline __attribute__ ((always_inline))
   52: # endif
   53: #else
   54: # define STATIC
   55: # define LIBC_START_MAIN BP_SYM (__libc_start_main)
   56: #endif
   57: 
   58: #ifdef MAIN_AUXVEC_ARG
   59: /* main gets passed a pointer to the auxiliary.  */
   60: # define MAIN_AUXVEC_DECL       , void *
   61: # define MAIN_AUXVEC_PARAM      , auxvec
   62: #else
   63: # define MAIN_AUXVEC_DECL
   64: # define MAIN_AUXVEC_PARAM
   65: #endif
   66: 
   67: STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
   68:                                          MAIN_AUXVEC_DECL),
   69:                             int argc,
   70:                             char *__unbounded *__unbounded ubp_av,
   71: #ifdef LIBC_START_MAIN_AUXVEC_ARG
   72:                             ElfW(auxv_t) *__unbounded auxvec,
   73: #endif
   74:                             __typeof (main) init,
   75:                             void (*fini) (void),
   76:                             void (*rtld_fini) (void),
   77:                             void *__unbounded stack_end)
   78:      __attribute__ ((noreturn));
   79: 
   80: 
   81: /* Note: the fini parameter is ignored here for shared library.  It
   82:    is registered with __cxa_atexit.  This had the disadvantage that
   83:    finalizers were called in more than one place.  */
   84: STATIC int
   85: LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
   86:                  int argc, char *__unbounded *__unbounded ubp_av,
   87: #ifdef LIBC_START_MAIN_AUXVEC_ARG
   88:                  ElfW(auxv_t) *__unbounded auxvec,
   89: #endif
   90:                  __typeof (main) init,
   91:                  void (*fini) (void),
   92:                  void (*rtld_fini) (void), void *__unbounded stack_end)
   93: {
   94: #if __BOUNDED_POINTERS__
   95:   char **argv;
   96: #else
   97: # define argv ubp_av
   98: #endif
   99: 
  100:   /* Result of the 'main' function.  */
  101:   int result;
  102: 
  103:   __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
  104: 
  105: #ifndef SHARED
  106:   char *__unbounded *__unbounded ubp_ev = &ubp_av[argc + 1];
  107: 
  108:   INIT_ARGV_and_ENVIRON;
  109: 
  110:   /* Store the lowest stack address.  This is done in ld.so if this is
  111:      the code for the DSO.  */
  112:   __libc_stack_end = stack_end;
  113: 
  114: # ifdef HAVE_AUX_VECTOR
  115:   /* First process the auxiliary vector since we need to find the
  116:      program header to locate an eventually present PT_TLS entry.  */
  117: #  ifndef LIBC_START_MAIN_AUXVEC_ARG
  118:   ElfW(auxv_t) *__unbounded auxvec;
  119:   {
  120:     char *__unbounded *__unbounded evp = ubp_ev;
  121:     while (*evp++ != NULL)
  122:       ;
  123:     auxvec = (ElfW(auxv_t) *__unbounded) evp;
  124:   }
  125: #  endif
  126:   _dl_aux_init (auxvec);
  127: # endif
  128: # ifdef DL_SYSDEP_OSCHECK
  129:   if (!__libc_multiple_libcs)
  130:     {
  131:       /* This needs to run to initiliaze _dl_osversion before TLS
  132:          setup might check it.  */
  133:       DL_SYSDEP_OSCHECK (__libc_fatal);
  134:     }
  135: # endif
  136: 
  137:   /* Initialize the thread library at least a bit since the libgcc
  138:      functions are using thread functions if these are available and
  139:      we need to setup errno.  */
  140:   __pthread_initialize_minimal ();
  141: 
  142:   /* Set up the stack checker's canary.  */
  143:   uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
  144: # ifdef THREAD_SET_STACK_GUARD
  145:   THREAD_SET_STACK_GUARD (stack_chk_guard);
  146: # else
  147:   __stack_chk_guard = stack_chk_guard;
  148: # endif
  149: #endif
  150: 
  151:   /* Register the destructor of the dynamic linker if there is any.  */
  152:   if (__builtin_expect (rtld_fini != NULL, 1))
  153:     __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
  154: 
  155: #ifndef SHARED
  156:   /* Call the initializer of the libc.  This is only needed here if we
  157:      are compiling for the static library in which case we haven't
  158:      run the constructors in `_dl_start_user'.  */
  159:   __libc_init_first (argc, argv, __environ);
  160: 
  161:   /* Register the destructor of the program, if any.  */
  162:   if (fini)
  163:     __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
  164: 
  165:   /* Some security at this point.  Prevent starting a SUID binary where
  166:      the standard file descriptors are not opened.  We have to do this
  167:      only for statically linked applications since otherwise the dynamic
  168:      loader did the work already.  */
  169:   if (__builtin_expect (__libc_enable_secure, 0))
  170:     __libc_check_standard_fds ();
  171: #endif
  172: 
  173:   /* Call the initializer of the program, if any.  */
  174: #ifdef SHARED
  175:   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
  176:     GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
  177: #endif
  178:   if (init)
  179:     (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
  180: 
  181: #ifdef SHARED
  182:   /* Auditing checkpoint: we have a new object.  */
  183:   if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
  184:     {
  185:       struct audit_ifaces *afct = GLRO(dl_audit);
  186:       struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
  187:       for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
  188:         {
  189:           if (afct->preinit != NULL)
  190:             afct->preinit (&head->l_audit[cnt].cookie);
  191: 
  192:           afct = afct->next;
  193:         }
  194:     }
  195: #endif
  196: 
  197: #ifdef SHARED
  198:   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
  199:     GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
  200: #endif
  201: 
  202: #ifdef HAVE_CLEANUP_JMP_BUF
  203:   /* Memory for the cancellation buffer.  */
  204:   struct pthread_unwind_buf unwind_buf;
  205: 
  206:   int not_first_call;
  207:   not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
  208:   if (__builtin_expect (! not_first_call, 1))
  209:     {
  210:       struct pthread *self = THREAD_SELF;
  211: 
  212:       /* Store old info.  */
  213:       unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
  214:       unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
  215: 
  216:       /* Store the new cleanup handler info.  */
  217:       THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
  218: 
  219:       /* Run the program.  */
  220:       result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
  221:     }
  222:   else
  223:     {
  224:       /* Remove the thread-local data.  */
  225: # ifdef SHARED
  226:       PTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
  227: # else
  228:       extern void __nptl_deallocate_tsd (void) __attribute ((weak));
  229:       __nptl_deallocate_tsd ();
  230: # endif
  231: 
  232:       /* One less thread.  Decrement the counter.  If it is zero we
  233:          terminate the entire process.  */
  234:       result = 0;
  235: # ifdef SHARED
  236:       unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
  237:       PTR_DEMANGLE (ptr);
  238: # else
  239:       extern unsigned int __nptl_nthreads __attribute ((weak));
  240:       unsigned int *const ptr = &__nptl_nthreads;
  241: # endif
  242: 
  243:       if (! atomic_decrement_and_test (ptr))
  244:         /* Not much left to do but to exit the thread, not the process.  */
  245:         __exit_thread (0);
  246:     }
  247: #else
  248:   /* Nothing fancy, just call the function.  */
  249:   result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
  250: #endif
  251: 
  252:   exit (result);
  253: }
Syntax (Markdown)