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 |