void nacl_irt_init(uint32_t *info) { void (*fini)(void) = nacl_startup_fini(info); char **envp = nacl_startup_envp(info); environ = envp; /* * We are the true entry point, never called by a dynamic linker. * So the finalizer function pointer is always NULL. * We don't bother registering anything with atexit anyway, * since we do not expect our own exit function ever to be called. * Any cleanup we might need done must happen in nacl_irt_exit (irt_basic.c). */ assert(fini == NULL); __pthread_initialize(); __libc_init_array(); /* * SRPC is initialized for use by irt_nameservice.c, which is used * by irt_random.c, and (in Chromium) by irt_manifest.c. */ if (!NaClSrpcModuleInit()) { static const char fatal_msg[] = "NaClSrpcModuleInit() failed\n"; write(2, fatal_msg, sizeof(fatal_msg) - 1); _exit(-1); } NaClLogModuleInit(); /* Enable NaClLog'ing used by CHECK(). */ }
/* Essentially sets up mutexes to protect global data/devices */ void LockSetup(void) { /* global mutex attribute */ _MUTEX_ATTR_INIT(Mutex.mattr); #ifdef __UCLIBC__ #if ((__UCLIBC_MAJOR__ << 16)+(__UCLIBC_MINOR__ << 8)+(__UCLIBC_SUBLEVEL__) < 0x00091D) /* If uClibc < 0.9.29, then re-initialize internal pthread-structs * pthread and mutexes doesn't work after daemon() is called and * the main-process is gone. * * This workaround will probably be fixed in uClibc-0.9.28 * Other uClibc developers have noticed similar problems which are * trigged when pthread functions are used in shared libraries. */ __pthread_initial_thread_bos = NULL; __pthread_initialize(); _MUTEX_ATTR_SET(Mutex.mattr, PTHREAD_MUTEX_ADAPTIVE_NP); #else /* UCLIBC_VERSION */ _MUTEX_ATTR_SET(Mutex.mattr, PTHREAD_MUTEX_DEFAULT); #endif /* UCLIBC_VERSION */ _MUTEX_INIT(Mutex.uclibc_mutex); #else /* __UCLIBC__ */ _MUTEX_ATTR_SET(Mutex.mattr, PTHREAD_MUTEX_DEFAULT); #endif /* __UCLIBC__ */ _MUTEX_INIT(Mutex.stat_mutex); _MUTEX_INIT(Mutex.controlflags_mutex); _MUTEX_INIT(Mutex.fstat_mutex); _MUTEX_INIT(Mutex.dir_mutex); _MUTEX_INIT(Mutex.typedir_mutex); _MUTEX_INIT(Mutex.externaldir_mutex); _MUTEX_INIT(Mutex.namefind_mutex); _MUTEX_INIT(Mutex.aliasfind_mutex); _MUTEX_INIT(Mutex.externalcount_mutex); _MUTEX_INIT(Mutex.timegm_mutex); _MUTEX_INIT(Mutex.detail_mutex); RWLOCK_INIT(Mutex.lib); RWLOCK_INIT(Mutex.cache); RWLOCK_INIT(Mutex.persistent_cache); RWLOCK_INIT(Inbound_Control.lock); RWLOCK_INIT(Inbound_Control.monitor_lock); #if OW_USB _MUTEX_INIT(Mutex.libusb_mutex); #endif /* OW_USB */ }
/* * This is the true entry point for untrusted code. * See nacl_startup.h for the layout at the argument pointer. */ void _start(uint32_t *info) { void (*fini)(void) = nacl_startup_fini(info); int argc = nacl_startup_argc(info); char **argv = nacl_startup_argv(info); char **envp = nacl_startup_envp(info); Elf32_auxv_t *auxv = nacl_startup_auxv(info); environ = envp; /* * Record the approximate address from which the stack grows * (usually downwards) so that libpthread can report it. Taking the * address of any stack-allocated variable will work here. */ __nacl_initial_thread_stack_end = &info; __libnacl_irt_init(auxv); /* * If we were started by a dynamic linker, then it passed its finalizer * function here. For static linking, this is always NULL. */ if (fini != NULL) atexit(fini); atexit(&__libc_fini_array); __pthread_initialize(); __libc_init_array(); int (*main_ptr)(int argc, char **argv, char **envp) = &__nacl_main; if (main_ptr == NULL) main_ptr = &main; exit(main_ptr(argc, argv, envp)); /*NOTREACHED*/ __builtin_trap(); }
static void ptmalloc_init (void) { #if __STD_C const char* s; #else char* s; #endif int secure = 0; if(__malloc_initialized >= 0) return; __malloc_initialized = 0; #ifdef _LIBC # if defined SHARED && defined USE_TLS && !USE___THREAD /* ptmalloc_init_minimal may already have been called via __libc_malloc_pthread_startup, above. */ if (mp_.pagesize == 0) # endif #endif ptmalloc_init_minimal(); #ifndef NO_THREADS # if defined _LIBC && defined USE_TLS /* We know __pthread_initialize_minimal has already been called, and that is enough. */ # define NO_STARTER # endif # ifndef NO_STARTER /* With some threads implementations, creating thread-specific data or initializing a mutex may call malloc() itself. Provide a simple starter version (realloc() won't work). */ save_malloc_hook = __malloc_hook; save_memalign_hook = __memalign_hook; save_free_hook = __free_hook; __malloc_hook = malloc_starter; __memalign_hook = memalign_starter; __free_hook = free_starter; # ifdef _LIBC /* Initialize the pthreads interface. */ if (__pthread_initialize != NULL) __pthread_initialize(); # endif /* !defined _LIBC */ # endif /* !defined NO_STARTER */ #endif /* !defined NO_THREADS */ mutex_init(&main_arena.mutex); main_arena.next = &main_arena; #if defined _LIBC && defined SHARED /* In case this libc copy is in a non-default namespace, never use brk. Likewise if dlopened from statically linked program. */ Dl_info di; struct link_map *l; if (_dl_open_hook != NULL || (_dl_addr (ptmalloc_init, &di, &l, NULL) != 0 && l->l_ns != LM_ID_BASE)) __morecore = __failing_morecore; #endif mutex_init(&list_lock); tsd_key_create(&arena_key, NULL); tsd_setspecific(arena_key, (Void_t *)&main_arena); thread_atfork(ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2); #ifndef NO_THREADS # ifndef NO_STARTER __malloc_hook = save_malloc_hook; __memalign_hook = save_memalign_hook; __free_hook = save_free_hook; # else # undef NO_STARTER # endif #endif #ifdef _LIBC secure = __libc_enable_secure; s = NULL; if (__builtin_expect (_environ != NULL, 1)) { char **runp = _environ; char *envline; while (__builtin_expect ((envline = next_env_entry (&runp)) != NULL, 0)) { size_t len = strcspn (envline, "="); if (envline[len] != '=') /* This is a "MALLOC_" variable at the end of the string without a '=' character. Ignore it since otherwise we will access invalid memory below. */ continue; switch (len) { case 6: if (memcmp (envline, "CHECK_", 6) == 0) s = &envline[7]; break; case 8: if (! secure) { if (memcmp (envline, "TOP_PAD_", 8) == 0) mALLOPt(M_TOP_PAD, atoi(&envline[9])); else if (memcmp (envline, "PERTURB_", 8) == 0) mALLOPt(M_PERTURB, atoi(&envline[9])); } break; case 9: if (! secure && memcmp (envline, "MMAP_MAX_", 9) == 0) mALLOPt(M_MMAP_MAX, atoi(&envline[10])); break; case 15: if (! secure) { if (memcmp (envline, "TRIM_THRESHOLD_", 15) == 0) mALLOPt(M_TRIM_THRESHOLD, atoi(&envline[16])); else if (memcmp (envline, "MMAP_THRESHOLD_", 15) == 0) mALLOPt(M_MMAP_THRESHOLD, atoi(&envline[16])); } break; default: break; } } } #else if (! secure) { if((s = getenv("MALLOC_TRIM_THRESHOLD_"))) mALLOPt(M_TRIM_THRESHOLD, atoi(s)); if((s = getenv("MALLOC_TOP_PAD_"))) mALLOPt(M_TOP_PAD, atoi(s)); if((s = getenv("MALLOC_PERTURB_"))) mALLOPt(M_PERTURB, atoi(s)); if((s = getenv("MALLOC_MMAP_THRESHOLD_"))) mALLOPt(M_MMAP_THRESHOLD, atoi(s)); if((s = getenv("MALLOC_MMAP_MAX_"))) mALLOPt(M_MMAP_MAX, atoi(s)); } s = getenv("MALLOC_CHECK_"); #endif if(s) { if(s[0]) mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0')); if (check_action != 0) __malloc_check_init(); } if(__malloc_initialize_hook != NULL) (*__malloc_initialize_hook)(); __malloc_initialized = 1; }
static #endif void ptmalloc_init(void) { const char* s; int secure = 0; void *mspace; if(__malloc_initialized >= 0) return; __malloc_initialized = 0; /*if (mp_.pagesize == 0) ptmalloc_init_minimal();*/ #ifndef NO_THREADS # if USE_STARTER & 1 /* With some threads implementations, creating thread-specific data or initializing a mutex may call malloc() itself. Provide a simple starter version (realloc() won't work). */ save_malloc_hook = __malloc_hook; save_memalign_hook = __memalign_hook; save_free_hook = __free_hook; __malloc_hook = malloc_starter; __memalign_hook = memalign_starter; __free_hook = free_starter; # ifdef _LIBC /* Initialize the pthreads interface. */ if (__pthread_initialize != NULL) __pthread_initialize(); # endif /* !defined _LIBC */ # endif /* USE_STARTER & 1 */ #endif /* !defined NO_THREADS */ mutex_init(&main_arena.mutex); main_arena.next = &main_arena; mspace = create_mspace_with_base((char*)&main_arena + MSPACE_OFFSET, sizeof(main_arena) - MSPACE_OFFSET, 0); assert(mspace == arena_to_mspace(&main_arena)); mutex_init(&list_lock); tsd_key_create(&arena_key, NULL); tsd_setspecific(arena_key, (void *)&main_arena); thread_atfork(ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2); #ifndef NO_THREADS # if USE_STARTER & 1 __malloc_hook = save_malloc_hook; __memalign_hook = save_memalign_hook; __free_hook = save_free_hook; # endif # if USE_STARTER & 2 __malloc_hook = 0; __memalign_hook = 0; __free_hook = 0; # endif #endif #ifdef _LIBC secure = __libc_enable_secure; #else if (! secure) { if ((s = getenv("MALLOC_TRIM_THRESHOLD_"))) public_mALLOPt(M_TRIM_THRESHOLD, atoi(s)); if ((s = getenv("MALLOC_TOP_PAD_")) || (s = getenv("MALLOC_GRANULARITY_"))) public_mALLOPt(M_GRANULARITY, atoi(s)); if ((s = getenv("MALLOC_MMAP_THRESHOLD_"))) public_mALLOPt(M_MMAP_THRESHOLD, atoi(s)); /*if ((s = getenv("MALLOC_MMAP_MAX_"))) this is no longer available public_mALLOPt(M_MMAP_MAX, atoi(s));*/ } s = getenv("MALLOC_CHECK_"); #endif if (s) { /*if(s[0]) mALLOPt(M_CHECK_ACTION, (int)(s[0] - '0')); __malloc_check_init();*/ } if (__malloc_initialize_hook != NULL) (*__malloc_initialize_hook)(); __malloc_initialized = 1; }