void _start(uintptr_t info[]) { Elf_auxv_t* auxv = nacl_startup_auxv(info); grok_auxv(auxv); DO_QUERY(NACL_IRT_BASIC_v0_1, __libnacl_irt_basic); struct nacl_irt_ppapihook ppapihook; DO_QUERY(NACL_IRT_PPAPIHOOK_v0_1, ppapihook); /* This is local as a workaround to avoid having to apply * relocations to global variables. */ struct PP_StartFunctions start_funcs = { MyPPP_InitializeModule, MyPPP_ShutdownModule, MyPPP_GetInterface, }; /* Similarly, initialise some global variables, avoiding relocations. */ struct PPP_Instance_1_0 local_ppp_instance = { DidCreate, DidDestroy, DidChangeView, DidChangeFocus, HandleDocumentLoad, }; ppp_instance = local_ppp_instance; struct PPP_Messaging_1_0 local_ppp_messaging = { HandleMessage, }; ppp_messaging = local_ppp_messaging; ppapihook.ppapi_start(&start_funcs); __libnacl_irt_basic.exit(0); }
void _start(uintptr_t info[]) { Elf_auxv_t* auxv = nacl_startup_auxv(info); grok_auxv(auxv); DO_QUERY(NACL_IRT_BASIC_v0_1, __libnacl_irt_basic); DO_QUERY(NACL_IRT_RANDOM_v0_1, __libnacl_irt_random); struct nacl_irt_ppapihook ppapihook; DO_QUERY(NACL_IRT_PPAPIHOOK_v0_1, ppapihook); /* This is local as a workaround to avoid having to apply * relocations to global variables. */ struct PP_StartFunctions start_funcs; start_funcs.PPP_InitializeModule = MyPPP_InitializeModule; start_funcs.PPP_ShutdownModule = MyPPP_ShutdownModule; start_funcs.PPP_GetInterface = MyPPP_GetInterface; /* Similarly, initialize some global variables, avoiding relocations. */ ppp_instance.DidCreate = DidCreate; ppp_instance.DidDestroy = DidDestroy; ppp_instance.DidChangeView = DidChangeView; ppp_instance.DidChangeFocus = DidChangeFocus; ppp_instance.HandleDocumentLoad = HandleDocumentLoad; ppp_messaging.HandleMessage = HandleMessage; ppapihook.ppapi_start(&start_funcs); __libnacl_irt_basic.exit(0); }
/* * 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) { Elf32_auxv_t *auxv = nacl_startup_auxv(info); __libnacl_irt_init(auxv); _exit(PpapiPluginStart(ih.__nacl_irt_query)); /*NOTREACHED*/ while (1) *(volatile int *) 0; /* Crash. */ }
void _pnacl_wrapper_start(uint32_t *info) { Elf32_auxv_t *auxv = nacl_startup_auxv(info); Elf32_auxv_t *entry = NULL; for (Elf32_auxv_t *av = auxv; av->a_type != AT_NULL; ++av) { if (av->a_type == AT_SYSINFO) { entry = av; break; } } if (entry != NULL) { __pnacl_real_irt_interface = (TYPE_nacl_irt_query) entry->a_un.a_val; entry->a_type = AT_SYSINFO; entry->a_un.a_val = (uintptr_t) __pnacl_irt_interface_wrapper; } _start(info); }
/* * This is the true entry point for untrusted code. * See nacl_startup.h for the layout at the argument pointer. */ void _pnacl_wrapper_start(uint32_t *info) { Elf32_auxv_t *auxv = nacl_startup_auxv(info); Elf32_auxv_t *entry = NULL; for (Elf32_auxv_t *av = auxv; av->a_type != AT_NULL; ++av) { if (av->a_type == AT_SYSINFO) { entry = av; break; } } if (entry != NULL) { /* * Save the real irt interface query function. */ __pnacl_real_irt_query_func = (TYPE_nacl_irt_query) entry->a_un.a_val; /* * Overwrite the auxv slot with the pnacl IRT shim query function. */ entry->a_type = AT_SYSINFO; entry->a_un.a_val = (uintptr_t) __pnacl_wrap_irt_query_func; } /* If entry is NULL still allow startup to continue. It may be the case * that the IRT was not actually used (e.g., for some commandline tests). * For newlib, we can tell that the IRT isn't used when libnacl_sys_private.a * is in the bitcode link line. However, glibc does not use * libnacl_sys_private, so that would not work. We could look for -lppapi * in the bitcode link line, but looking at the bitcode link line * seems brittle (what if the bitcode link was separated from translation). * Thus we always wrap _start, even if there is no IRT auxv entry. */ /* * Call the user entry point function. It should not return. * TODO(sehr): Find a way to ensure this is invoked via a tail call. */ _start(info); }
/* * 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(); }
void nacl_irt_enter_user_code(uint32_t *info, nacl_irt_query_func_t query_func) { Elf32_auxv_t *auxv = nacl_startup_auxv(info); Elf32_auxv_t *entry = NULL; for (Elf32_auxv_t *av = auxv; av->a_type != AT_NULL; ++av) { if (av->a_type == AT_ENTRY) { entry = av; break; } } if (entry == NULL) { static const char fatal_msg[] = "irt_entry: No AT_ENTRY item found in auxv. " "Is there no user executable loaded?\n"; write(2, fatal_msg, sizeof(fatal_msg) - 1); _exit(-1); } void (*user_start)(uint32_t *) = (void (*)(uint32_t *)) entry->a_un.a_val; /* * The user application does not need to see the AT_ENTRY item. * Reuse the auxv slot and overwrite it with the IRT query function. */ entry->a_type = AT_SYSINFO; entry->a_un.a_val = (uintptr_t) query_func; /* * Call the user entry point function. It should not return. */ (*user_start)(info); /* * But just in case it does... */ _exit(0); }
static void chainload(const char *program, const char *interp_prefix, int argc, char **argv, int envc, char **envp) { if (nacl_interface_query(NACL_IRT_RESOURCE_OPEN_v0_1, &resource_open, sizeof(resource_open)) != sizeof(resource_open)) resource_open.open_resource = NULL; if (nacl_interface_query(NACL_IRT_CODE_DATA_ALLOC_v0_1, &code_data_alloc, sizeof(code_data_alloc)) != sizeof(code_data_alloc)) { fprintf(stderr, "Failed to find necessary IRT interface %s!\n", NACL_IRT_CODE_DATA_ALLOC_v0_1); exit(1); } const size_t pagesize = NACL_MAP_PAGESIZE; const TYPE_nacl_irt_query irt_query = __nacl_irt_query; /* * Populate our own info array on the stack. We do not assume that the * argv and envp arrays are in their usual layout, since the caller could * be passing different values. */ uint32_t info[NACL_STARTUP_ARGV + argc + 1 + envc + 1 + (kAuxvCount * 2)]; info[NACL_STARTUP_FINI] = 0; info[NACL_STARTUP_ENVC] = envc; info[NACL_STARTUP_ARGC] = argc; memcpy(nacl_startup_argv(info), argv, (argc + 1) * sizeof(argv[0])); memcpy(nacl_startup_envp(info), envp, (envc + 1) * sizeof(envp[0])); Elf32_auxv_t *auxv = nacl_startup_auxv(info); /* * Populate the auxiliary vector with the values dynamic linkers expect. */ auxv[kPhdr].a_type = AT_PHDR; auxv[kPhent].a_type = AT_PHENT; auxv[kPhent].a_un.a_val = sizeof(Elf32_Phdr); auxv[kPhnum].a_type = AT_PHNUM; auxv[kBase].a_type = AT_BASE; auxv[kEntry].a_type = AT_ENTRY; auxv[kSysinfo].a_type = AT_SYSINFO; auxv[kSysinfo].a_un.a_val = (uint32_t) irt_query; auxv[kNull].a_type = AT_NULL; auxv[kNull].a_un.a_val = 0; /* * Load the program and point the auxv elements at its phdrs and entry. */ const char *interp = NULL; uint32_t entry = load_elf_file(program, pagesize, &auxv[kBase].a_un.a_val, &auxv[kPhdr].a_un.a_val, &auxv[kPhnum].a_un.a_val, &interp); auxv[kEntry].a_un.a_val = entry; if (auxv[kPhdr].a_un.a_val == 0) auxv[kPhdr].a_type = AT_IGNORE; DEBUG_PRINTF("XXX loaded %s, entry %#x, interp %s\n", program, entry, interp); if (interp != NULL) { /* * There was a PT_INTERP, so we have a dynamic linker to load. */ char interp_buf[PATH_MAX]; if (interp_prefix != NULL) { /* * Apply the command-line-specified prefix to the embedded file name. */ snprintf(interp_buf, sizeof(interp_buf), "%s%s", interp_prefix, interp); interp = interp_buf; } entry = load_elf_file(interp, pagesize, NULL, NULL, NULL, NULL); DEBUG_PRINTF("XXX loaded PT_INTERP %s, entry %#x\n", interp, entry); } for (uint32_t *p = info; p < (uint32_t *) &auxv[kNull + 1]; ++p) DEBUG_PRINTF("XXX info[%d] = %#x\n", p - info, *p); /* * Off to the races! * The application's entry point should not return. Crash if it does. */ DEBUG_PRINTF("XXX user entry point: %#x(%#x)\n", entry, (uintptr_t) info); (*(void (*)(uint32_t[])) entry)(info); while (1) __builtin_trap(); }