diff options
Diffstat (limited to 'chrome/nacl/sel_main.cc')
-rw-r--r-- | chrome/nacl/sel_main.cc | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/chrome/nacl/sel_main.cc b/chrome/nacl/sel_main.cc new file mode 100644 index 0000000..7174706 --- /dev/null +++ b/chrome/nacl/sel_main.cc @@ -0,0 +1,210 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "build/build_config.h" + +#include "native_client/src/include/portability.h" + +#if NACL_OSX +#include <crt_externs.h> +#endif + +EXTERN_C_BEGIN +#include "native_client/src/shared/platform/nacl_sync.h" +#include "native_client/src/shared/platform/nacl_sync_checked.h" +#include "native_client/src/trusted/service_runtime/nacl_globals.h" +#include "native_client/src/trusted/service_runtime/expiration.h" +#include "native_client/src/trusted/service_runtime/nacl_app.h" +#include "native_client/src/trusted/service_runtime/nacl_all_modules.h" +#include "native_client/src/trusted/service_runtime/sel_ldr.h" +#include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h" +EXTERN_C_END + +int verbosity = 0; + +#ifdef __GNUC__ + +/* + * GDB's canonical overlay managment routine. + * We need its symbol in the symbol table so don't inline it. + * TODO(dje): add some explanation for the non-GDB person. + */ + +static void __attribute__ ((noinline)) _ovly_debug_event (void) { + /* + * The asm volatile is here as instructed by the GCC docs. + * It's not enough to declare a function noinline. + * GCC will still look inside the function to see if it's worth calling. + */ + asm volatile (""); +} + +#endif + +static void StopForDebuggerInit (const struct NaClApp *state) { + /* Put xlate_base in a place where gdb can find it. */ + nacl_global_xlate_base = state->xlate_base; + +#ifdef __GNUC__ + _ovly_debug_event (); +#endif +} + +int SelMain(const int desc, const NaClHandle handle) { + char *av[1]; + int ac = 1; + + char **envp; + struct NaClApp state; + char *nacl_file = 0; + int main_thread_only = 1; + int export_addr_to = -2; + + struct NaClApp *nap; + + NaClErrorCode errcode; + + int ret_code = 1; +#if NACL_OSX + // Mac dynamic libraries cannot access the environ variable directly. + envp = *_NSGetEnviron(); +#else + extern char **environ; + envp = environ; +#endif + + + if (NaClHasExpired()) { + // TODO(gregoryd): report error to browser? + fprintf(stderr, "This version of Native Client has expired.\n"); + fprintf(stderr, "Please visit: http://code.google.com/p/nativeclient/\n"); + exit(-1); + } + + NaClAllModulesInit(); + + /* used to be -P */ + NaClSrpcFileDescriptor = desc; + /* used to be -X */ + export_addr_to = desc; + + /* to be passed to NaClMain, eventually... */ + av[0] = const_cast<char*>("NaClMain"); + + if (!NaClAppCtor(&state)) { + fprintf(stderr, "Error while constructing app state\n"); + goto done_file_dtor; + } + + state.restrict_to_main_thread = main_thread_only; + + nap = &state; + errcode = LOAD_OK; + + /* import IMC handle - used to be "-i" */ + NaClAddImcHandle(nap, handle, desc); + + /* + * in order to report load error to the browser plugin through the + * secure command channel, we do not immediate jump to cleanup code + * on error. rather, we continue processing (assuming earlier + * errors do not make it inappropriate) until the secure command + * channel is set up, and then bail out. + */ + + /* + * Ensure this operating system platform is supported. + */ + if (!NaClOsIsSupported()) { + errcode = LOAD_UNSUPPORTED_OS_PLATFORM; + nap->module_load_status = errcode; + fprintf(stderr, "Error while loading \"%s\": %s\n", + nacl_file, + NaClErrorString(errcode)); + } + + /* Give debuggers a well known point at which xlate_base is known. */ + StopForDebuggerInit(&state); + + /* + * If export_addr_to is set to a non-negative integer, we create a + * bound socket and socket address pair and bind the former to + * descriptor 3 and the latter to descriptor 4. The socket address + * is written out to the export_addr_to descriptor. + * + * The service runtime also accepts a connection on the bound socket + * and spawns a secure command channel thread to service it. + * + * If export_addr_to is -1, we only create the bound socket and + * socket address pair, and we do not export to an IMC socket. This + * use case is typically only used in testing, where we only "dump" + * the socket address to stdout or similar channel. + */ + if (-2 < export_addr_to) { + NaClCreateServiceSocket(nap); + if (0 <= export_addr_to) { + NaClSendServiceAddressTo(nap, export_addr_to); + /* + * NB: spawns a thread that uses the command channel. we do + * this after NaClAppLoadFile so that NaClApp object is more + * fully populated. Hereafter any changes to nap should be done + * while holding locks. + */ + NaClSecureCommandChannel(nap); + } + } + + NaClXMutexLock(&nap->mu); + nap->module_load_status = LOAD_OK; + NaClXCondVarBroadcast(&nap->cv); + NaClXMutexUnlock(&nap->mu); + + if (NULL != nap->secure_channel) { + /* + * wait for start_module RPC call on secure channel thread. + */ + NaClWaitForModuleStartStatusCall(nap); + } + + /* + * error reporting done; can quit now if there was an error earlier. + */ + if (LOAD_OK != errcode) { + goto done; + } + + /* + * only nap->ehdrs.e_entry is usable, no symbol table is + * available. + */ + if (!NaClCreateMainThread(nap, + ac, + av, + envp)) { + fprintf(stderr, "creating main thread failed\n"); + goto done; + } + + ret_code = NaClWaitForMainThreadToExit(nap); + + /* + * exit_group or equiv kills any still running threads while module + * addr space is still valid. otherwise we'd have to kill threads + * before we clean up the address space. + */ + return ret_code; + + done: + fflush(stdout); + + NaClAppDtor(&state); + + done_file_dtor: + fflush(stdout); + + NaClAllModulesFini(); + + return ret_code; +} + |