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