OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include "native_client/src/trusted/service_runtime/osx/mach_exception_handler.h " | 7 #include "native_client/src/trusted/service_runtime/osx/mach_exception_handler.h " |
8 | 8 |
9 #include <mach/mach.h> | 9 #include <mach/mach.h> |
10 #include <mach/mach_vm.h> | 10 #include <mach/mach_vm.h> |
11 #include <mach/thread_status.h> | 11 #include <mach/thread_status.h> |
12 #include <pthread.h> | 12 #include <pthread.h> |
13 #include <stddef.h> | 13 #include <stddef.h> |
14 #include <stdio.h> | 14 #include <stdio.h> |
15 #include <stdlib.h> | 15 #include <stdlib.h> |
16 | 16 |
17 #include "native_client/src/include/nacl_macros.h" | 17 #include "native_client/src/include/nacl_macros.h" |
18 #include "native_client/src/include/portability.h" | 18 #include "native_client/src/include/portability.h" |
19 #include "native_client/src/shared/platform/nacl_check.h" | 19 #include "native_client/src/shared/platform/nacl_check.h" |
20 #include "native_client/src/shared/platform/nacl_log.h" | 20 #include "native_client/src/shared/platform/nacl_log.h" |
21 #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h" | 21 #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h" |
22 #include "native_client/src/trusted/service_runtime/nacl_app.h" | 22 #include "native_client/src/trusted/service_runtime/nacl_app.h" |
23 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h" | 23 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h" |
24 #include "native_client/src/trusted/service_runtime/nacl_config.h" | 24 #include "native_client/src/trusted/service_runtime/nacl_config.h" |
25 #include "native_client/src/trusted/service_runtime/nacl_exc.h" | 25 #include "native_client/src/trusted/service_runtime/nacl_exc.h" |
26 #include "native_client/src/trusted/service_runtime/nacl_exception.h" | 26 #include "native_client/src/trusted/service_runtime/nacl_exception.h" |
27 #include "native_client/src/trusted/service_runtime/nacl_globals.h" | 27 #include "native_client/src/trusted/service_runtime/nacl_globals.h" |
28 #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h" | 28 #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h" |
29 #include "native_client/src/trusted/service_runtime/nacl_tls.h" | |
30 #include "native_client/src/trusted/service_runtime/osx/crash_filter.h" | |
31 #include "native_client/src/trusted/service_runtime/osx/mach_thread_map.h" | |
29 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | 32 #include "native_client/src/trusted/service_runtime/sel_ldr.h" |
30 #include "native_client/src/trusted/service_runtime/sel_rt.h" | 33 #include "native_client/src/trusted/service_runtime/sel_rt.h" |
31 | 34 |
32 /* Only handle x86_32 for now. */ | 35 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 |
33 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 | |
34 | 36 |
35 | 37 |
36 /* | 38 /* |
37 * MIG generated message pump from /usr/include/mach/exc.defs | 39 * MIG generated message pump from /usr/include/mach/exc.defs |
38 * Tweaked to place in an isolated namespace. | 40 * Tweaked to place in an isolated namespace. |
39 */ | 41 */ |
40 boolean_t nacl_exc_server( | 42 boolean_t nacl_exc_server( |
41 mach_msg_header_t *InHeadP, | 43 mach_msg_header_t *InHeadP, |
42 mach_msg_header_t *OutHeadP); | 44 mach_msg_header_t *OutHeadP); |
43 | 45 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
80 } | 82 } |
81 } | 83 } |
82 | 84 |
83 static void FireDebugStubEvent(int pipe_fd) { | 85 static void FireDebugStubEvent(int pipe_fd) { |
84 char buf = 0; | 86 char buf = 0; |
85 if (write(pipe_fd, &buf, sizeof(buf)) != sizeof(buf)) { | 87 if (write(pipe_fd, &buf, sizeof(buf)) != sizeof(buf)) { |
86 NaClLog(LOG_FATAL, "FireDebugStubEvent: Can't send debug stub event\n"); | 88 NaClLog(LOG_FATAL, "FireDebugStubEvent: Can't send debug stub event\n"); |
87 } | 89 } |
88 } | 90 } |
89 | 91 |
92 #if NACL_BUILD_SUBARCH == 32 | |
93 | |
94 #define NATIVE_x86_THREAD_STATE x86_THREAD_STATE32 | |
95 #define X86_REG_BP(regs) ((regs).uts.ts32.__ebp) | |
96 #define X86_REG_SP(regs) ((regs).uts.ts32.__esp) | |
97 #define X86_REG_IP(regs) ((regs).uts.ts32.__eip) | |
98 #define X86_REG_FLAGS(regs) ((regs).uts.ts32.__eflags) | |
99 | |
100 #elif NACL_BUILD_SUBARCH == 64 | |
101 | |
102 #define NATIVE_x86_THREAD_STATE x86_THREAD_STATE64 | |
103 #define X86_REG_BP(regs) ((regs).uts.ts64.__rbp) | |
104 #define X86_REG_SP(regs) ((regs).uts.ts64.__rsp) | |
105 #define X86_REG_IP(regs) ((regs).uts.ts64.__rip) | |
106 #define X86_REG_FLAGS(regs) ((regs).uts.ts64.__rflags) | |
107 | |
108 #endif /* NACL_BUILD_SUBARCH */ | |
109 | |
90 static int HandleException(mach_port_t thread_port, | 110 static int HandleException(mach_port_t thread_port, |
91 exception_type_t exception, int *is_untrusted) { | 111 exception_type_t exception, int *is_untrusted) { |
92 mach_msg_type_number_t size; | 112 mach_msg_type_number_t size; |
93 x86_thread_state_t regs; | 113 x86_thread_state_t regs; |
94 kern_return_t result; | 114 kern_return_t result; |
95 uint16_t trusted_cs = NaClGetGlobalCs(); | |
96 uint16_t trusted_ds = NaClGetGlobalDs(); | |
97 uint32_t nacl_thread_index; | 115 uint32_t nacl_thread_index; |
98 struct NaClApp *nap; | 116 struct NaClApp *nap; |
99 struct NaClAppThread *natp; | 117 struct NaClAppThread *natp; |
100 struct NaClExceptionFrame frame; | 118 struct NaClExceptionFrame frame; |
101 uintptr_t frame_addr_user; | 119 uint32_t frame_addr_user; |
102 uintptr_t frame_addr_sys; | 120 uintptr_t frame_addr_sys; |
121 #if NACL_BUILD_SUBARCH == 32 | |
122 uint16_t trusted_cs = NaClGetGlobalCs(); | |
123 uint16_t trusted_ds = NaClGetGlobalDs(); | |
124 #endif | |
103 | 125 |
104 /* Assume untrusted crash until we know otherwise. */ | 126 /* Assume untrusted crash until we know otherwise. */ |
105 *is_untrusted = TRUE; | 127 *is_untrusted = TRUE; |
106 | 128 |
107 /* Capture the register state of the 'excepting' thread. */ | 129 /* Capture the register state of the 'excepting' thread. */ |
108 size = sizeof(regs) / sizeof(natural_t); | 130 size = x86_THREAD_STATE_COUNT; |
109 result = thread_get_state(thread_port, x86_THREAD_STATE, | 131 result = thread_get_state(thread_port, x86_THREAD_STATE, |
110 (void *) ®s, &size); | 132 (thread_state_t) ®s, &size); |
111 if (result != KERN_SUCCESS) { | 133 if (result != KERN_SUCCESS) { |
112 return 0; | 134 return 0; |
113 } | 135 } |
136 CHECK(regs.tsh.flavor == NATIVE_x86_THREAD_STATE); | |
114 | 137 |
115 /* | 138 #if NACL_BUILD_SUBARCH == 32 |
116 * If trusted_cs is 0 (which is not a usable segment selector), the | |
117 * sandbox has not been initialised yet, so there can be no untrusted | |
118 * code running. | |
119 */ | |
120 if (trusted_cs == 0) { | |
121 *is_untrusted = FALSE; | |
122 return 0; | |
123 } | |
124 | |
125 /* | |
126 * If the current code segment is the trusted one, we aren't in the | |
127 * sandbox. | |
128 * TODO(bradnelson): This makes the potentially false assumption that cs is | |
129 * the last thing to change when switching into untrusted code. We need | |
130 * tests to vet this. | |
131 */ | |
132 if (regs.uts.ts32.__cs == trusted_cs) { | |
133 /* | |
134 * If we are single-stepping, allow NaClSwitchRemainingRegsViaECX() | |
135 * to continue in order to restore control to untrusted code. | |
136 */ | |
137 if (exception == EXC_BREAKPOINT && | |
138 (regs.uts.ts32.__eflags & NACL_X86_TRAP_FLAG) != 0 && | |
139 regs.uts.ts32.__eip >= (uintptr_t) NaClSwitchRemainingRegsViaECX && | |
140 regs.uts.ts32.__eip < (uintptr_t) NaClSwitchRemainingRegsAsmEnd) { | |
141 return 1; | |
142 } | |
143 *is_untrusted = FALSE; | |
144 return 0; | |
145 } | |
146 | |
147 /* | 139 /* |
148 * We can get the thread index from the segment selector used for TLS | 140 * We can get the thread index from the segment selector used for TLS |
149 * from %gs >> 3. | 141 * from %gs >> 3. |
150 * TODO(bradnelson): Migrate that knowledge to a single shared location. | 142 * TODO(bradnelson): Migrate that knowledge to a single shared location. |
151 */ | 143 */ |
152 nacl_thread_index = regs.uts.ts32.__gs >> 3; | 144 nacl_thread_index = regs.uts.ts32.__gs >> 3; |
145 #elif NACL_BUILD_SUBARCH == 64 | |
146 nacl_thread_index = NaClGetThreadIndexForMachThread(thread_port); | |
147 #endif | |
148 | |
149 if (nacl_thread_index == NACL_TLS_INDEX_INVALID) { | |
Mark Seaborn
2013/02/20 18:33:17
This check should really go inside the "#elif NACL
| |
150 *is_untrusted = FALSE; | |
151 return 0; | |
152 } | |
153 | |
153 natp = NaClAppThreadGetFromIndex(nacl_thread_index); | 154 natp = NaClAppThreadGetFromIndex(nacl_thread_index); |
155 if (!natp) { | |
Mark Seaborn
2013/02/20 18:33:17
Nit: NaCl style is "natp == NULL"
| |
156 *is_untrusted = FALSE; | |
157 return 0; | |
158 } | |
154 nap = natp->nap; | 159 nap = natp->nap; |
155 | 160 |
161 /* | |
162 * TODO(bradnelson): For x86_32, this makes the potentially false assumption | |
163 * that cs is the last thing to change when switching into untrusted | |
164 * code. We need tests to vet this. | |
165 */ | |
166 *is_untrusted = NaClMachThreadStateIsInUntrusted(®s, nacl_thread_index); | |
167 | |
168 #if NACL_BUILD_SUBARCH == 64 | |
Mark Seaborn
2013/02/20 18:33:17
This check can be unconditional -- it's not specif
| |
169 /* | |
170 * If trusted code accidentally jumped to untrusted code, don't let the | |
171 * untrusted exception handler take over. | |
172 */ | |
173 if (*is_untrusted && | |
174 (natp->suspend_state & NACL_APP_THREAD_UNTRUSTED) == 0) { | |
175 *is_untrusted = 0; | |
Mark Seaborn
2013/02/20 18:33:17
Adding an early return here would be an additional
| |
176 } | |
177 #endif | |
178 | |
179 if (!*is_untrusted) { | |
180 #if NACL_BUILD_SUBARCH == 32 | |
181 /* | |
182 * If we are single-stepping, allow NaClSwitchRemainingRegsViaECX() | |
183 * to continue in order to restore control to untrusted code. | |
184 */ | |
185 if (exception == EXC_BREAKPOINT && | |
186 (X86_REG_FLAGS(regs) & NACL_X86_TRAP_FLAG) != 0 && | |
187 X86_REG_IP(regs) >= (uintptr_t) NaClSwitchRemainingRegsViaECX && | |
188 X86_REG_IP(regs) < (uintptr_t) NaClSwitchRemainingRegsAsmEnd) { | |
189 return 1; | |
190 } | |
191 #endif | |
192 return 0; | |
193 } | |
194 | |
156 if (nap->enable_faulted_thread_queue) { | 195 if (nap->enable_faulted_thread_queue) { |
196 #if NACL_BUILD_SUBARCH == 32 | |
157 /* | 197 /* |
158 * If we are single-stepping, step through until we reach untrusted code. | 198 * If we are single-stepping, step through until we reach untrusted code. |
159 */ | 199 */ |
160 if (exception == EXC_BREAKPOINT && | 200 if (exception == EXC_BREAKPOINT && |
161 (regs.uts.ts32.__eflags & NACL_X86_TRAP_FLAG) != 0) { | 201 (X86_REG_FLAGS(regs) & NACL_X86_TRAP_FLAG) != 0) { |
162 if (regs.uts.ts32.__eip >= nap->all_regs_springboard.start_addr && | 202 if (X86_REG_IP(regs) >= nap->all_regs_springboard.start_addr && |
163 regs.uts.ts32.__eip < nap->all_regs_springboard.end_addr) { | 203 X86_REG_IP(regs) < nap->all_regs_springboard.end_addr) { |
164 return 1; | 204 return 1; |
165 } | 205 } |
166 /* | 206 /* |
167 * Step through the instruction we have been asked to restore | 207 * Step through the instruction we have been asked to restore |
168 * control to. | 208 * control to. |
169 */ | 209 */ |
170 if (regs.uts.ts32.__eip == natp->user.gs_segment.new_prog_ctr) { | 210 if (X86_REG_IP(regs) == natp->user.gs_segment.new_prog_ctr) { |
171 return 1; | 211 return 1; |
172 } | 212 } |
173 } | 213 } |
214 #endif | |
174 | 215 |
175 /* | 216 /* |
176 * Increment the kernel's thread suspension count so that the | 217 * Increment the kernel's thread suspension count so that the |
177 * thread remains suspended after we return. | 218 * thread remains suspended after we return. |
178 */ | 219 */ |
179 result = thread_suspend(thread_port); | 220 result = thread_suspend(thread_port); |
180 if (result != KERN_SUCCESS) { | 221 if (result != KERN_SUCCESS) { |
181 NaClLog(LOG_FATAL, "HandleException: thread_suspend() call failed\n"); | 222 NaClLog(LOG_FATAL, "HandleException: thread_suspend() call failed\n"); |
182 } | 223 } |
183 /* | 224 /* |
(...skipping 12 matching lines...) Expand all Loading... | |
196 * Ignore all but bad accesses for now. | 237 * Ignore all but bad accesses for now. |
197 * TODO(bradnelson): eventually consider these too: | 238 * TODO(bradnelson): eventually consider these too: |
198 * EXC_BAD_INSTRUCTION | 239 * EXC_BAD_INSTRUCTION |
199 * EXC_ARITHMETIC | 240 * EXC_ARITHMETIC |
200 * EXC_BREAKPOINT | 241 * EXC_BREAKPOINT |
201 */ | 242 */ |
202 if (exception != EXC_BAD_ACCESS) { | 243 if (exception != EXC_BAD_ACCESS) { |
203 return 0; | 244 return 0; |
204 } | 245 } |
205 | 246 |
247 /* Don't handle if no exception handler is set. */ | |
Mark Seaborn
2013/02/20 18:33:17
Can you note this change in the commit message, pl
| |
248 if (nap->exception_handler == 0) { | |
249 return 0; | |
250 } | |
251 | |
206 /* Don't handle it if the exception flag is set. */ | 252 /* Don't handle it if the exception flag is set. */ |
207 if (natp->exception_flag) { | 253 if (natp->exception_flag) { |
208 return 0; | 254 return 0; |
209 } | 255 } |
210 /* Set the flag. */ | 256 /* Set the flag. */ |
211 natp->exception_flag = 1; | 257 natp->exception_flag = 1; |
212 | 258 |
213 /* Don't handle if no exception handler is set. */ | |
214 if (nap->exception_handler == 0) { | |
215 return 0; | |
216 } | |
217 | |
218 /* Get location of exception stack frame. */ | 259 /* Get location of exception stack frame. */ |
219 if (natp->exception_stack) { | 260 if (natp->exception_stack) { |
220 frame_addr_user = natp->exception_stack; | 261 frame_addr_user = natp->exception_stack; |
221 } else { | 262 } else { |
222 /* If not set default to user stack. */ | 263 /* If not set default to user stack. */ |
223 frame_addr_user = regs.uts.ts32.__esp; | 264 frame_addr_user = X86_REG_SP(regs) - NACL_STACK_RED_ZONE; |
224 } | 265 } |
225 | 266 |
226 /* Align stack frame properly. */ | 267 /* Align stack frame properly. */ |
227 frame_addr_user -= | 268 frame_addr_user -= |
228 sizeof(struct NaClExceptionFrame) - NACL_STACK_PAD_BELOW_ALIGN; | 269 sizeof(struct NaClExceptionFrame) - NACL_STACK_PAD_BELOW_ALIGN; |
229 frame_addr_user &= ~NACL_STACK_ALIGN_MASK; | 270 frame_addr_user &= ~NACL_STACK_ALIGN_MASK; |
230 frame_addr_user -= NACL_STACK_PAD_BELOW_ALIGN; | 271 frame_addr_user -= NACL_STACK_PAD_BELOW_ALIGN; |
231 | 272 |
232 /* Convert from user to system space. */ | 273 /* Convert from user to system space. */ |
233 frame_addr_sys = NaClUserToSysAddrRange( | 274 frame_addr_sys = NaClUserToSysAddrRange( |
234 nap, frame_addr_user, sizeof(struct NaClExceptionFrame)); | 275 nap, frame_addr_user, sizeof(struct NaClExceptionFrame)); |
235 if (frame_addr_sys == kNaClBadAddress) { | 276 if (frame_addr_sys == kNaClBadAddress) { |
236 return 0; | 277 return 0; |
237 } | 278 } |
238 | 279 |
239 /* Set up the stack frame for the handler invocation. */ | 280 /* Set up the stack frame for the handler invocation. */ |
240 frame.return_addr = 0; | 281 frame.return_addr = 0; |
282 frame.context.prog_ctr = X86_REG_IP(regs); | |
283 frame.context.stack_ptr = X86_REG_SP(regs); | |
284 frame.context.frame_ptr = X86_REG_BP(regs); | |
285 #if NACL_BUILD_SUBARCH == 32 | |
241 frame.context_ptr = frame_addr_user + | 286 frame.context_ptr = frame_addr_user + |
242 offsetof(struct NaClExceptionFrame, context); | 287 offsetof(struct NaClExceptionFrame, context); |
243 frame.context.prog_ctr = regs.uts.ts32.__eip; | 288 #endif |
244 frame.context.stack_ptr = regs.uts.ts32.__esp; | |
245 frame.context.frame_ptr = regs.uts.ts32.__ebp; | |
246 | 289 |
247 /* | 290 /* |
248 * Write the stack frame into untrusted address space. We do not | 291 * Write the stack frame into untrusted address space. We do not |
249 * write to the memory directly because that will fault if the | 292 * write to the memory directly because that will fault if the |
250 * destination location is not writable. Faulting is OK for NaCl | 293 * destination location is not writable. Faulting is OK for NaCl |
251 * syscalls, but here we do not want to trigger an exception while | 294 * syscalls, but here we do not want to trigger an exception while |
252 * in the exception handler. The overhead of using a Mach system | 295 * in the exception handler. The overhead of using a Mach system |
253 * call to write to memory is acceptable here. | 296 * call to write to memory is acceptable here. |
254 */ | 297 */ |
255 result = mach_vm_write(mach_task_self(), frame_addr_sys, | 298 result = mach_vm_write(mach_task_self(), frame_addr_sys, |
256 (uintptr_t) &frame, sizeof(frame)); | 299 (uintptr_t) &frame, sizeof(frame)); |
257 if (result != KERN_SUCCESS) { | 300 if (result != KERN_SUCCESS) { |
258 return 0; | 301 return 0; |
259 } | 302 } |
260 | 303 |
261 /* Set up thread context to resume at handler. */ | 304 /* Set up thread context to resume at handler. */ |
262 natp->user.new_prog_ctr = nap->exception_handler; | |
263 natp->user.stack_ptr = frame_addr_user; | |
264 /* TODO(bradnelson): put all registers in some default state. */ | 305 /* TODO(bradnelson): put all registers in some default state. */ |
265 | 306 #if NACL_BUILD_SUBARCH == 32 |
266 /* | 307 /* |
267 * Put registers in right place to land at NaClSwitchNoSSEViaECX | 308 * Put registers in right place to land at NaClSwitchNoSSEViaECX |
268 * This is required because: | 309 * This is required because: |
269 * - For an unknown reason thread_set_state resets %cs to the default | 310 * - For an unknown reason thread_set_state resets %cs to the default |
270 * value, even when set to something else, in current XNU versions. | 311 * value, even when set to something else, in current XNU versions. |
271 * - An examination of the XNU sources indicates | 312 * - An examination of the XNU sources indicates |
272 * that setting the code which state the thread state resets | 313 * that setting the code which state the thread state resets |
273 * %cs, %ds, %es, %ss to their default values in some early versions. | 314 * %cs, %ds, %es, %ss to their default values in some early versions. |
274 * (For instance: xnu-792.6.22/osfmk/i386/pcb.c:616) | 315 * (For instance: xnu-792.6.22/osfmk/i386/pcb.c:616) |
275 * This precludes going directly to the untrusted handler. | 316 * This precludes going directly to the untrusted handler. |
276 * Instead we call a variant of NaClSwitchNoSSE which takes a pointer | 317 * Instead we call a variant of NaClSwitchNoSSE which takes a pointer |
277 * to the thread user context in %ecx. | 318 * to the thread user context in %ecx. |
278 */ | 319 */ |
279 regs.uts.ts32.__eip = (uint32_t) &NaClSwitchNoSSEViaECX; | 320 natp->user.new_prog_ctr = nap->exception_handler; |
321 natp->user.stack_ptr = frame_addr_user; | |
322 X86_REG_IP(regs) = (uint32_t) &NaClSwitchNoSSEViaECX; | |
280 regs.uts.ts32.__cs = trusted_cs; | 323 regs.uts.ts32.__cs = trusted_cs; |
281 regs.uts.ts32.__ecx = (uint32_t) &natp->user; | 324 regs.uts.ts32.__ecx = (uint32_t) &natp->user; |
282 regs.uts.ts32.__ds = trusted_ds; | 325 regs.uts.ts32.__ds = trusted_ds; |
283 regs.uts.ts32.__es = trusted_ds; /* just for good measure */ | 326 regs.uts.ts32.__es = trusted_ds; /* just for good measure */ |
284 regs.uts.ts32.__ss = trusted_ds; /* just for good measure */ | 327 regs.uts.ts32.__ss = trusted_ds; /* just for good measure */ |
285 regs.uts.ts32.__eflags &= ~NACL_X86_DIRECTION_FLAG; | 328 #elif NACL_BUILD_SUBARCH == 64 |
329 X86_REG_IP(regs) = NaClUserToSys(nap, nap->exception_handler); | |
330 X86_REG_SP(regs) = frame_addr_sys; | |
331 X86_REG_BP(regs) = nap->mem_start; | |
332 | |
333 /* Argument 1 */ | |
334 regs.uts.ts64.__rdi = frame_addr_user + | |
335 offsetof(struct NaClExceptionFrame, context); | |
336 #endif | |
337 X86_REG_FLAGS(regs) &= ~NACL_X86_DIRECTION_FLAG; | |
286 result = thread_set_state(thread_port, x86_THREAD_STATE, | 338 result = thread_set_state(thread_port, x86_THREAD_STATE, |
287 (void *) ®s, size); | 339 (thread_state_t) ®s, size); |
288 if (result != KERN_SUCCESS) { | 340 if (result != KERN_SUCCESS) { |
289 return 0; | 341 return 0; |
290 } | 342 } |
291 | 343 |
292 /* Return success, and resume the thread. */ | 344 /* Return success, and resume the thread. */ |
293 return 1; | 345 return 1; |
294 } | 346 } |
295 | 347 |
296 | 348 |
297 static kern_return_t ForwardException( | 349 static kern_return_t ForwardException( |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
563 failure: | 615 failure: |
564 if (data) { | 616 if (data) { |
565 if (MACH_PORT_NULL != data->exception_port) { | 617 if (MACH_PORT_NULL != data->exception_port) { |
566 mach_port_deallocate(current_task, data->exception_port); | 618 mach_port_deallocate(current_task, data->exception_port); |
567 } | 619 } |
568 free(data); | 620 free(data); |
569 } | 621 } |
570 return FALSE; | 622 return FALSE; |
571 } | 623 } |
572 | 624 |
573 #else /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 */ | 625 #endif /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 */ |
574 | |
575 int NaClInterceptMachExceptions(void) { | |
576 return FALSE; | |
577 } | |
578 | |
579 #endif /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 */ | |
OLD | NEW |