/* Store the lowest stack address. This is done in ld.so if this is the code for the DSO. */ //保存栈的最高地址 __libc_stack_end = stack_end;
# ifdef HAVE_AUX_VECTOR //处理辅助变量 /* 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) *auxvec; { char **evp = ev; while (*evp++ != NULL) ; 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. */
/* 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 __pthread_initialize_minimal ();
//设置canary /* Set up the stack checker's canary. */ uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random); # ifdef THREAD_SET_STACK_GUARD THREAD_SET_STACK_GUARD (stack_chk_guard); # else __stack_chk_guard = stack_chk_guard; # endif
/* Set up the pointer guard value. */ //设置canary的值 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 (__glibc_likely (rtld_fini != NULL)) __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 __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 (); #endif
/* 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]); #endif if (init) (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
/* Make sure we don't initialize twice. */ if (!__libc_multiple_libcs) { /* Set the FPU control word to the proper default value if the kernel would use a different value. */ if (__fpu_control != GLRO(dl_fpu_control)) __setfpucw (__fpu_control); }
/* Save the command-line arguments. */ __libc_argc = argc; __libc_argv = argv; __environ = envp;
#ifndef SHARED __libc_init_secure ();
/* First the initialization which normally would be done by the dynamic linker. */ _dl_non_dynamic_init (); #endif
#ifdef VDSO_SETUP VDSO_SETUP (); #endif
__init_misc (argc, argv, envp);
#ifdef USE_NONOPTION_FLAGS /* This is a hack to make the special getopt in GNU libc working. */ __getopt_clean_environment (envp); #endif
/* Initialize ctype data. */ __ctype_init ();
#if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS __libc_global_ctors (); #endif }
void __libc_csu_init (int argc, char **argv, char **envp) { /* For dynamically linked executables the preinit array is executed by the dynamic linker (before initializing any shared object). */
#ifndef LIBC_NONSHARED /* For static executables, preinit happens right before init. */ { constsize_t size = __preinit_array_end - __preinit_array_start; size_t i; for (i = 0; i < size; i++) (*__preinit_array_start [i]) (argc, argv, envp); } #endif
#ifndef NO_INITFINI _init (); #endif //执行init_array中存储的函数指针 constsize_t size = __init_array_end - __init_array_start; for (size_t i = 0; i < size; i++) (*__init_array_start [i]) (argc, argv, envp); }
#ifndef SHARED _dl_debug_initialize (0, LM_ID_BASE); #endif #ifdef HAVE_CLEANUP_JMP_BUF /* Memory for the cancellation buffer. */ structpthread_unwind_bufunwind_buf;
int not_first_call; not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); if (__glibc_likely (! not_first_call)) { structpthread *self = THREAD_SELF;
/* Store old info. */ unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); unwind_buf.priv.data.cleanup = 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); } else { /* Remove the thread-local data. */ # ifdef SHARED PTHFCT_CALL (ptr__nptl_deallocate_tsd, ()); # else externvoid __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 unsignedint *ptr = __libc_pthread_functions.ptr_nthreads; # ifdef PTR_DEMANGLE PTR_DEMANGLE (ptr); # endif # else externunsignedint __nptl_nthreads __attribute ((weak)); unsignedint *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 (); } #else /* Nothing fancy, just call the function. */ result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); #endif
/* We do it this way to handle recursive calls to exit () made by the functions registered with `atexit' and `on_exit'. We call everyone on the list and use the status value in the last exit (). */ while (*listp != NULL) { structexit_function_list *cur = *listp;
case ef_free: case ef_us: break; case ef_on: onfct = f->func.on.fn; #ifdef PTR_DEMANGLE PTR_DEMANGLE (onfct); #endif onfct (status, f->func.on.arg); break; case ef_at: atfct = f->func.at; #ifdef PTR_DEMANGLE PTR_DEMANGLE (atfct); #endif atfct (); break; case ef_cxa: cxafct = f->func.cxa.fn; #ifdef PTR_DEMANGLE PTR_DEMANGLE (cxafct); #endif cxafct (f->func.cxa.arg, status); break; } }
*listp = cur->next; if (*listp != NULL) /* Don't free the last element in the chain, this is the statically allocate element. */ free (cur); } //清理IO。即调用_IO_cleanup if (run_list_atexit) RUN_HOOK (__libc_atexit, ());