Back to index

glibc  2.9
Defines | Functions | Variables
libc-start.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <ldsodefs.h>
#include <bp-start.h>
#include <bp-sym.h>
#include <tls.h>
#include <dl-osinfo.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.


#define STATIC
#define LIBC_START_MAIN   BP_SYM (__libc_start_main)
#define argv   ubp_av


void __libc_init_first (int argc, char **argv, char **envp)
void __pthread_initialize_minimal (void)
STATIC int LIBC_START_MAIN (int(*main)(int, char **, char **MAIN_AUXVEC_DECL), int argc, char *__unbounded *__unbounded ubp_av, __typeof(main) init, void(*fini)(void), void(*rtld_fini)(void), void *__unbounded stack_end) __attribute__((noreturn))


int __libc_multiple_libcs
uintptr_t __stack_chk_guard attribute_relro

Define Documentation

#define argv   ubp_av

Definition at line 55 of file libc-start.c.

Definition at line 63 of file libc-start.c.

Definition at line 64 of file libc-start.c.

#define STATIC

Definition at line 54 of file libc-start.c.

Function Documentation

void __libc_init_first ( int  argc,
char **  argv,
char **  envp 

Definition at line 99 of file init-first.c.

  init (argc, argv, envp);

Definition at line 306 of file pthread.c.

#ifdef USE_TLS
  pthread_descr self;

  /* First of all init __pthread_handles[0] and [1] if needed.  */
# if __LT_SPINLOCK_INIT != 0
  __pthread_handles[0].h_lock = __LOCK_INITIALIZER;
  __pthread_handles[1].h_lock = __LOCK_INITIALIZER;
# endif
# ifndef SHARED
  /* Unlike in the dynamically linked case the dynamic linker has not
     taken care of initializing the TLS data structures.  */
  __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN);
# elif !USE___THREAD
  if (__builtin_expect (GL(dl_tls_dtv_slotinfo_list) == NULL, 0))
      tcbhead_t *tcbp;

      /* There is no actual TLS being used, so the thread register
        was not initialized in the dynamic linker.  */

      /* We need to install special hooks so that the malloc and memalign
        calls in _dl_tls_setup and _dl_allocate_tls won't cause full
        malloc initialization that will try to set up its thread state.  */

      extern void __libc_malloc_pthread_startup (bool first_time);
      __libc_malloc_pthread_startup (true);

      if (__builtin_expect (_dl_tls_setup (), 0)
         || __builtin_expect ((tcbp = _dl_allocate_tls (NULL)) == NULL, 0))
         static const char msg[] = "\
cannot allocate TLS data structures for initial thread\n";
         TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO,
                                          msg, sizeof msg - 1));
         abort ();
      const char *lossage = TLS_INIT_TP (tcbp, 0);
      if (__builtin_expect (lossage != NULL, 0))
         static const char msg[] = "cannot set up thread-local storage: ";
         const char nl = '\n';
         TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO,
                                          msg, sizeof msg - 1));
         TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO,
                                          lossage, strlen (lossage)));
         TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, &nl, 1));

      /* Though it was allocated with libc's malloc, that was done without
        the user's __malloc_hook installed.  A later realloc that uses
        the hooks might not work with that block from the plain malloc.
        So we record this block as unfreeable just as the dynamic linker
        does when it allocates the DTV before the libc malloc exists.  */
      GL(dl_initial_dtv) = GET_DTV (tcbp);

      __libc_malloc_pthread_startup (false);
# endif

  self = THREAD_SELF;

  /* The memory for the thread descriptor was allocated elsewhere as
     part of the TLS allocation.  We have to initialize the data
     structure by hand.  This initialization must mirror the struct
     definition above.  */
  self->p_nextlive = self->p_prevlive = self;
  self->p_tid = PTHREAD_THREADS_MAX;
  self->p_lock = &__pthread_handles[0].h_lock;
# ifndef HAVE___THREAD
  self->p_errnop = &_errno;
  self->p_h_errnop = &_h_errno;
# endif
  /* self->p_start_args need not be initialized, it's all zero.  */
  self->p_userstack = 1;
# if __LT_SPINLOCK_INIT != 0
  self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER;
# endif
  self->p_alloca_cutoff = __MAX_ALLOCA_CUTOFF;

  /* Another variable which points to the thread descriptor.  */
  __pthread_main_thread = self;

  /* And fill in the pointer the the thread __pthread_handles array.  */
  __pthread_handles[0].h_descr = self;

#else  /* USE_TLS */

  /* First of all init __pthread_handles[0] and [1].  */
# if __LT_SPINLOCK_INIT != 0
  __pthread_handles[0].h_lock = __LOCK_INITIALIZER;
  __pthread_handles[1].h_lock = __LOCK_INITIALIZER;
