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