__noreturn void __libc_init(void* raw_args, void (*onexit)(void), int (*slingshot)(int, char**, char**), structors_array_t const * const structors) { KernelArgumentBlock args(raw_args); __libc_init_tls(args); __libc_init_common(args); apply_gnu_relro(); // Several Linux ABIs don't pass the onexit pointer, and the ones that // do never use it. Therefore, we ignore it. call_array(structors->preinit_array); call_array(structors->init_array); // The executable may have its own destructors listed in its .fini_array // so we need to ensure that these are called when the program exits // normally. if (structors->fini_array != NULL) { __cxa_atexit(__libc_fini,structors->fini_array,NULL); } exit(slingshot(args.argc, args.argv, args.envp)); }
// We flag the __libc_preinit function as a constructor to ensure // that its address is listed in libc.so's .init_array section. // This ensures that the function is called by the dynamic linker // as soon as the shared library is loaded. __attribute__((constructor)) static void __libc_preinit() { /* ARC MOD BEGIN */ #endif /* Initialize IRT table using __nacl_irt_query. */ #if defined(__native_client__) || defined(BARE_METAL_BIONIC) __nacl_irt_query = irt_query; __init_irt_table(); #endif /* ARC MOD END */ // Read the kernel argument block pointer from TLS. void* tls = const_cast<void*>(__get_tls()); KernelArgumentBlock** args_slot = &reinterpret_cast<KernelArgumentBlock**>(tls)[TLS_SLOT_BIONIC_PREINIT]; KernelArgumentBlock* args = *args_slot; // Clear the slot so no other initializer sees its value. // __libc_init_common() will change the TLS area so the old one won't be accessible anyway. *args_slot = NULL; __libc_init_common(*args); // Hooks for the debug malloc and pthread libraries to let them know that we're starting up. /* ARC MOD BEGIN */ // We do not use the pthread debug feature. // pthread_debug_init(); /* ARC MOD END */ malloc_debug_init(); }
__noreturn void __libc_init(uintptr_t *elfdata, void (*onexit)(void), int (*slingshot)(int, char**, char**), structors_array_t const * const structors) { int argc; char **argv, **envp; /* Initialize the C runtime environment */ __libc_init_common(elfdata); /* Several Linux ABIs don't pass the onexit pointer, and the ones that * do never use it. Therefore, we ignore it. */ /* pre-init array. */ call_array(structors->preinit_array); /* .ctors section initializers, for non-arm-eabi ABIs */ call_array(structors->ctors_array); // call static constructors call_array(structors->init_array); argc = (int) *elfdata; argv = (char**)(elfdata + 1); envp = argv + argc + 1; exit(slingshot(argc, argv, envp)); }
void __libc_preinit(void) { /* Read the ELF data pointer from a special slot of the * TLS area, then call __libc_init_common with it. * * Note that: * - we clear the slot so no other initializer sees its value. * - __libc_init_common() will change the TLS area so the old one * won't be accessible anyway. */ void** tls_area = (void**)__get_tls(); unsigned* elfdata = tls_area[TLS_SLOT_BIONIC_PREINIT]; tls_area[TLS_SLOT_BIONIC_PREINIT] = NULL; __libc_init_common(elfdata); /* Setup pthread routines accordingly to the environment. * Requires system properties */ #ifdef PTHREAD_DEBUG extern void pthread_debug_init(void); pthread_debug_init(); #endif /* Setup malloc routines accordingly to the environment. * Requires system properties */ extern void malloc_debug_init(void); malloc_debug_init(); }
// We flag the __libc_preinit function as a constructor to ensure // that its address is listed in libc.so's .init_array section. // This ensures that the function is called by the dynamic linker // as soon as the shared library is loaded. __attribute__((constructor)) static void __libc_preinit() { // Read the kernel argument block pointer from TLS. void** tls = __get_tls(); KernelArgumentBlock** args_slot = &reinterpret_cast<KernelArgumentBlock**>(tls)[TLS_SLOT_BIONIC_PREINIT]; KernelArgumentBlock* args = *args_slot; // Clear the slot so no other initializer sees its value. // __libc_init_common() will change the TLS area so the old one won't be accessible anyway. *args_slot = NULL; __libc_init_common(*args); // Hooks for various libraries to let them know that we're starting up. malloc_debug_init(); netdClientInit(); }
__noreturn void __libc_init(uintptr_t *elfdata, void (*onexit)(void), int (*slingshot)(int, char**, char**), structors_array_t const * const structors) { int argc; char **argv, **envp; __libc_init_tls(NULL); /* Initialize the C runtime environment */ __libc_init_common(elfdata); /* Several Linux ABIs don't pass the onexit pointer, and the ones that * do never use it. Therefore, we ignore it. */ /* pre-init array. */ call_array(structors->preinit_array); // call static constructors call_array(structors->init_array); argc = (int) *elfdata; argv = (char**)(elfdata + 1); envp = argv + argc + 1; /* The executable may have its own destructors listed in its .fini_array * so we need to ensure that these are called when the program exits * normally. */ if (structors->fini_array) __cxa_atexit(__libc_fini,structors->fini_array,NULL); apply_gnu_relro(); exit(slingshot(argc, argv, envp)); }