| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "build/build_config.h" | |
| 6 | |
| 7 #include "native_client/src/include/portability.h" | |
| 8 | |
| 9 #if NACL_OSX | |
| 10 #include <crt_externs.h> | |
| 11 #endif | |
| 12 | |
| 13 EXTERN_C_BEGIN | |
| 14 #include "native_client/src/shared/platform/nacl_sync.h" | |
| 15 #include "native_client/src/shared/platform/nacl_sync_checked.h" | |
| 16 #include "native_client/src/trusted/service_runtime/nacl_globals.h" | |
| 17 #include "native_client/src/trusted/service_runtime/expiration.h" | |
| 18 #include "native_client/src/trusted/service_runtime/nacl_app.h" | |
| 19 #include "native_client/src/trusted/service_runtime/nacl_all_modules.h" | |
| 20 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | |
| 21 #include "native_client/src/trusted/platform_qualify/nacl_os_qualify.h" | |
| 22 EXTERN_C_END | |
| 23 | |
| 24 int verbosity = 0; | |
| 25 | |
| 26 #ifdef __GNUC__ | |
| 27 | |
| 28 /* | |
| 29 * GDB's canonical overlay managment routine. | |
| 30 * We need its symbol in the symbol table so don't inline it. | |
| 31 * TODO(dje): add some explanation for the non-GDB person. | |
| 32 */ | |
| 33 | |
| 34 static void __attribute__ ((noinline)) _ovly_debug_event (void) { | |
| 35 /* | |
| 36 * The asm volatile is here as instructed by the GCC docs. | |
| 37 * It's not enough to declare a function noinline. | |
| 38 * GCC will still look inside the function to see if it's worth calling. | |
| 39 */ | |
| 40 asm volatile (""); | |
| 41 } | |
| 42 | |
| 43 #endif | |
| 44 | |
| 45 static void StopForDebuggerInit (const struct NaClApp *state) { | |
| 46 /* Put xlate_base in a place where gdb can find it. */ | |
| 47 nacl_global_xlate_base = state->xlate_base; | |
| 48 | |
| 49 #ifdef __GNUC__ | |
| 50 _ovly_debug_event (); | |
| 51 #endif | |
| 52 } | |
| 53 | |
| 54 int SelMain(const int desc, const NaClHandle handle) { | |
| 55 char *av[1]; | |
| 56 int ac = 1; | |
| 57 | |
| 58 char **envp; | |
| 59 struct NaClApp state; | |
| 60 char *nacl_file = 0; | |
| 61 int main_thread_only = 1; | |
| 62 int export_addr_to = -2; | |
| 63 | |
| 64 struct NaClApp *nap; | |
| 65 | |
| 66 NaClErrorCode errcode; | |
| 67 | |
| 68 int ret_code = 1; | |
| 69 #if NACL_OSX | |
| 70 // Mac dynamic libraries cannot access the environ variable directly. | |
| 71 envp = *_NSGetEnviron(); | |
| 72 #else | |
| 73 extern char **environ; | |
| 74 envp = environ; | |
| 75 #endif | |
| 76 | |
| 77 | |
| 78 if (NaClHasExpired()) { | |
| 79 // TODO(gregoryd): report error to browser? | |
| 80 fprintf(stderr, "This version of Native Client has expired.\n"); | |
| 81 fprintf(stderr, "Please visit: http://code.google.com/p/nativeclient/\n"); | |
| 82 exit(-1); | |
| 83 } | |
| 84 | |
| 85 NaClAllModulesInit(); | |
| 86 | |
| 87 /* used to be -P */ | |
| 88 NaClSrpcFileDescriptor = desc; | |
| 89 /* used to be -X */ | |
| 90 export_addr_to = desc; | |
| 91 | |
| 92 /* to be passed to NaClMain, eventually... */ | |
| 93 av[0] = const_cast<char*>("NaClMain"); | |
| 94 | |
| 95 if (!NaClAppCtor(&state)) { | |
| 96 fprintf(stderr, "Error while constructing app state\n"); | |
| 97 goto done_file_dtor; | |
| 98 } | |
| 99 | |
| 100 state.restrict_to_main_thread = main_thread_only; | |
| 101 | |
| 102 nap = &state; | |
| 103 errcode = LOAD_OK; | |
| 104 | |
| 105 /* import IMC handle - used to be "-i" */ | |
| 106 NaClAddImcHandle(nap, handle, desc); | |
| 107 | |
| 108 /* | |
| 109 * in order to report load error to the browser plugin through the | |
| 110 * secure command channel, we do not immediate jump to cleanup code | |
| 111 * on error. rather, we continue processing (assuming earlier | |
| 112 * errors do not make it inappropriate) until the secure command | |
| 113 * channel is set up, and then bail out. | |
| 114 */ | |
| 115 | |
| 116 /* | |
| 117 * Ensure this operating system platform is supported. | |
| 118 */ | |
| 119 if (!NaClOsIsSupported()) { | |
| 120 errcode = LOAD_UNSUPPORTED_OS_PLATFORM; | |
| 121 nap->module_load_status = errcode; | |
| 122 fprintf(stderr, "Error while loading \"%s\": %s\n", | |
| 123 nacl_file, | |
| 124 NaClErrorString(errcode)); | |
| 125 } | |
| 126 | |
| 127 /* Give debuggers a well known point at which xlate_base is known. */ | |
| 128 StopForDebuggerInit(&state); | |
| 129 | |
| 130 /* | |
| 131 * If export_addr_to is set to a non-negative integer, we create a | |
| 132 * bound socket and socket address pair and bind the former to | |
| 133 * descriptor 3 and the latter to descriptor 4. The socket address | |
| 134 * is written out to the export_addr_to descriptor. | |
| 135 * | |
| 136 * The service runtime also accepts a connection on the bound socket | |
| 137 * and spawns a secure command channel thread to service it. | |
| 138 * | |
| 139 * If export_addr_to is -1, we only create the bound socket and | |
| 140 * socket address pair, and we do not export to an IMC socket. This | |
| 141 * use case is typically only used in testing, where we only "dump" | |
| 142 * the socket address to stdout or similar channel. | |
| 143 */ | |
| 144 if (-2 < export_addr_to) { | |
| 145 NaClCreateServiceSocket(nap); | |
| 146 if (0 <= export_addr_to) { | |
| 147 NaClSendServiceAddressTo(nap, export_addr_to); | |
| 148 /* | |
| 149 * NB: spawns a thread that uses the command channel. we do | |
| 150 * this after NaClAppLoadFile so that NaClApp object is more | |
| 151 * fully populated. Hereafter any changes to nap should be done | |
| 152 * while holding locks. | |
| 153 */ | |
| 154 NaClSecureCommandChannel(nap); | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 NaClXMutexLock(&nap->mu); | |
| 159 nap->module_load_status = LOAD_OK; | |
| 160 NaClXCondVarBroadcast(&nap->cv); | |
| 161 NaClXMutexUnlock(&nap->mu); | |
| 162 | |
| 163 if (NULL != nap->secure_channel) { | |
| 164 /* | |
| 165 * wait for start_module RPC call on secure channel thread. | |
| 166 */ | |
| 167 NaClWaitForModuleStartStatusCall(nap); | |
| 168 } | |
| 169 | |
| 170 /* | |
| 171 * error reporting done; can quit now if there was an error earlier. | |
| 172 */ | |
| 173 if (LOAD_OK != errcode) { | |
| 174 goto done; | |
| 175 } | |
| 176 | |
| 177 /* | |
| 178 * only nap->ehdrs.e_entry is usable, no symbol table is | |
| 179 * available. | |
| 180 */ | |
| 181 if (!NaClCreateMainThread(nap, | |
| 182 ac, | |
| 183 av, | |
| 184 envp)) { | |
| 185 fprintf(stderr, "creating main thread failed\n"); | |
| 186 goto done; | |
| 187 } | |
| 188 | |
| 189 ret_code = NaClWaitForMainThreadToExit(nap); | |
| 190 | |
| 191 /* | |
| 192 * exit_group or equiv kills any still running threads while module | |
| 193 * addr space is still valid. otherwise we'd have to kill threads | |
| 194 * before we clean up the address space. | |
| 195 */ | |
| 196 return ret_code; | |
| 197 | |
| 198 done: | |
| 199 fflush(stdout); | |
| 200 | |
| 201 NaClAppDtor(&state); | |
| 202 | |
| 203 done_file_dtor: | |
| 204 fflush(stdout); | |
| 205 | |
| 206 NaClAllModulesFini(); | |
| 207 | |
| 208 return ret_code; | |
| 209 } | |
| 210 | |
| OLD | NEW |