1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  *
4  * Copyright 2014 Mozilla Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include "wasm/WasmSignalHandlers.h"
20 
21 #include "mozilla/DebugOnly.h"
22 #include "mozilla/ThreadLocal.h"
23 
24 #include "threading/Thread.h"
25 #include "vm/JitActivation.h"  // js::jit::JitActivation
26 #include "vm/Realm.h"
27 #include "vm/Runtime.h"
28 #include "wasm/WasmInstance.h"
29 
30 #if defined(XP_WIN)
31 #  include <winternl.h>  // must include before util/Windows.h's `#undef`s
32 #  include "util/Windows.h"
33 #elif defined(XP_DARWIN)
34 #  include <mach/exc.h>
35 #  include <mach/mach.h>
36 #else
37 #  include <signal.h>
38 #endif
39 
40 using namespace js;
41 using namespace js::wasm;
42 
43 using mozilla::DebugOnly;
44 
45 // =============================================================================
46 // This following pile of macros and includes defines the ToRegisterState() and
47 // the ContextTo{PC,FP,SP,LR}() functions from the (highly) platform-specific
48 // CONTEXT struct which is provided to the signal handler.
49 // =============================================================================
50 
51 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
52 #  include <sys/ucontext.h>  // for ucontext_t, mcontext_t
53 #endif
54 
55 #if defined(__x86_64__)
56 #  if defined(__DragonFly__)
57 #    include <machine/npx.h>  // for union savefpu
58 #  elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
59       defined(__NetBSD__) || defined(__OpenBSD__)
60 #    include <machine/fpu.h>  // for struct savefpu/fxsave64
61 #  endif
62 #endif
63 
64 #if defined(XP_WIN)
65 #  define EIP_sig(p) ((p)->Eip)
66 #  define EBP_sig(p) ((p)->Ebp)
67 #  define ESP_sig(p) ((p)->Esp)
68 #  define RIP_sig(p) ((p)->Rip)
69 #  define RSP_sig(p) ((p)->Rsp)
70 #  define RBP_sig(p) ((p)->Rbp)
71 #  define R11_sig(p) ((p)->R11)
72 #  define R13_sig(p) ((p)->R13)
73 #  define R14_sig(p) ((p)->R14)
74 #  define R15_sig(p) ((p)->R15)
75 #  define EPC_sig(p) ((p)->Pc)
76 #  define RFP_sig(p) ((p)->Fp)
77 #  define R31_sig(p) ((p)->Sp)
78 #  define RLR_sig(p) ((p)->Lr)
79 #elif defined(__OpenBSD__)
80 #  define EIP_sig(p) ((p)->sc_eip)
81 #  define EBP_sig(p) ((p)->sc_ebp)
82 #  define ESP_sig(p) ((p)->sc_esp)
83 #  define RIP_sig(p) ((p)->sc_rip)
84 #  define RSP_sig(p) ((p)->sc_rsp)
85 #  define RBP_sig(p) ((p)->sc_rbp)
86 #  define R11_sig(p) ((p)->sc_r11)
87 #  if defined(__arm__)
88 #    define R13_sig(p) ((p)->sc_usr_sp)
89 #    define R14_sig(p) ((p)->sc_usr_lr)
90 #    define R15_sig(p) ((p)->sc_pc)
91 #  else
92 #    define R13_sig(p) ((p)->sc_r13)
93 #    define R14_sig(p) ((p)->sc_r14)
94 #    define R15_sig(p) ((p)->sc_r15)
95 #  endif
96 #  if defined(__aarch64__)
97 #    define EPC_sig(p) ((p)->sc_elr)
98 #    define RFP_sig(p) ((p)->sc_x[29])
99 #    define RLR_sig(p) ((p)->sc_lr)
100 #    define R31_sig(p) ((p)->sc_sp)
101 #  endif
102 #  if defined(__mips__)
103 #    define EPC_sig(p) ((p)->sc_pc)
104 #    define RFP_sig(p) ((p)->sc_regs[30])
105 #  endif
106 #  if defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \
107       defined(__PPC64LE__)
108 #    define R01_sig(p) ((p)->sc_frame.fixreg[1])
109 #    define R32_sig(p) ((p)->sc_frame.srr0)
110 #  endif
111 #elif defined(__linux__) || defined(__sun)
112 #  if defined(__linux__)
113 #    define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_EIP])
114 #    define EBP_sig(p) ((p)->uc_mcontext.gregs[REG_EBP])
115 #    define ESP_sig(p) ((p)->uc_mcontext.gregs[REG_ESP])
116 #  else
117 #    define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_PC])
118 #    define EBP_sig(p) ((p)->uc_mcontext.gregs[REG_EBP])
119 #    define ESP_sig(p) ((p)->uc_mcontext.gregs[REG_ESP])
120 #  endif
121 #  define RIP_sig(p) ((p)->uc_mcontext.gregs[REG_RIP])
122 #  define RSP_sig(p) ((p)->uc_mcontext.gregs[REG_RSP])
123 #  define RBP_sig(p) ((p)->uc_mcontext.gregs[REG_RBP])
124 #  if defined(__linux__) && defined(__arm__)
125 #    define R11_sig(p) ((p)->uc_mcontext.arm_fp)
126 #    define R13_sig(p) ((p)->uc_mcontext.arm_sp)
127 #    define R14_sig(p) ((p)->uc_mcontext.arm_lr)
128 #    define R15_sig(p) ((p)->uc_mcontext.arm_pc)
129 #  else
130 #    define R11_sig(p) ((p)->uc_mcontext.gregs[REG_R11])
131 #    define R13_sig(p) ((p)->uc_mcontext.gregs[REG_R13])
132 #    define R14_sig(p) ((p)->uc_mcontext.gregs[REG_R14])
133 #    define R15_sig(p) ((p)->uc_mcontext.gregs[REG_R15])
134 #  endif
135 #  if defined(__linux__) && defined(__aarch64__)
136 #    define EPC_sig(p) ((p)->uc_mcontext.pc)
137 #    define RFP_sig(p) ((p)->uc_mcontext.regs[29])
138 #    define RLR_sig(p) ((p)->uc_mcontext.regs[30])
139 #    define R31_sig(p) ((p)->uc_mcontext.sp)
140 #  endif
141 #  if defined(__linux__) && defined(__mips__)
142 #    define EPC_sig(p) ((p)->uc_mcontext.pc)
143 #    define RFP_sig(p) ((p)->uc_mcontext.gregs[30])
144 #    define RSP_sig(p) ((p)->uc_mcontext.gregs[29])
145 #    define R31_sig(p) ((p)->uc_mcontext.gregs[31])
146 #  endif
147 #  if defined(__linux__) && (defined(__sparc__) && defined(__arch64__))
148 #    define PC_sig(p) ((p)->uc_mcontext.mc_gregs[MC_PC])
149 #    define FP_sig(p) ((p)->uc_mcontext.mc_fp)
150 #    define SP_sig(p) ((p)->uc_mcontext.mc_i7)
151 #  endif
152 #  if defined(__linux__) && (defined(__ppc64__) || defined(__PPC64__) || \
153                              defined(__ppc64le__) || defined(__PPC64LE__))
154 #    define R01_sig(p) ((p)->uc_mcontext.gp_regs[1])
155 #    define R32_sig(p) ((p)->uc_mcontext.gp_regs[32])
156 #  endif
157 #elif defined(__NetBSD__)
158 #  define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
159 #  define EBP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EBP])
160 #  define ESP_sig(p) ((p)->uc_mcontext.__gregs[_REG_ESP])
161 #  define RIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_RIP])
162 #  define RSP_sig(p) ((p)->uc_mcontext.__gregs[_REG_RSP])
163 #  define RBP_sig(p) ((p)->uc_mcontext.__gregs[_REG_RBP])
164 #  define R11_sig(p) ((p)->uc_mcontext.__gregs[_REG_R11])
165 #  define R13_sig(p) ((p)->uc_mcontext.__gregs[_REG_R13])
166 #  define R14_sig(p) ((p)->uc_mcontext.__gregs[_REG_R14])
167 #  define R15_sig(p) ((p)->uc_mcontext.__gregs[_REG_R15])
168 #  if defined(__aarch64__)
169 #    define EPC_sig(p) ((p)->uc_mcontext.__gregs[_REG_PC])
170 #    define RFP_sig(p) ((p)->uc_mcontext.__gregs[_REG_X29])
171 #    define RLR_sig(p) ((p)->uc_mcontext.__gregs[_REG_X30])
172 #    define R31_sig(p) ((p)->uc_mcontext.__gregs[_REG_SP])
173 #  endif
174 #  if defined(__mips__)
175 #    define EPC_sig(p) ((p)->uc_mcontext.__gregs[_REG_EPC])
176 #    define RFP_sig(p) ((p)->uc_mcontext.__gregs[_REG_S8])
177 #  endif
178 #  if defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \
179       defined(__PPC64LE__)
180 #    define R01_sig(p) ((p)->uc_mcontext.__gregs[_REG_R1])
181 #    define R32_sig(p) ((p)->uc_mcontext.__gregs[_REG_PC])
182 #  endif
183 #elif defined(__DragonFly__) || defined(__FreeBSD__) || \
184     defined(__FreeBSD_kernel__)
185 #  define EIP_sig(p) ((p)->uc_mcontext.mc_eip)
186 #  define EBP_sig(p) ((p)->uc_mcontext.mc_ebp)
187 #  define ESP_sig(p) ((p)->uc_mcontext.mc_esp)
188 #  define RIP_sig(p) ((p)->uc_mcontext.mc_rip)
189 #  define RSP_sig(p) ((p)->uc_mcontext.mc_rsp)
190 #  define RBP_sig(p) ((p)->uc_mcontext.mc_rbp)
191 #  if defined(__FreeBSD__) && defined(__arm__)
192 #    define R11_sig(p) ((p)->uc_mcontext.__gregs[_REG_R11])
193 #    define R13_sig(p) ((p)->uc_mcontext.__gregs[_REG_R13])
194 #    define R14_sig(p) ((p)->uc_mcontext.__gregs[_REG_R14])
195 #    define R15_sig(p) ((p)->uc_mcontext.__gregs[_REG_R15])
196 #  else
197 #    define R11_sig(p) ((p)->uc_mcontext.mc_r11)
198 #    define R13_sig(p) ((p)->uc_mcontext.mc_r13)
199 #    define R14_sig(p) ((p)->uc_mcontext.mc_r14)
200 #    define R15_sig(p) ((p)->uc_mcontext.mc_r15)
201 #  endif
202 #  if defined(__FreeBSD__) && defined(__aarch64__)
203 #    define EPC_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_elr)
204 #    define RFP_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_x[29])
205 #    define RLR_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_lr)
206 #    define R31_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_sp)
207 #  endif
208 #  if defined(__FreeBSD__) && defined(__mips__)
209 #    define EPC_sig(p) ((p)->uc_mcontext.mc_pc)
210 #    define RFP_sig(p) ((p)->uc_mcontext.mc_regs[30])
211 #  endif
212 #  if defined(__FreeBSD__) && (defined(__ppc64__) || defined(__PPC64__) || \
213                                defined(__ppc64le__) || defined(__PPC64LE__))
214 #    define R01_sig(p) ((p)->uc_mcontext.mc_gpr[1])
215 #    define R32_sig(p) ((p)->uc_mcontext.mc_srr0)
216 #  endif
217 #elif defined(XP_DARWIN)
218 #  define EIP_sig(p) ((p)->thread.uts.ts32.__eip)
219 #  define EBP_sig(p) ((p)->thread.uts.ts32.__ebp)
220 #  define ESP_sig(p) ((p)->thread.uts.ts32.__esp)
221 #  define RIP_sig(p) ((p)->thread.__rip)
222 #  define RBP_sig(p) ((p)->thread.__rbp)
223 #  define RSP_sig(p) ((p)->thread.__rsp)
224 #  define R11_sig(p) ((p)->thread.__r[11])
225 #  define R13_sig(p) ((p)->thread.__sp)
226 #  define R14_sig(p) ((p)->thread.__lr)
227 #  define R15_sig(p) ((p)->thread.__pc)
228 #  define EPC_sig(p) ((p)->thread.__pc)
229 #  define RFP_sig(p) ((p)->thread.__fp)
230 #  define R31_sig(p) ((p)->thread.__sp)
231 #  define RLR_sig(p) ((p)->thread.__lr)
232 #else
233 #  error "Don't know how to read/write to the thread state via the mcontext_t."
234 #endif
235 
236 #if defined(ANDROID)
237 // Not all versions of the Android NDK define ucontext_t or mcontext_t.
238 // Detect this and provide custom but compatible definitions. Note that these
239 // follow the GLibc naming convention to access register values from
240 // mcontext_t.
241 //
242 // See: https://chromiumcodereview.appspot.com/10829122/
243 // See: http://code.google.com/p/android/issues/detail?id=34784
244 #  if !defined(__BIONIC_HAVE_UCONTEXT_T)
245 #    if defined(__arm__)
246 
247 // GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
248 // Old versions of the C library <signal.h> didn't define the type.
249 #      if !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
250 #        include <asm/sigcontext.h>
251 #      endif
252 
253 typedef struct sigcontext mcontext_t;
254 
255 typedef struct ucontext {
256   uint32_t uc_flags;
257   struct ucontext* uc_link;
258   stack_t uc_stack;
259   mcontext_t uc_mcontext;
260   // Other fields are not used so don't define them here.
261 } ucontext_t;
262 
263 #    elif defined(__mips__)
264 
265 typedef struct {
266   uint32_t regmask;
267   uint32_t status;
268   uint64_t pc;
269   uint64_t gregs[32];
270   uint64_t fpregs[32];
271   uint32_t acx;
272   uint32_t fpc_csr;
273   uint32_t fpc_eir;
274   uint32_t used_math;
275   uint32_t dsp;
276   uint64_t mdhi;
277   uint64_t mdlo;
278   uint32_t hi1;
279   uint32_t lo1;
280   uint32_t hi2;
281   uint32_t lo2;
282   uint32_t hi3;
283   uint32_t lo3;
284 } mcontext_t;
285 
286 typedef struct ucontext {
287   uint32_t uc_flags;
288   struct ucontext* uc_link;
289   stack_t uc_stack;
290   mcontext_t uc_mcontext;
291   // Other fields are not used so don't define them here.
292 } ucontext_t;
293 
294 #    elif defined(__i386__)
295 // x86 version for Android.
296 typedef struct {
297   uint32_t gregs[19];
298   void* fpregs;
299   uint32_t oldmask;
300   uint32_t cr2;
301 } mcontext_t;
302 
303 typedef uint32_t kernel_sigset_t[2];  // x86 kernel uses 64-bit signal masks
304 typedef struct ucontext {
305   uint32_t uc_flags;
306   struct ucontext* uc_link;
307   stack_t uc_stack;
308   mcontext_t uc_mcontext;
309   // Other fields are not used by V8, don't define them here.
310 } ucontext_t;
311 enum { REG_EIP = 14 };
312 #    endif  // defined(__i386__)
313 #  endif    // !defined(__BIONIC_HAVE_UCONTEXT_T)
314 #endif      // defined(ANDROID)
315 
316 #if defined(XP_DARWIN)
317 #  if defined(__x86_64__)
318 struct macos_x64_context {
319   x86_thread_state64_t thread;
320   x86_float_state64_t float_;
321 };
322 #    define CONTEXT macos_x64_context
323 #  elif defined(__i386__)
324 struct macos_x86_context {
325   x86_thread_state_t thread;
326   x86_float_state_t float_;
327 };
328 #    define CONTEXT macos_x86_context
329 #  elif defined(__arm__)
330 struct macos_arm_context {
331   arm_thread_state_t thread;
332   arm_neon_state_t float_;
333 };
334 #    define CONTEXT macos_arm_context
335 #  elif defined(__aarch64__)
336 struct macos_aarch64_context {
337   arm_thread_state64_t thread;
338   arm_neon_state64_t float_;
339 };
340 #    define CONTEXT macos_aarch64_context
341 #  else
342 #    error Unsupported architecture
343 #  endif
344 #elif !defined(XP_WIN)
345 #  define CONTEXT ucontext_t
346 #endif
347 
348 #if defined(_M_X64) || defined(__x86_64__)
349 #  define PC_sig(p) RIP_sig(p)
350 #  define FP_sig(p) RBP_sig(p)
351 #  define SP_sig(p) RSP_sig(p)
352 #elif defined(_M_IX86) || defined(__i386__)
353 #  define PC_sig(p) EIP_sig(p)
354 #  define FP_sig(p) EBP_sig(p)
355 #  define SP_sig(p) ESP_sig(p)
356 #elif defined(__arm__)
357 #  define FP_sig(p) R11_sig(p)
358 #  define SP_sig(p) R13_sig(p)
359 #  define LR_sig(p) R14_sig(p)
360 #  define PC_sig(p) R15_sig(p)
361 #elif defined(_M_ARM64) || defined(__aarch64__)
362 #  define PC_sig(p) EPC_sig(p)
363 #  define FP_sig(p) RFP_sig(p)
364 #  define SP_sig(p) R31_sig(p)
365 #  define LR_sig(p) RLR_sig(p)
366 #elif defined(__mips__)
367 #  define PC_sig(p) EPC_sig(p)
368 #  define FP_sig(p) RFP_sig(p)
369 #  define SP_sig(p) RSP_sig(p)
370 #  define LR_sig(p) R31_sig(p)
371 #elif defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \
372     defined(__PPC64LE__)
373 #  define PC_sig(p) R32_sig(p)
374 #  define SP_sig(p) R01_sig(p)
375 #  define FP_sig(p) R01_sig(p)
376 #endif
377 
SetContextPC(CONTEXT * context,uint8_t * pc)378 static void SetContextPC(CONTEXT* context, uint8_t* pc) {
379 #ifdef PC_sig
380   *reinterpret_cast<uint8_t**>(&PC_sig(context)) = pc;
381 #else
382   MOZ_CRASH();
383 #endif
384 }
385 
ContextToPC(CONTEXT * context)386 static uint8_t* ContextToPC(CONTEXT* context) {
387 #ifdef PC_sig
388   return reinterpret_cast<uint8_t*>(PC_sig(context));
389 #else
390   MOZ_CRASH();
391 #endif
392 }
393 
ContextToFP(CONTEXT * context)394 static uint8_t* ContextToFP(CONTEXT* context) {
395 #ifdef FP_sig
396   return reinterpret_cast<uint8_t*>(FP_sig(context));
397 #else
398   MOZ_CRASH();
399 #endif
400 }
401 
ContextToSP(CONTEXT * context)402 static uint8_t* ContextToSP(CONTEXT* context) {
403 #ifdef SP_sig
404   return reinterpret_cast<uint8_t*>(SP_sig(context));
405 #else
406   MOZ_CRASH();
407 #endif
408 }
409 
410 #if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
ContextToLR(CONTEXT * context)411 static uint8_t* ContextToLR(CONTEXT* context) {
412 #  ifdef LR_sig
413   return reinterpret_cast<uint8_t*>(LR_sig(context));
414 #  else
415   MOZ_CRASH();
416 #  endif
417 }
418 #endif
419 
ToRegisterState(CONTEXT * context)420 static JS::ProfilingFrameIterator::RegisterState ToRegisterState(
421     CONTEXT* context) {
422   JS::ProfilingFrameIterator::RegisterState state;
423   state.fp = ContextToFP(context);
424   state.pc = ContextToPC(context);
425   state.sp = ContextToSP(context);
426 #if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
427   state.lr = ContextToLR(context);
428 #else
429   state.lr = (void*)UINTPTR_MAX;
430 #endif
431   return state;
432 }
433 
434 // =============================================================================
435 // All signals/exceptions funnel down to this one trap-handling function which
436 // tests whether the pc is in a wasm module and, if so, whether there is
437 // actually a trap expected at this pc. These tests both avoid real bugs being
438 // silently converted to wasm traps and provides the trapping wasm bytecode
439 // offset we need to report in the error.
440 //
441 // Crashing inside wasm trap handling (due to a bug in trap handling or exposed
442 // during trap handling) must be reported like a normal crash, not cause the
443 // crash report to be lost. On Windows and non-Mach Unix, a crash during the
444 // handler reenters the handler, possibly repeatedly until exhausting the stack,
445 // and so we prevent recursion with the thread-local sAlreadyHandlingTrap. On
446 // Mach, the wasm exception handler has its own thread and is installed only on
447 // the thread-level debugging ports of JSRuntime threads, so a crash on
448 // exception handler thread will not recurse; it will bubble up to the
449 // process-level debugging ports (where Breakpad is installed).
450 // =============================================================================
451 
452 static MOZ_THREAD_LOCAL(bool) sAlreadyHandlingTrap;
453 
454 struct AutoHandlingTrap {
AutoHandlingTrapAutoHandlingTrap455   AutoHandlingTrap() {
456     MOZ_ASSERT(!sAlreadyHandlingTrap.get());
457     sAlreadyHandlingTrap.set(true);
458   }
459 
~AutoHandlingTrapAutoHandlingTrap460   ~AutoHandlingTrap() {
461     MOZ_ASSERT(sAlreadyHandlingTrap.get());
462     sAlreadyHandlingTrap.set(false);
463   }
464 };
465 
HandleTrap(CONTEXT * context,JSContext * assertCx=nullptr)466 [[nodiscard]] static bool HandleTrap(CONTEXT* context,
467                                      JSContext* assertCx = nullptr) {
468   MOZ_ASSERT(sAlreadyHandlingTrap.get());
469 
470   uint8_t* pc = ContextToPC(context);
471   const CodeSegment* codeSegment = LookupCodeSegment(pc);
472   if (!codeSegment || !codeSegment->isModule()) {
473     return false;
474   }
475 
476   const ModuleSegment& segment = *codeSegment->asModule();
477 
478   Trap trap;
479   BytecodeOffset bytecode;
480   if (!segment.code().lookupTrap(pc, &trap, &bytecode)) {
481     return false;
482   }
483 
484   // We have a safe, expected wasm trap, so fp is well-defined to be a Frame*.
485   // For the first sanity check, the Trap::IndirectCallBadSig special case is
486   // due to this trap occurring in the indirect call prologue, while fp points
487   // to the caller's Frame which can be in a different Module. In any case,
488   // though, the containing JSContext is the same.
489 
490   auto* frame = reinterpret_cast<Frame*>(ContextToFP(context));
491   Instance* instance = GetNearestEffectiveTls(frame)->instance;
492   MOZ_RELEASE_ASSERT(&instance->code() == &segment.code() ||
493                      trap == Trap::IndirectCallBadSig);
494 
495   JSContext* cx =
496       instance->realm()->runtimeFromAnyThread()->mainContextFromAnyThread();
497   MOZ_RELEASE_ASSERT(!assertCx || cx == assertCx);
498 
499   // JitActivation::startWasmTrap() stores enough register state from the
500   // point of the trap to allow stack unwinding or resumption, both of which
501   // will call finishWasmTrap().
502   jit::JitActivation* activation = cx->activation()->asJit();
503   activation->startWasmTrap(trap, bytecode.offset(), ToRegisterState(context));
504   SetContextPC(context, segment.trapCode());
505   return true;
506 }
507 
508 // =============================================================================
509 // The following platform-specific handlers funnel all signals/exceptions into
510 // the shared HandleTrap() above.
511 // =============================================================================
512 
513 #if defined(XP_WIN)
514 // Obtained empirically from thread_local codegen on x86/x64/arm64.
515 // Compiled in all user binaries, so should be stable over time.
516 static const unsigned sThreadLocalArrayPointerIndex = 11;
517 
WasmTrapHandler(LPEXCEPTION_POINTERS exception)518 static LONG WINAPI WasmTrapHandler(LPEXCEPTION_POINTERS exception) {
519   // Make sure TLS is initialized before reading sAlreadyHandlingTrap.
520   if (!NtCurrentTeb()->Reserved1[sThreadLocalArrayPointerIndex]) {
521     return EXCEPTION_CONTINUE_SEARCH;
522   }
523 
524   if (sAlreadyHandlingTrap.get()) {
525     return EXCEPTION_CONTINUE_SEARCH;
526   }
527   AutoHandlingTrap aht;
528 
529   EXCEPTION_RECORD* record = exception->ExceptionRecord;
530   if (record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION &&
531       record->ExceptionCode != EXCEPTION_ILLEGAL_INSTRUCTION) {
532     return EXCEPTION_CONTINUE_SEARCH;
533   }
534 
535   if (!HandleTrap(exception->ContextRecord, TlsContext.get())) {
536     return EXCEPTION_CONTINUE_SEARCH;
537   }
538 
539   return EXCEPTION_CONTINUE_EXECUTION;
540 }
541 
542 #elif defined(XP_DARWIN)
543 // On OSX we are forced to use the lower-level Mach exception mechanism instead
544 // of Unix signals because breakpad uses Mach exceptions and would otherwise
545 // report a crash before wasm gets a chance to handle the exception.
546 
547 // This definition was generated by mig (the Mach Interface Generator) for the
548 // routine 'exception_raise' (exc.defs).
549 #  pragma pack(4)
550 typedef struct {
551   mach_msg_header_t Head;
552   /* start of the kernel processed data */
553   mach_msg_body_t msgh_body;
554   mach_msg_port_descriptor_t thread;
555   mach_msg_port_descriptor_t task;
556   /* end of the kernel processed data */
557   NDR_record_t NDR;
558   exception_type_t exception;
559   mach_msg_type_number_t codeCnt;
560   int64_t code[2];
561 } Request__mach_exception_raise_t;
562 #  pragma pack()
563 
564 // The full Mach message also includes a trailer.
565 struct ExceptionRequest {
566   Request__mach_exception_raise_t body;
567   mach_msg_trailer_t trailer;
568 };
569 
HandleMachException(const ExceptionRequest & request)570 static bool HandleMachException(const ExceptionRequest& request) {
571   // Get the port of the JSContext's thread from the message.
572   mach_port_t cxThread = request.body.thread.name;
573 
574   // Read out the JSRuntime thread's register state.
575   CONTEXT context;
576 #  if defined(__x86_64__)
577   unsigned int thread_state_count = x86_THREAD_STATE64_COUNT;
578   unsigned int float_state_count = x86_FLOAT_STATE64_COUNT;
579   int thread_state = x86_THREAD_STATE64;
580   int float_state = x86_FLOAT_STATE64;
581 #  elif defined(__i386__)
582   unsigned int thread_state_count = x86_THREAD_STATE_COUNT;
583   unsigned int float_state_count = x86_FLOAT_STATE_COUNT;
584   int thread_state = x86_THREAD_STATE;
585   int float_state = x86_FLOAT_STATE;
586 #  elif defined(__arm__)
587   unsigned int thread_state_count = ARM_THREAD_STATE_COUNT;
588   unsigned int float_state_count = ARM_NEON_STATE_COUNT;
589   int thread_state = ARM_THREAD_STATE;
590   int float_state = ARM_NEON_STATE;
591 #  elif defined(__aarch64__)
592   unsigned int thread_state_count = ARM_THREAD_STATE64_COUNT;
593   unsigned int float_state_count = ARM_NEON_STATE64_COUNT;
594   int thread_state = ARM_THREAD_STATE64;
595   int float_state = ARM_NEON_STATE64;
596 #  else
597 #    error Unsupported architecture
598 #  endif
599   kern_return_t kret;
600   kret = thread_get_state(cxThread, thread_state,
601                           (thread_state_t)&context.thread, &thread_state_count);
602   if (kret != KERN_SUCCESS) {
603     return false;
604   }
605   kret = thread_get_state(cxThread, float_state,
606                           (thread_state_t)&context.float_, &float_state_count);
607   if (kret != KERN_SUCCESS) {
608     return false;
609   }
610 
611   if (request.body.exception != EXC_BAD_ACCESS &&
612       request.body.exception != EXC_BAD_INSTRUCTION) {
613     return false;
614   }
615 
616   {
617     AutoNoteSingleThreadedRegion anstr;
618     AutoHandlingTrap aht;
619     if (!HandleTrap(&context)) {
620       return false;
621     }
622   }
623 
624   // Update the thread state with the new pc and register values.
625   kret = thread_set_state(cxThread, float_state,
626                           (thread_state_t)&context.float_, float_state_count);
627   if (kret != KERN_SUCCESS) {
628     return false;
629   }
630   kret = thread_set_state(cxThread, thread_state,
631                           (thread_state_t)&context.thread, thread_state_count);
632   if (kret != KERN_SUCCESS) {
633     return false;
634   }
635 
636   return true;
637 }
638 
639 static mach_port_t sMachDebugPort = MACH_PORT_NULL;
640 
MachExceptionHandlerThread()641 static void MachExceptionHandlerThread() {
642   ThisThread::SetName("JS Wasm MachExceptionHandler");
643 
644   // Taken from mach_exc in /usr/include/mach/mach_exc.defs.
645   static const unsigned EXCEPTION_MSG_ID = 2405;
646 
647   while (true) {
648     ExceptionRequest request;
649     kern_return_t kret =
650         mach_msg(&request.body.Head, MACH_RCV_MSG, 0, sizeof(request),
651                  sMachDebugPort, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
652 
653     // If we fail even receiving the message, we can't even send a reply!
654     // Rather than hanging the faulting thread (hanging the browser), crash.
655     if (kret != KERN_SUCCESS) {
656       fprintf(stderr, "MachExceptionHandlerThread: mach_msg failed with %d\n",
657               (int)kret);
658       MOZ_CRASH();
659     }
660 
661     if (request.body.Head.msgh_id != EXCEPTION_MSG_ID) {
662       fprintf(stderr, "Unexpected msg header id %d\n",
663               (int)request.body.Head.msgh_bits);
664       MOZ_CRASH();
665     }
666 
667     // Some thread just commited an EXC_BAD_ACCESS and has been suspended by
668     // the kernel. The kernel is waiting for us to reply with instructions.
669     // Our default is the "not handled" reply (by setting the RetCode field
670     // of the reply to KERN_FAILURE) which tells the kernel to continue
671     // searching at the process and system level. If this is an asm.js
672     // expected exception, we handle it and return KERN_SUCCESS.
673     bool handled = HandleMachException(request);
674     kern_return_t replyCode = handled ? KERN_SUCCESS : KERN_FAILURE;
675 
676     // This magic incantation to send a reply back to the kernel was
677     // derived from the exc_server generated by
678     // 'mig -v /usr/include/mach/mach_exc.defs'.
679     __Reply__exception_raise_t reply;
680     reply.Head.msgh_bits =
681         MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.body.Head.msgh_bits), 0);
682     reply.Head.msgh_size = sizeof(reply);
683     reply.Head.msgh_remote_port = request.body.Head.msgh_remote_port;
684     reply.Head.msgh_local_port = MACH_PORT_NULL;
685     reply.Head.msgh_id = request.body.Head.msgh_id + 100;
686     reply.NDR = NDR_record;
687     reply.RetCode = replyCode;
688     mach_msg(&reply.Head, MACH_SEND_MSG, sizeof(reply), 0, MACH_PORT_NULL,
689              MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
690   }
691 }
692 
693 #else  // If not Windows or Mac, assume Unix
694 
695 #  ifdef __mips__
696 static const uint32_t kWasmTrapSignal = SIGFPE;
697 #  else
698 static const uint32_t kWasmTrapSignal = SIGILL;
699 #  endif
700 
701 static struct sigaction sPrevSEGVHandler;
702 static struct sigaction sPrevSIGBUSHandler;
703 static struct sigaction sPrevWasmTrapHandler;
704 
WasmTrapHandler(int signum,siginfo_t * info,void * context)705 static void WasmTrapHandler(int signum, siginfo_t* info, void* context) {
706   if (!sAlreadyHandlingTrap.get()) {
707     AutoHandlingTrap aht;
708     MOZ_RELEASE_ASSERT(signum == SIGSEGV || signum == SIGBUS ||
709                        signum == kWasmTrapSignal);
710     if (HandleTrap((CONTEXT*)context, TlsContext.get())) {
711       return;
712     }
713   }
714 
715   struct sigaction* previousSignal = nullptr;
716   switch (signum) {
717     case SIGSEGV:
718       previousSignal = &sPrevSEGVHandler;
719       break;
720     case SIGBUS:
721       previousSignal = &sPrevSIGBUSHandler;
722       break;
723     case kWasmTrapSignal:
724       previousSignal = &sPrevWasmTrapHandler;
725       break;
726   }
727   MOZ_ASSERT(previousSignal);
728 
729   // This signal is not for any asm.js code we expect, so we need to forward
730   // the signal to the next handler. If there is no next handler (SIG_IGN or
731   // SIG_DFL), then it's time to crash. To do this, we set the signal back to
732   // its original disposition and return. This will cause the faulting op to
733   // be re-executed which will crash in the normal way. The advantage of
734   // doing this to calling _exit() is that we remove ourselves from the crash
735   // stack which improves crash reports. If there is a next handler, call it.
736   // It will either crash synchronously, fix up the instruction so that
737   // execution can continue and return, or trigger a crash by returning the
738   // signal to it's original disposition and returning.
739   //
740   // Note: the order of these tests matter.
741   if (previousSignal->sa_flags & SA_SIGINFO) {
742     previousSignal->sa_sigaction(signum, info, context);
743   } else if (previousSignal->sa_handler == SIG_DFL ||
744              previousSignal->sa_handler == SIG_IGN) {
745     sigaction(signum, previousSignal, nullptr);
746   } else {
747     previousSignal->sa_handler(signum);
748   }
749 }
750 #endif  // XP_WIN || XP_DARWIN || assume unix
751 
752 #if defined(ANDROID) && defined(MOZ_LINKER)
753 extern "C" MFBT_API bool IsSignalHandlingBroken();
754 #endif
755 
756 struct InstallState {
757   bool tried;
758   bool success;
InstallStateInstallState759   InstallState() : tried(false), success(false) {}
760 };
761 
762 static ExclusiveData<InstallState> sEagerInstallState(
763     mutexid::WasmSignalInstallState);
764 
EnsureEagerProcessSignalHandlers()765 void wasm::EnsureEagerProcessSignalHandlers() {
766   auto eagerInstallState = sEagerInstallState.lock();
767   if (eagerInstallState->tried) {
768     return;
769   }
770 
771   eagerInstallState->tried = true;
772   MOZ_RELEASE_ASSERT(eagerInstallState->success == false);
773 
774 #if defined(JS_CODEGEN_NONE)
775   // If there is no JIT, then there should be no Wasm signal handlers.
776   return;
777 #endif
778 
779 #if defined(ANDROID) && defined(MOZ_LINKER)
780   // Signal handling is broken on some android systems.
781   if (IsSignalHandlingBroken()) {
782     return;
783   }
784 #endif
785 
786   sAlreadyHandlingTrap.infallibleInit();
787 
788   // Install whatever exception/signal handler is appropriate for the OS.
789 #if defined(XP_WIN)
790 
791 #  if defined(MOZ_ASAN)
792   // Under ASan we need to let the ASan runtime's ShadowExceptionHandler stay
793   // in the first handler position. This requires some coordination with
794   // MemoryProtectionExceptionHandler::isDisabled().
795   const bool firstHandler = false;
796 #  else
797   // Otherwise, WasmTrapHandler needs to go first, so that we can recover
798   // from wasm faults and continue execution without triggering handlers
799   // such as MemoryProtectionExceptionHandler that assume we are crashing.
800   const bool firstHandler = true;
801 #  endif
802   if (!AddVectoredExceptionHandler(firstHandler, WasmTrapHandler)) {
803     // Windows has all sorts of random security knobs for disabling things
804     // so make this a dynamic failure that disables wasm, not a MOZ_CRASH().
805     return;
806   }
807 
808 #elif defined(XP_DARWIN)
809   // All the Mach setup in EnsureLazyProcessSignalHandlers.
810 #else
811   // SA_NODEFER allows us to reenter the signal handler if we crash while
812   // handling the signal, and fall through to the Breakpad handler by testing
813   // handlingSegFault.
814 
815   // Allow handling OOB with signals on all architectures
816   struct sigaction faultHandler;
817   faultHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
818   faultHandler.sa_sigaction = WasmTrapHandler;
819   sigemptyset(&faultHandler.sa_mask);
820   if (sigaction(SIGSEGV, &faultHandler, &sPrevSEGVHandler)) {
821     MOZ_CRASH("unable to install segv handler");
822   }
823 
824 #  if defined(JS_CODEGEN_ARM)
825   // On Arm Handle Unaligned Accesses
826   struct sigaction busHandler;
827   busHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
828   busHandler.sa_sigaction = WasmTrapHandler;
829   sigemptyset(&busHandler.sa_mask);
830   if (sigaction(SIGBUS, &busHandler, &sPrevSIGBUSHandler)) {
831     MOZ_CRASH("unable to install sigbus handler");
832   }
833 #  endif
834 
835   // Install a handler to handle the instructions that are emitted to implement
836   // wasm traps.
837   struct sigaction wasmTrapHandler;
838   wasmTrapHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
839   wasmTrapHandler.sa_sigaction = WasmTrapHandler;
840   sigemptyset(&wasmTrapHandler.sa_mask);
841   if (sigaction(kWasmTrapSignal, &wasmTrapHandler, &sPrevWasmTrapHandler)) {
842     MOZ_CRASH("unable to install wasm trap handler");
843   }
844 #endif
845 
846   eagerInstallState->success = true;
847 }
848 
849 static ExclusiveData<InstallState> sLazyInstallState(
850     mutexid::WasmSignalInstallState);
851 
EnsureLazyProcessSignalHandlers()852 static bool EnsureLazyProcessSignalHandlers() {
853   auto lazyInstallState = sLazyInstallState.lock();
854   if (lazyInstallState->tried) {
855     return lazyInstallState->success;
856   }
857 
858   lazyInstallState->tried = true;
859   MOZ_RELEASE_ASSERT(lazyInstallState->success == false);
860 
861 #ifdef XP_DARWIN
862   // Create the port that all JSContext threads will redirect their traps to.
863   kern_return_t kret;
864   kret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
865                             &sMachDebugPort);
866   if (kret != KERN_SUCCESS) {
867     return false;
868   }
869   kret = mach_port_insert_right(mach_task_self(), sMachDebugPort,
870                                 sMachDebugPort, MACH_MSG_TYPE_MAKE_SEND);
871   if (kret != KERN_SUCCESS) {
872     return false;
873   }
874 
875   // Create the thread that will wait on and service sMachDebugPort.
876   // It's not useful to destroy this thread on process shutdown so
877   // immediately detach on successful start.
878   Thread handlerThread;
879   if (!handlerThread.init(MachExceptionHandlerThread)) {
880     return false;
881   }
882   handlerThread.detach();
883 #endif
884 
885   lazyInstallState->success = true;
886   return true;
887 }
888 
EnsureFullSignalHandlers(JSContext * cx)889 bool wasm::EnsureFullSignalHandlers(JSContext* cx) {
890   if (cx->wasm().triedToInstallSignalHandlers) {
891     return cx->wasm().haveSignalHandlers;
892   }
893 
894   cx->wasm().triedToInstallSignalHandlers = true;
895   MOZ_RELEASE_ASSERT(!cx->wasm().haveSignalHandlers);
896 
897   {
898     auto eagerInstallState = sEagerInstallState.lock();
899     MOZ_RELEASE_ASSERT(eagerInstallState->tried);
900     if (!eagerInstallState->success) {
901       return false;
902     }
903   }
904 
905   if (!EnsureLazyProcessSignalHandlers()) {
906     return false;
907   }
908 
909 #ifdef XP_DARWIN
910   // In addition to the process-wide signal handler setup, OSX needs each
911   // thread configured to send its exceptions to sMachDebugPort. While there
912   // are also task-level (i.e. process-level) exception ports, those are
913   // "claimed" by breakpad and chaining Mach exceptions is dark magic that we
914   // avoid by instead intercepting exceptions at the thread level before they
915   // propagate to the process-level. This works because there are no other
916   // uses of thread-level exception ports.
917   MOZ_RELEASE_ASSERT(sMachDebugPort != MACH_PORT_NULL);
918   thread_port_t thisThread = mach_thread_self();
919   kern_return_t kret = thread_set_exception_ports(
920       thisThread, EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION,
921       sMachDebugPort, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
922       THREAD_STATE_NONE);
923   mach_port_deallocate(mach_task_self(), thisThread);
924   if (kret != KERN_SUCCESS) {
925     return false;
926   }
927 #endif
928 
929   cx->wasm().haveSignalHandlers = true;
930   return true;
931 }
932 
MemoryAccessTraps(const RegisterState & regs,uint8_t * addr,uint32_t numBytes,uint8_t ** newPC)933 bool wasm::MemoryAccessTraps(const RegisterState& regs, uint8_t* addr,
934                              uint32_t numBytes, uint8_t** newPC) {
935   const wasm::CodeSegment* codeSegment = wasm::LookupCodeSegment(regs.pc);
936   if (!codeSegment || !codeSegment->isModule()) {
937     return false;
938   }
939 
940   const wasm::ModuleSegment& segment = *codeSegment->asModule();
941 
942   Trap trap;
943   BytecodeOffset bytecode;
944   if (!segment.code().lookupTrap(regs.pc, &trap, &bytecode) ||
945       trap != Trap::OutOfBounds) {
946     return false;
947   }
948 
949   Instance& instance =
950       *GetNearestEffectiveTls(Frame::fromUntaggedWasmExitFP(regs.fp))->instance;
951   MOZ_ASSERT(&instance.code() == &segment.code());
952 
953   if (!instance.memoryAccessInGuardRegion((uint8_t*)addr, numBytes)) {
954     return false;
955   }
956 
957   jit::JitActivation* activation = TlsContext.get()->activation()->asJit();
958   activation->startWasmTrap(Trap::OutOfBounds, bytecode.offset(), regs);
959   *newPC = segment.trapCode();
960   return true;
961 }
962 
HandleIllegalInstruction(const RegisterState & regs,uint8_t ** newPC)963 bool wasm::HandleIllegalInstruction(const RegisterState& regs,
964                                     uint8_t** newPC) {
965   const wasm::CodeSegment* codeSegment = wasm::LookupCodeSegment(regs.pc);
966   if (!codeSegment || !codeSegment->isModule()) {
967     return false;
968   }
969 
970   const wasm::ModuleSegment& segment = *codeSegment->asModule();
971 
972   Trap trap;
973   BytecodeOffset bytecode;
974   if (!segment.code().lookupTrap(regs.pc, &trap, &bytecode)) {
975     return false;
976   }
977 
978   jit::JitActivation* activation = TlsContext.get()->activation()->asJit();
979   activation->startWasmTrap(trap, bytecode.offset(), regs);
980   *newPC = segment.trapCode();
981   return true;
982 }
983