# endif
  __pthread_handles[0].h_descr = &__pthread_initial_thread;
  __pthread_handles[1].h_descr = &__pthread_manager_thread;

  /* If we have special thread_self processing, initialize that for the
     main thread now.  */
  INIT_THREAD_SELF(&__pthread_initial_thread, 0);
# endif

# ifdef USE_TLS
  self->p_cpuclock_offset = GL(dl_cpuclock_offset);
# else
  __pthread_initial_thread.p_cpuclock_offset = GL(dl_cpuclock_offset);
# endif

  __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions);

Here is the caller graph for this function:

STATIC int LIBC_START_MAIN ( int(*)(int, char **, char **MAIN_AUXVEC_DECL main,
int  argc,
char *__unbounded *__unbounded  ubp_av,
__typeof(main init,
void(*)(void)  fini,
void(*)(void)  rtld_fini,
void *__unbounded  stack_end 

Definition at line 85 of file libc-start.c.

  char **argv;
# define argv ubp_av

  /* 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];


  /* Store the lowest stack address.  This is done in if this is
     the code for the DSO.  */
  __libc_stack_end = stack_end;

  /* First process the auxiliary vector since we need to find the
     program header to locate an eventually present PT_TLS entry.  */
  ElfW(auxv_t) *__unbounded auxvec;
    char *__unbounded *__unbounded evp = ubp_ev;
    while (*evp++ != NULL)
    auxvec = (ElfW(auxv_t) *__unbounded) evp;
#  endif
  _dl_aux_init (auxvec);
# endif
  if (!__libc_multiple_libcs)
      /* This needs to run to initiliaze _dl_osversion before TLS
        setup might check it.  */
      DL_SYSDEP_OSCHECK (__libc_fatal);
# endif

  /* 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.  */
  __pthread_initialize_minimal ();

  /* Set up the stack checker's canary.  */
  uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
  THREAD_SET_STACK_GUARD (stack_chk_guard);
# else
  __stack_chk_guard = stack_chk_guard;
# endif

  /* Register the destructor of the dynamic linker if there is any.  */
  if (__builtin_expect (rtld_fini != NULL, 1))
    __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);

#ifndef SHARED
  /* Call the initializer of the libc.  This is only needed here if we
     are compiling for the static library in which case we haven't
     run the constructors in `_dl_start_user'.  */
  __libc_init_first (argc, argv, __environ);

  /* Register the destructor of the program, if any.  */
  if (fini)
    __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);

  /* Some security at this point.  Prevent starting a SUID binary where
     the standard file descriptors are not opened.  We have to do this
     only for statically linked applications since otherwise the dynamic
     loader did the work already.  */
  if (__builtin_expect (__libc_enable_secure, 0))
    __libc_check_standard_fds ();

  /* Call the initializer of the program, if any.  */
#ifdef SHARED
  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
    GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]);
  if (init)
    (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);

#ifdef SHARED
  /* Auditing checkpoint: we have a new object.  */
  if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
      struct audit_ifaces *afct = GLRO(dl_audit);
      struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
         if (afct->preinit != NULL)
           afct->preinit (&head->l_audit[cnt].cookie);

         afct = afct->next;

#ifdef SHARED
  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
    GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);

  /* 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))
      struct pthread *self = THREAD_SELF;

      /* Store old info.  */ = THREAD_GETMEM (self, cleanup_jmp_buf); = THREAD_GETMEM (self, cleanup);

      /* Store the new cleanup handler info.  */
      THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);

      /* Run the program.  */
      result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
      /* Remove the thread-local data.  */
# ifdef SHARED
      PTHFCT_CALL (ptr__nptl_deallocate_tsd, ());
# else
      extern void __nptl_deallocate_tsd (void) __attribute ((weak));
      __nptl_deallocate_tsd ();
# endif

      /* One less thread.  Decrement the counter.  If it is zero we
        terminate the entire process.  */
      result = 0;
# ifdef SHARED
      unsigned int *ptr = __libc_pthread_functions.ptr_nthreads;
      PTR_DEMANGLE (ptr);
# else
      extern unsigned int __nptl_nthreads __attribute ((weak));
      unsigned int *const ptr = &__nptl_nthreads;
# endif

      if (! atomic_decrement_and_test (ptr))
       /* Not much left to do but to exit the thread, not the process.  */
       __exit_thread (0);
  /* Nothing fancy, just call the function.  */
  result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);

  exit (result);

Here is the call graph for this function:

Variable Documentation

Definition at line 59 of file dl-sysdep.c.

Definition at line 37 of file libc-start.c.