Source code

Revision control

Other Tools

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
*
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/ScopeExit.h"
23
#include "mozilla/ThreadLocal.h"
24
25
#include "threading/Thread.h"
26
#include "vm/JitActivation.h" // js::jit::JitActivation
27
#include "vm/Realm.h"
28
#include "vm/Runtime.h"
29
#include "wasm/WasmInstance.h"
30
31
#if defined(XP_WIN)
32
# include <winternl.h> // must include before util/Windows.h's `#undef`s
33
# include "util/Windows.h"
34
#elif defined(XP_DARWIN)
35
# include <mach/exc.h>
36
# include <mach/mach.h>
37
#else
38
# include <signal.h>
39
#endif
40
41
using namespace js;
42
using namespace js::wasm;
43
44
using mozilla::DebugOnly;
45
46
// =============================================================================
47
// This following pile of macros and includes defines the ToRegisterState() and
48
// the ContextTo{PC,FP,SP,LR}() functions from the (highly) platform-specific
49
// CONTEXT struct which is provided to the signal handler.
50
// =============================================================================
51
52
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
53
# include <sys/ucontext.h> // for ucontext_t, mcontext_t
54
#endif
55
56
#if defined(__x86_64__)
57
# if defined(__DragonFly__)
58
# include <machine/npx.h> // for union savefpu
59
# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
60
defined(__NetBSD__) || defined(__OpenBSD__)
61
# include <machine/fpu.h> // for struct savefpu/fxsave64
62
# endif
63
#endif
64
65
#if defined(XP_WIN)
66
# define EIP_sig(p) ((p)->Eip)
67
# define EBP_sig(p) ((p)->Ebp)
68
# define ESP_sig(p) ((p)->Esp)
69
# define RIP_sig(p) ((p)->Rip)
70
# define RSP_sig(p) ((p)->Rsp)
71
# define RBP_sig(p) ((p)->Rbp)
72
# define R11_sig(p) ((p)->R11)
73
# define R13_sig(p) ((p)->R13)
74
# define R14_sig(p) ((p)->R14)
75
# define R15_sig(p) ((p)->R15)
76
# define EPC_sig(p) ((p)->Pc)
77
# define RFP_sig(p) ((p)->Fp)
78
# define R31_sig(p) ((p)->Sp)
79
# define RLR_sig(p) ((p)->Lr)
80
#elif defined(__OpenBSD__)
81
# define EIP_sig(p) ((p)->sc_eip)
82
# define EBP_sig(p) ((p)->sc_ebp)
83
# define ESP_sig(p) ((p)->sc_esp)
84
# define RIP_sig(p) ((p)->sc_rip)
85
# define RSP_sig(p) ((p)->sc_rsp)
86
# define RBP_sig(p) ((p)->sc_rbp)
87
# define R11_sig(p) ((p)->sc_r11)
88
# if defined(__arm__)
89
# define R13_sig(p) ((p)->sc_usr_sp)
90
# define R14_sig(p) ((p)->sc_usr_lr)
91
# define R15_sig(p) ((p)->sc_pc)
92
# else
93
# define R13_sig(p) ((p)->sc_r13)
94
# define R14_sig(p) ((p)->sc_r14)
95
# define R15_sig(p) ((p)->sc_r15)
96
# endif
97
# if defined(__aarch64__)
98
# define EPC_sig(p) ((p)->sc_elr)
99
# define RFP_sig(p) ((p)->sc_x[29])
100
# define RLR_sig(p) ((p)->sc_lr)
101
# define R31_sig(p) ((p)->sc_sp)
102
# endif
103
# if defined(__mips__)
104
# define EPC_sig(p) ((p)->sc_pc)
105
# define RFP_sig(p) ((p)->sc_regs[30])
106
# endif
107
# if defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \
108
defined(__PPC64LE__)
109
# define R01_sig(p) ((p)->sc_frame.fixreg[1])
110
# define R32_sig(p) ((p)->sc_frame.srr0)
111
# endif
112
#elif defined(__linux__) || defined(__sun)
113
# if defined(__linux__)
114
# define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_EIP])
115
# define EBP_sig(p) ((p)->uc_mcontext.gregs[REG_EBP])
116
# define ESP_sig(p) ((p)->uc_mcontext.gregs[REG_ESP])
117
# else
118
# define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_PC])
119
# define EBP_sig(p) ((p)->uc_mcontext.gregs[REG_EBP])
120
# define ESP_sig(p) ((p)->uc_mcontext.gregs[REG_ESP])
121
# endif
122
# define RIP_sig(p) ((p)->uc_mcontext.gregs[REG_RIP])
123
# define RSP_sig(p) ((p)->uc_mcontext.gregs[REG_RSP])
124
# define RBP_sig(p) ((p)->uc_mcontext.gregs[REG_RBP])
125
# if defined(__linux__) && defined(__arm__)
126
# define R11_sig(p) ((p)->uc_mcontext.arm_fp)
127
# define R13_sig(p) ((p)->uc_mcontext.arm_sp)
128
# define R14_sig(p) ((p)->uc_mcontext.arm_lr)
129
# define R15_sig(p) ((p)->uc_mcontext.arm_pc)
130
# else
131
# define R11_sig(p) ((p)->uc_mcontext.gregs[REG_R11])
132
# define R13_sig(p) ((p)->uc_mcontext.gregs[REG_R13])
133
# define R14_sig(p) ((p)->uc_mcontext.gregs[REG_R14])
134
# define R15_sig(p) ((p)->uc_mcontext.gregs[REG_R15])
135
# endif
136
# if defined(__linux__) && defined(__aarch64__)
137
# define EPC_sig(p) ((p)->uc_mcontext.pc)
138
# define RFP_sig(p) ((p)->uc_mcontext.regs[29])
139
# define RLR_sig(p) ((p)->uc_mcontext.regs[30])
140
# define R31_sig(p) ((p)->uc_mcontext.sp)
141
# endif
142
# if defined(__linux__) && defined(__mips__)
143
# define EPC_sig(p) ((p)->uc_mcontext.pc)
144
# define RFP_sig(p) ((p)->uc_mcontext.gregs[30])
145
# define RSP_sig(p) ((p)->uc_mcontext.gregs[29])
146
# define R31_sig(p) ((p)->uc_mcontext.gregs[31])
147
# endif
148
# if defined(__linux__) && (defined(__sparc__) && defined(__arch64__))
149
# define PC_sig(p) ((p)->uc_mcontext.mc_gregs[MC_PC])
150
# define FP_sig(p) ((p)->uc_mcontext.mc_fp)
151
# define SP_sig(p) ((p)->uc_mcontext.mc_i7)
152
# endif
153
# if defined(__linux__) && (defined(__ppc64__) || defined(__PPC64__) || \
154
defined(__ppc64le__) || defined(__PPC64LE__))
155
# define R01_sig(p) ((p)->uc_mcontext.gp_regs[1])
156
# define R32_sig(p) ((p)->uc_mcontext.gp_regs[32])
157
# endif
158
#elif defined(__NetBSD__)
159
# define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
160
# define EBP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EBP])
161
# define ESP_sig(p) ((p)->uc_mcontext.__gregs[_REG_ESP])
162
# define RIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_RIP])
163
# define RSP_sig(p) ((p)->uc_mcontext.__gregs[_REG_RSP])
164
# define RBP_sig(p) ((p)->uc_mcontext.__gregs[_REG_RBP])
165
# define R11_sig(p) ((p)->uc_mcontext.__gregs[_REG_R11])
166
# define R13_sig(p) ((p)->uc_mcontext.__gregs[_REG_R13])
167
# define R14_sig(p) ((p)->uc_mcontext.__gregs[_REG_R14])
168
# define R15_sig(p) ((p)->uc_mcontext.__gregs[_REG_R15])
169
# if defined(__aarch64__)
170
# define EPC_sig(p) ((p)->uc_mcontext.__gregs[_REG_PC])
171
# define RFP_sig(p) ((p)->uc_mcontext.__gregs[_REG_X29])
172
# define RLR_sig(p) ((p)->uc_mcontext.__gregs[_REG_X30])
173
# define R31_sig(p) ((p)->uc_mcontext.__gregs[_REG_SP])
174
# endif
175
# if defined(__mips__)
176
# define EPC_sig(p) ((p)->uc_mcontext.__gregs[_REG_EPC])
177
# define RFP_sig(p) ((p)->uc_mcontext.__gregs[_REG_S8])
178
# endif
179
# if defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \
180
defined(__PPC64LE__)
181
# define R01_sig(p) ((p)->uc_mcontext.__gregs[_REG_R1])
182
# define R32_sig(p) ((p)->uc_mcontext.__gregs[_REG_PC])
183
# endif
184
#elif defined(__DragonFly__) || defined(__FreeBSD__) || \
185
defined(__FreeBSD_kernel__)
186
# define EIP_sig(p) ((p)->uc_mcontext.mc_eip)
187
# define EBP_sig(p) ((p)->uc_mcontext.mc_ebp)
188
# define ESP_sig(p) ((p)->uc_mcontext.mc_esp)
189
# define RIP_sig(p) ((p)->uc_mcontext.mc_rip)
190
# define RSP_sig(p) ((p)->uc_mcontext.mc_rsp)
191
# define RBP_sig(p) ((p)->uc_mcontext.mc_rbp)
192
# if defined(__FreeBSD__) && defined(__arm__)
193
# define R11_sig(p) ((p)->uc_mcontext.__gregs[_REG_R11])
194
# define R13_sig(p) ((p)->uc_mcontext.__gregs[_REG_R13])
195
# define R14_sig(p) ((p)->uc_mcontext.__gregs[_REG_R14])
196
# define R15_sig(p) ((p)->uc_mcontext.__gregs[_REG_R15])
197
# else
198
# define R11_sig(p) ((p)->uc_mcontext.mc_r11)
199
# define R13_sig(p) ((p)->uc_mcontext.mc_r13)
200
# define R14_sig(p) ((p)->uc_mcontext.mc_r14)
201
# define R15_sig(p) ((p)->uc_mcontext.mc_r15)
202
# endif
203
# if defined(__FreeBSD__) && defined(__aarch64__)
204
# define EPC_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_elr)
205
# define RFP_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_x[29])
206
# define RLR_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_lr)
207
# define R31_sig(p) ((p)->uc_mcontext.mc_gpregs.gp_sp)
208
# endif
209
# if defined(__FreeBSD__) && defined(__mips__)
210
# define EPC_sig(p) ((p)->uc_mcontext.mc_pc)
211
# define RFP_sig(p) ((p)->uc_mcontext.mc_regs[30])
212
# endif
213
# if defined(__FreeBSD__) && (defined(__ppc64__) || defined(__PPC64__) || \
214
defined(__ppc64le__) || defined(__PPC64LE__))
215
# define R01_sig(p) ((p)->uc_mcontext.mc_gpr[1])
216
# define R32_sig(p) ((p)->uc_mcontext.mc_srr0)
217
# endif
218
#elif defined(XP_DARWIN)
219
# define EIP_sig(p) ((p)->thread.uts.ts32.__eip)
220
# define EBP_sig(p) ((p)->thread.uts.ts32.__ebp)
221
# define ESP_sig(p) ((p)->thread.uts.ts32.__esp)
222
# define RIP_sig(p) ((p)->thread.__rip)
223
# define RBP_sig(p) ((p)->thread.__rbp)
224
# define RSP_sig(p) ((p)->thread.__rsp)
225
# define R11_sig(p) ((p)->thread.__r[11])
226
# define R13_sig(p) ((p)->thread.__sp)
227
# define R14_sig(p) ((p)->thread.__lr)
228
# define R15_sig(p) ((p)->thread.__pc)
229
#else
230
# error "Don't know how to read/write to the thread state via the mcontext_t."
231
#endif
232
233
// On ARM Linux, including Android, unaligned FP accesses that were not flagged
234
// as unaligned will tend to trap (with SIGBUS) and will need to be emulated.
235
//
236
// We can only perform this emulation if the system header files provide access
237
// to the FP registers. In particular, <sys/user.h> must have definitions of
238
// `struct user_vfp` and `struct user_vfp_exc`, as it does on Android.
239
//
240
// Those definitions are however not present in the headers of every Linux
241
// distro - Raspbian is known to be a problem, for example. However those
242
// distros are tier-3 platforms.
243
//
244
// If you run into compile problems on a tier-3 platform, you can disable the
245
// emulation here.
246
247
#if defined(__linux__) && defined(__arm__)
248
# define WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS
249
#endif
250
251
#ifdef WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS
252
# include <sys/user.h>
253
#endif
254
255
#if defined(ANDROID)
256
// Not all versions of the Android NDK define ucontext_t or mcontext_t.
257
// Detect this and provide custom but compatible definitions. Note that these
258
// follow the GLibc naming convention to access register values from
259
// mcontext_t.
260
//
263
# if !defined(__BIONIC_HAVE_UCONTEXT_T)
264
# if defined(__arm__)
265
266
// GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
267
// Old versions of the C library <signal.h> didn't define the type.
268
# if !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
269
# include <asm/sigcontext.h>
270
# endif
271
272
typedef struct sigcontext mcontext_t;
273
274
typedef struct ucontext {
275
uint32_t uc_flags;
276
struct ucontext* uc_link;
277
stack_t uc_stack;
278
mcontext_t uc_mcontext;
279
// Other fields are not used so don't define them here.
280
} ucontext_t;
281
282
# elif defined(__mips__)
283
284
typedef struct {
285
uint32_t regmask;
286
uint32_t status;
287
uint64_t pc;
288
uint64_t gregs[32];
289
uint64_t fpregs[32];
290
uint32_t acx;
291
uint32_t fpc_csr;
292
uint32_t fpc_eir;
293
uint32_t used_math;
294
uint32_t dsp;
295
uint64_t mdhi;
296
uint64_t mdlo;
297
uint32_t hi1;
298
uint32_t lo1;
299
uint32_t hi2;
300
uint32_t lo2;
301
uint32_t hi3;
302
uint32_t lo3;
303
} mcontext_t;
304
305
typedef struct ucontext {
306
uint32_t uc_flags;
307
struct ucontext* uc_link;
308
stack_t uc_stack;
309
mcontext_t uc_mcontext;
310
// Other fields are not used so don't define them here.
311
} ucontext_t;
312
313
# elif defined(__i386__)
314
// x86 version for Android.
315
typedef struct {
316
uint32_t gregs[19];
317
void* fpregs;
318
uint32_t oldmask;
319
uint32_t cr2;
320
} mcontext_t;
321
322
typedef uint32_t kernel_sigset_t[2]; // x86 kernel uses 64-bit signal masks
323
typedef struct ucontext {
324
uint32_t uc_flags;
325
struct ucontext* uc_link;
326
stack_t uc_stack;
327
mcontext_t uc_mcontext;
328
// Other fields are not used by V8, don't define them here.
329
} ucontext_t;
330
enum { REG_EIP = 14 };
331
# endif // defined(__i386__)
332
# endif // !defined(__BIONIC_HAVE_UCONTEXT_T)
333
#endif // defined(ANDROID)
334
335
#if defined(XP_DARWIN)
336
# if defined(__x86_64__)
337
struct macos_x64_context {
338
x86_thread_state64_t thread;
339
x86_float_state64_t float_;
340
};
341
# define CONTEXT macos_x64_context
342
# elif defined(__i386__)
343
struct macos_x86_context {
344
x86_thread_state_t thread;
345
x86_float_state_t float_;
346
};
347
# define CONTEXT macos_x86_context
348
# elif defined(__arm__)
349
struct macos_arm_context {
350
arm_thread_state_t thread;
351
arm_neon_state_t float_;
352
};
353
# define CONTEXT macos_arm_context
354
# else
355
# error Unsupported architecture
356
# endif
357
#elif !defined(XP_WIN)
358
# define CONTEXT ucontext_t
359
#endif
360
361
#if defined(_M_X64) || defined(__x86_64__)
362
# define PC_sig(p) RIP_sig(p)
363
# define FP_sig(p) RBP_sig(p)
364
# define SP_sig(p) RSP_sig(p)
365
#elif defined(_M_IX86) || defined(__i386__)
366
# define PC_sig(p) EIP_sig(p)
367
# define FP_sig(p) EBP_sig(p)
368
# define SP_sig(p) ESP_sig(p)
369
#elif defined(__arm__)
370
# define FP_sig(p) R11_sig(p)
371
# define SP_sig(p) R13_sig(p)
372
# define LR_sig(p) R14_sig(p)
373
# define PC_sig(p) R15_sig(p)
374
#elif defined(_M_ARM64) || defined(__aarch64__)
375
# define PC_sig(p) EPC_sig(p)
376
# define FP_sig(p) RFP_sig(p)
377
# define SP_sig(p) R31_sig(p)
378
# define LR_sig(p) RLR_sig(p)
379
#elif defined(__mips__)
380
# define PC_sig(p) EPC_sig(p)
381
# define FP_sig(p) RFP_sig(p)
382
# define SP_sig(p) RSP_sig(p)
383
# define LR_sig(p) R31_sig(p)
384
#elif defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \
385
defined(__PPC64LE__)
386
# define PC_sig(p) R32_sig(p)
387
# define SP_sig(p) R01_sig(p)
388
# define FP_sig(p) R01_sig(p)
389
#endif
390
391
static void SetContextPC(CONTEXT* context, uint8_t* pc) {
392
#ifdef PC_sig
393
*reinterpret_cast<uint8_t**>(&PC_sig(context)) = pc;
394
#else
395
MOZ_CRASH();
396
#endif
397
}
398
399
static uint8_t* ContextToPC(CONTEXT* context) {
400
#ifdef PC_sig
401
return reinterpret_cast<uint8_t*>(PC_sig(context));
402
#else
403
MOZ_CRASH();
404
#endif
405
}
406
407
static uint8_t* ContextToFP(CONTEXT* context) {
408
#ifdef FP_sig
409
return reinterpret_cast<uint8_t*>(FP_sig(context));
410
#else
411
MOZ_CRASH();
412
#endif
413
}
414
415
static uint8_t* ContextToSP(CONTEXT* context) {
416
#ifdef SP_sig
417
return reinterpret_cast<uint8_t*>(SP_sig(context));
418
#else
419
MOZ_CRASH();
420
#endif
421
}
422
423
#if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
424
static uint8_t* ContextToLR(CONTEXT* context) {
425
# ifdef LR_sig
426
return reinterpret_cast<uint8_t*>(LR_sig(context));
427
# else
428
MOZ_CRASH();
429
# endif
430
}
431
#endif
432
433
static JS::ProfilingFrameIterator::RegisterState ToRegisterState(
434
CONTEXT* context) {
435
JS::ProfilingFrameIterator::RegisterState state;
436
state.fp = ContextToFP(context);
437
state.pc = ContextToPC(context);
438
state.sp = ContextToSP(context);
439
#if defined(__arm__) || defined(__aarch64__) || defined(__mips__)
440
state.lr = ContextToLR(context);
441
#else
442
state.lr = (void*)UINTPTR_MAX;
443
#endif
444
return state;
445
}
446
447
// =============================================================================
448
// All signals/exceptions funnel down to this one trap-handling function which
449
// tests whether the pc is in a wasm module and, if so, whether there is
450
// actually a trap expected at this pc. These tests both avoid real bugs being
451
// silently converted to wasm traps and provides the trapping wasm bytecode
452
// offset we need to report in the error.
453
//
454
// Crashing inside wasm trap handling (due to a bug in trap handling or exposed
455
// during trap handling) must be reported like a normal crash, not cause the
456
// crash report to be lost. On Windows and non-Mach Unix, a crash during the
457
// handler reenters the handler, possibly repeatedly until exhausting the stack,
458
// and so we prevent recursion with the thread-local sAlreadyHandlingTrap. On
459
// Mach, the wasm exception handler has its own thread and is installed only on
460
// the thread-level debugging ports of JSRuntime threads, so a crash on
461
// exception handler thread will not recurse; it will bubble up to the
462
// process-level debugging ports (where Breakpad is installed).
463
// =============================================================================
464
465
static MOZ_THREAD_LOCAL(bool) sAlreadyHandlingTrap;
466
467
struct AutoHandlingTrap {
468
AutoHandlingTrap() {
469
MOZ_ASSERT(!sAlreadyHandlingTrap.get());
470
sAlreadyHandlingTrap.set(true);
471
}
472
473
~AutoHandlingTrap() {
474
MOZ_ASSERT(sAlreadyHandlingTrap.get());
475
sAlreadyHandlingTrap.set(false);
476
}
477
};
478
479
#ifdef WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS
480
481
// Code to handle SIGBUS for unaligned floating point accesses on 32-bit ARM.
482
483
static uintptr_t ReadGPR(CONTEXT* context, uint32_t rn) {
484
switch (rn) {
485
case 0:
486
return context->uc_mcontext.arm_r0;
487
case 1:
488
return context->uc_mcontext.arm_r1;
489
case 2:
490
return context->uc_mcontext.arm_r2;
491
case 3:
492
return context->uc_mcontext.arm_r3;
493
case 4:
494
return context->uc_mcontext.arm_r4;
495
case 5:
496
return context->uc_mcontext.arm_r5;
497
case 6:
498
return context->uc_mcontext.arm_r6;
499
case 7:
500
return context->uc_mcontext.arm_r7;
501
case 8:
502
return context->uc_mcontext.arm_r8;
503
case 9:
504
return context->uc_mcontext.arm_r9;
505
case 10:
506
return context->uc_mcontext.arm_r10;
507
case 11:
508
return context->uc_mcontext.arm_fp;
509
case 12:
510
return context->uc_mcontext.arm_ip;
511
case 13:
512
return context->uc_mcontext.arm_sp;
513
case 14:
514
return context->uc_mcontext.arm_lr;
515
case 15:
516
return context->uc_mcontext.arm_pc;
517
default:
518
MOZ_CRASH();
519
}
520
}
521
522
// Linux kernel data structures.
523
//
524
// The vfp_sigframe is a kernel type overlaid on the uc_regspace field of the
525
// ucontext_t if the first word of the uc_regspace is VFP_MAGIC. (user_vfp and
526
// user_vfp_exc are defined in sys/user.h and are stable.)
527
//
528
// VFP_MAGIC appears to have been stable since a commit to Linux on 2010-04-11,
529
// when it was changed from being 0x56465001 on ARMv6 and earlier and 0x56465002
530
// on ARMv7 and later, to being 0x56465001 on all CPU versions. This was in
531
// Kernel 2.6.34-rc5.
532
//
533
// My best interpretation of the Android commit history is that Android has had
534
// vfp_sigframe and VFP_MAGIC in this form since at least Android 3.4 / 2012;
535
// Firefox requires Android 4.0 at least and we're probably safe here.
536
537
struct vfp_sigframe {
538
unsigned long magic;
539
unsigned long size;
540
struct user_vfp ufp;
541
struct user_vfp_exc ufp_exc;
542
};
543
544
# define VFP_MAGIC 0x56465001
545
546
static vfp_sigframe* GetVFPFrame(CONTEXT* context) {
547
if (context->uc_regspace[0] != VFP_MAGIC) {
548
return nullptr;
549
}
550
return (vfp_sigframe*)&context->uc_regspace;
551
}
552
553
static bool ReadFPR64(CONTEXT* context, uint32_t vd, double* val) {
554
MOZ_ASSERT(vd < 32);
555
vfp_sigframe* frame = GetVFPFrame(context);
556
if (frame) {
557
*val = ((double*)frame->ufp.fpregs)[vd];
558
return true;
559
}
560
return false;
561
}
562
563
static bool WriteFPR64(CONTEXT* context, uint32_t vd, double val) {
564
MOZ_ASSERT(vd < 32);
565
vfp_sigframe* frame = GetVFPFrame(context);
566
if (frame) {
567
((double*)frame->ufp.fpregs)[vd] = val;
568
return true;
569
}
570
return false;
571
}
572
573
static bool ReadFPR32(CONTEXT* context, uint32_t vd, float* val) {
574
MOZ_ASSERT(vd < 32);
575
vfp_sigframe* frame = GetVFPFrame(context);
576
if (frame) {
577
*val = ((float*)frame->ufp.fpregs)[vd];
578
return true;
579
}
580
return false;
581
}
582
583
static bool WriteFPR32(CONTEXT* context, uint32_t vd, float val) {
584
MOZ_ASSERT(vd < 32);
585
vfp_sigframe* frame = GetVFPFrame(context);
586
if (frame) {
587
((float*)frame->ufp.fpregs)[vd] = val;
588
return true;
589
}
590
return false;
591
}
592
593
static bool HandleUnalignedTrap(CONTEXT* context, uint8_t* pc,
594
Instance* instance) {
595
// ARM only, no Thumb.
596
MOZ_RELEASE_ASSERT(uintptr_t(pc) % 4 == 0);
597
598
// wasmLoadImpl() and wasmStoreImpl() in MacroAssembler-arm.cpp emit plain,
599
// unconditional VLDR and VSTR instructions that do not use the PC as the base
600
// register.
601
uint32_t instr = *(uint32_t*)pc;
602
uint32_t masked = instr & 0x0F300E00;
603
bool isVLDR = masked == 0x0D100A00;
604
bool isVSTR = masked == 0x0D000A00;
605
606
if (!isVLDR && !isVSTR) {
607
// Three obvious cases if we don't get our expected instructions:
608
// - masm is generating other FP access instructions than it should
609
// - we're encountering a device that traps on new kinds of accesses,
610
// perhaps unaligned integer accesses
611
// - general code generation bugs that lead to SIGBUS
612
# ifdef ANDROID
613
__android_log_print(ANDROID_LOG_ERROR, "WASM", "Bad SIGBUS instr %08x",
614
instr);
615
# endif
616
# ifdef DEBUG
617
MOZ_CRASH("Unexpected instruction");
618
# endif
619
return false;
620
}
621
622
bool isUnconditional = (instr >> 28) == 0xE;
623
bool isDouble = (instr & 0x00000100) != 0;
624
bool isAdd = (instr & 0x00800000) != 0;
625
uint32_t dBit = (instr >> 22) & 1;
626
uint32_t offs = (instr & 0xFF) << 2;
627
uint32_t rn = (instr >> 16) & 0xF;
628
629
MOZ_RELEASE_ASSERT(isUnconditional);
630
MOZ_RELEASE_ASSERT(rn != 15);
631
632
uint8_t* p = (uint8_t*)ReadGPR(context, rn) + (isAdd ? offs : -offs);
633
634
if (!instance->memoryAccessInBounds(
635
p, isDouble ? sizeof(double) : sizeof(float))) {
636
return false;
637
}
638
639
if (isDouble) {
640
uint32_t vd = ((instr >> 12) & 0xF) | (dBit << 4);
641
double val;
642
if (isVLDR) {
643
memcpy(&val, p, sizeof(val));
644
if (WriteFPR64(context, vd, val)) {
645
SetContextPC(context, pc + 4);
646
return true;
647
}
648
} else {
649
if (ReadFPR64(context, vd, &val)) {
650
memcpy(p, &val, sizeof(val));
651
SetContextPC(context, pc + 4);
652
return true;
653
}
654
}
655
} else {
656
uint32_t vd = ((instr >> 11) & (0xF << 1)) | dBit;
657
float val;
658
if (isVLDR) {
659
memcpy(&val, p, sizeof(val));
660
if (WriteFPR32(context, vd, val)) {
661
SetContextPC(context, pc + 4);
662
return true;
663
}
664
} else {
665
if (ReadFPR32(context, vd, &val)) {
666
memcpy(p, &val, sizeof(val));
667
SetContextPC(context, pc + 4);
668
return true;
669
}
670
}
671
}
672
673
# ifdef DEBUG
674
MOZ_CRASH(
675
"SIGBUS handler could not access FP register, incompatible kernel?");
676
# endif
677
return false;
678
}
679
#else // WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS
680
static bool HandleUnalignedTrap(CONTEXT* context, uint8_t* pc,
681
Instance* instance) {
682
return false;
683
}
684
#endif // WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS
685
686
static MOZ_MUST_USE bool HandleTrap(CONTEXT* context,
687
bool isUnalignedSignal = false,
688
JSContext* assertCx = nullptr) {
689
MOZ_ASSERT(sAlreadyHandlingTrap.get());
690
691
uint8_t* pc = ContextToPC(context);
692
const CodeSegment* codeSegment = LookupCodeSegment(pc);
693
if (!codeSegment || !codeSegment->isModule()) {
694
return false;
695
}
696
697
const ModuleSegment& segment = *codeSegment->asModule();
698
699
Trap trap;
700
BytecodeOffset bytecode;
701
if (!segment.code().lookupTrap(pc, &trap, &bytecode)) {
702
return false;
703
}
704
705
// We have a safe, expected wasm trap, so fp is well-defined to be a Frame*.
706
// For the first sanity check, the Trap::IndirectCallBadSig special case is
707
// due to this trap occurring in the indirect call prologue, while fp points
708
// to the caller's Frame which can be in a different Module. In any case,
709
// though, the containing JSContext is the same.
710
Instance* instance = ((Frame*)ContextToFP(context))->tls->instance;
711
MOZ_RELEASE_ASSERT(&instance->code() == &segment.code() ||
712
trap == Trap::IndirectCallBadSig);
713
714
if (isUnalignedSignal) {
715
if (trap != Trap::OutOfBounds) {
716
return false;
717
}
718
if (HandleUnalignedTrap(context, pc, instance)) {
719
return true;
720
}
721
}
722
723
JSContext* cx =
724
instance->realm()->runtimeFromAnyThread()->mainContextFromAnyThread();
725
MOZ_RELEASE_ASSERT(!assertCx || cx == assertCx);
726
727
// JitActivation::startWasmTrap() stores enough register state from the
728
// point of the trap to allow stack unwinding or resumption, both of which
729
// will call finishWasmTrap().
730
jit::JitActivation* activation = cx->activation()->asJit();
731
activation->startWasmTrap(trap, bytecode.offset(), ToRegisterState(context));
732
SetContextPC(context, segment.trapCode());
733
return true;
734
}
735
736
// =============================================================================
737
// The following platform-specific handlers funnel all signals/exceptions into
738
// the shared HandleTrap() above.
739
// =============================================================================
740
741
#if defined(XP_WIN)
742
// Obtained empirically from thread_local codegen on x86/x64/arm64.
743
// Compiled in all user binaries, so should be stable over time.
744
static const unsigned sThreadLocalArrayPointerIndex = 11;
745
746
static LONG WINAPI WasmTrapHandler(LPEXCEPTION_POINTERS exception) {
747
// Make sure TLS is initialized before reading sAlreadyHandlingTrap.
748
if (!NtCurrentTeb()->Reserved1[sThreadLocalArrayPointerIndex]) {
749
return EXCEPTION_CONTINUE_SEARCH;
750
}
751
752
if (sAlreadyHandlingTrap.get()) {
753
return EXCEPTION_CONTINUE_SEARCH;
754
}
755
AutoHandlingTrap aht;
756
757
EXCEPTION_RECORD* record = exception->ExceptionRecord;
758
if (record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION &&
759
record->ExceptionCode != EXCEPTION_ILLEGAL_INSTRUCTION) {
760
return EXCEPTION_CONTINUE_SEARCH;
761
}
762
763
if (!HandleTrap(exception->ContextRecord, false, TlsContext.get())) {
764
return EXCEPTION_CONTINUE_SEARCH;
765
}
766
767
return EXCEPTION_CONTINUE_EXECUTION;
768
}
769
770
#elif defined(XP_DARWIN)
771
// On OSX we are forced to use the lower-level Mach exception mechanism instead
772
// of Unix signals because breakpad uses Mach exceptions and would otherwise
773
// report a crash before wasm gets a chance to handle the exception.
774
775
// This definition was generated by mig (the Mach Interface Generator) for the
776
// routine 'exception_raise' (exc.defs).
777
# pragma pack(4)
778
typedef struct {
779
mach_msg_header_t Head;
780
/* start of the kernel processed data */
781
mach_msg_body_t msgh_body;
782
mach_msg_port_descriptor_t thread;
783
mach_msg_port_descriptor_t task;
784
/* end of the kernel processed data */
785
NDR_record_t NDR;
786
exception_type_t exception;
787
mach_msg_type_number_t codeCnt;
788
int64_t code[2];
789
} Request__mach_exception_raise_t;
790
# pragma pack()
791
792
// The full Mach message also includes a trailer.
793
struct ExceptionRequest {
794
Request__mach_exception_raise_t body;
795
mach_msg_trailer_t trailer;
796
};
797
798
static bool HandleMachException(const ExceptionRequest& request) {
799
// Get the port of the JSContext's thread from the message.
800
mach_port_t cxThread = request.body.thread.name;
801
802
// Read out the JSRuntime thread's register state.
803
CONTEXT context;
804
# if defined(__x86_64__)
805
unsigned int thread_state_count = x86_THREAD_STATE64_COUNT;
806
unsigned int float_state_count = x86_FLOAT_STATE64_COUNT;
807
int thread_state = x86_THREAD_STATE64;
808
int float_state = x86_FLOAT_STATE64;
809
# elif defined(__i386__)
810
unsigned int thread_state_count = x86_THREAD_STATE_COUNT;
811
unsigned int float_state_count = x86_FLOAT_STATE_COUNT;
812
int thread_state = x86_THREAD_STATE;
813
int float_state = x86_FLOAT_STATE;
814
# elif defined(__arm__)
815
unsigned int thread_state_count = ARM_THREAD_STATE_COUNT;
816
unsigned int float_state_count = ARM_NEON_STATE_COUNT;
817
int thread_state = ARM_THREAD_STATE;
818
int float_state = ARM_NEON_STATE;
819
# else
820
# error Unsupported architecture
821
# endif
822
kern_return_t kret;
823
kret = thread_get_state(cxThread, thread_state,
824
(thread_state_t)&context.thread, &thread_state_count);
825
if (kret != KERN_SUCCESS) {
826
return false;
827
}
828
kret = thread_get_state(cxThread, float_state,
829
(thread_state_t)&context.float_, &float_state_count);
830
if (kret != KERN_SUCCESS) {
831
return false;
832
}
833
834
if (request.body.exception != EXC_BAD_ACCESS &&
835
request.body.exception != EXC_BAD_INSTRUCTION) {
836
return false;
837
}
838
839
{
840
AutoNoteSingleThreadedRegion anstr;
841
AutoHandlingTrap aht;
842
if (!HandleTrap(&context)) {
843
return false;
844
}
845
}
846
847
// Update the thread state with the new pc and register values.
848
kret = thread_set_state(cxThread, float_state,
849
(thread_state_t)&context.float_, float_state_count);
850
if (kret != KERN_SUCCESS) {
851
return false;
852
}
853
kret = thread_set_state(cxThread, thread_state,
854
(thread_state_t)&context.thread, thread_state_count);
855
if (kret != KERN_SUCCESS) {
856
return false;
857
}
858
859
return true;
860
}
861
862
static mach_port_t sMachDebugPort = MACH_PORT_NULL;
863
864
static void MachExceptionHandlerThread() {
865
// Taken from mach_exc in /usr/include/mach/mach_exc.defs.
866
static const unsigned EXCEPTION_MSG_ID = 2405;
867
868
while (true) {
869
ExceptionRequest request;
870
kern_return_t kret =
871
mach_msg(&request.body.Head, MACH_RCV_MSG, 0, sizeof(request),
872
sMachDebugPort, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
873
874
// If we fail even receiving the message, we can't even send a reply!
875
// Rather than hanging the faulting thread (hanging the browser), crash.
876
if (kret != KERN_SUCCESS) {
877
fprintf(stderr, "MachExceptionHandlerThread: mach_msg failed with %d\n",
878
(int)kret);
879
MOZ_CRASH();
880
}
881
882
if (request.body.Head.msgh_id != EXCEPTION_MSG_ID) {
883
fprintf(stderr, "Unexpected msg header id %d\n",
884
(int)request.body.Head.msgh_bits);
885
MOZ_CRASH();
886
}
887
888
// Some thread just commited an EXC_BAD_ACCESS and has been suspended by
889
// the kernel. The kernel is waiting for us to reply with instructions.
890
// Our default is the "not handled" reply (by setting the RetCode field
891
// of the reply to KERN_FAILURE) which tells the kernel to continue
892
// searching at the process and system level. If this is an asm.js
893
// expected exception, we handle it and return KERN_SUCCESS.
894
bool handled = HandleMachException(request);
895
kern_return_t replyCode = handled ? KERN_SUCCESS : KERN_FAILURE;
896
897
// This magic incantation to send a reply back to the kernel was
898
// derived from the exc_server generated by
899
// 'mig -v /usr/include/mach/mach_exc.defs'.
900
__Reply__exception_raise_t reply;
901
reply.Head.msgh_bits =
902
MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.body.Head.msgh_bits), 0);
903
reply.Head.msgh_size = sizeof(reply);
904
reply.Head.msgh_remote_port = request.body.Head.msgh_remote_port;
905
reply.Head.msgh_local_port = MACH_PORT_NULL;
906
reply.Head.msgh_id = request.body.Head.msgh_id + 100;
907
reply.NDR = NDR_record;
908
reply.RetCode = replyCode;
909
mach_msg(&reply.Head, MACH_SEND_MSG, sizeof(reply), 0, MACH_PORT_NULL,
910
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
911
}
912
}
913
914
#else // If not Windows or Mac, assume Unix
915
916
# ifdef __mips__
917
static const uint32_t kWasmTrapSignal = SIGFPE;
918
# else
919
static const uint32_t kWasmTrapSignal = SIGILL;
920
# endif
921
922
static struct sigaction sPrevSEGVHandler;
923
static struct sigaction sPrevSIGBUSHandler;
924
static struct sigaction sPrevWasmTrapHandler;
925
926
static void WasmTrapHandler(int signum, siginfo_t* info, void* context) {
927
if (!sAlreadyHandlingTrap.get()) {
928
AutoHandlingTrap aht;
929
MOZ_RELEASE_ASSERT(signum == SIGSEGV || signum == SIGBUS ||
930
signum == kWasmTrapSignal);
931
if (HandleTrap((CONTEXT*)context, signum == SIGBUS, TlsContext.get())) {
932
return;
933
}
934
}
935
936
struct sigaction* previousSignal = nullptr;
937
switch (signum) {
938
case SIGSEGV:
939
previousSignal = &sPrevSEGVHandler;
940
break;
941
case SIGBUS:
942
previousSignal = &sPrevSIGBUSHandler;
943
break;
944
case kWasmTrapSignal:
945
previousSignal = &sPrevWasmTrapHandler;
946
break;
947
}
948
MOZ_ASSERT(previousSignal);
949
950
// This signal is not for any asm.js code we expect, so we need to forward
951
// the signal to the next handler. If there is no next handler (SIG_IGN or
952
// SIG_DFL), then it's time to crash. To do this, we set the signal back to
953
// its original disposition and return. This will cause the faulting op to
954
// be re-executed which will crash in the normal way. The advantage of
955
// doing this to calling _exit() is that we remove ourselves from the crash
956
// stack which improves crash reports. If there is a next handler, call it.
957
// It will either crash synchronously, fix up the instruction so that
958
// execution can continue and return, or trigger a crash by returning the
959
// signal to it's original disposition and returning.
960
//
961
// Note: the order of these tests matter.
962
if (previousSignal->sa_flags & SA_SIGINFO) {
963
previousSignal->sa_sigaction(signum, info, context);
964
} else if (previousSignal->sa_handler == SIG_DFL ||
965
previousSignal->sa_handler == SIG_IGN) {
966
sigaction(signum, previousSignal, nullptr);
967
} else {
968
previousSignal->sa_handler(signum);
969
}
970
}
971
#endif // XP_WIN || XP_DARWIN || assume unix
972
973
#if defined(ANDROID) && defined(MOZ_LINKER)
974
extern "C" MFBT_API bool IsSignalHandlingBroken();
975
#endif
976
977
struct InstallState {
978
bool tried;
979
bool success;
980
InstallState() : tried(false), success(false) {}
981
};
982
983
static ExclusiveData<InstallState> sEagerInstallState(
984
mutexid::WasmSignalInstallState);
985
986
void wasm::EnsureEagerProcessSignalHandlers() {
987
auto eagerInstallState = sEagerInstallState.lock();
988
if (eagerInstallState->tried) {
989
return;
990
}
991
992
eagerInstallState->tried = true;
993
MOZ_RELEASE_ASSERT(eagerInstallState->success == false);
994
995
#if defined(JS_CODEGEN_NONE)
996
// If there is no JIT, then there should be no Wasm signal handlers.
997
return;
998
#endif
999
1000
// Signal handlers are currently disabled when recording or replaying.
1001
if (mozilla::recordreplay::IsRecordingOrReplaying()) {
1002
return;
1003
}
1004
1005
#if defined(ANDROID) && defined(MOZ_LINKER)
1006
// Signal handling is broken on some android systems.
1007
if (IsSignalHandlingBroken()) {
1008
return;
1009
}
1010
#endif
1011
1012
sAlreadyHandlingTrap.infallibleInit();
1013
1014
// Install whatever exception/signal handler is appropriate for the OS.
1015
#if defined(XP_WIN)
1016
1017
# if defined(MOZ_ASAN)
1018
// Under ASan we need to let the ASan runtime's ShadowExceptionHandler stay
1019
// in the first handler position. This requires some coordination with
1020
// MemoryProtectionExceptionHandler::isDisabled().
1021
const bool firstHandler = false;
1022
# else
1023
// Otherwise, WasmTrapHandler needs to go first, so that we can recover
1024
// from wasm faults and continue execution without triggering handlers
1025
// such as MemoryProtectionExceptionHandler that assume we are crashing.
1026
const bool firstHandler = true;
1027
# endif
1028
if (!AddVectoredExceptionHandler(firstHandler, WasmTrapHandler)) {
1029
// Windows has all sorts of random security knobs for disabling things
1030
// so make this a dynamic failure that disables wasm, not a MOZ_CRASH().
1031
return;
1032
}
1033
1034
#elif defined(XP_DARWIN)
1035
// All the Mach setup in EnsureLazyProcessSignalHandlers.
1036
#else
1037
// SA_NODEFER allows us to reenter the signal handler if we crash while
1038
// handling the signal, and fall through to the Breakpad handler by testing
1039
// handlingSegFault.
1040
1041
// Allow handling OOB with signals on all architectures
1042
struct sigaction faultHandler;
1043
faultHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
1044
faultHandler.sa_sigaction = WasmTrapHandler;
1045
sigemptyset(&faultHandler.sa_mask);
1046
if (sigaction(SIGSEGV, &faultHandler, &sPrevSEGVHandler)) {
1047
MOZ_CRASH("unable to install segv handler");
1048
}
1049
1050
# if defined(JS_CODEGEN_ARM)
1051
// On Arm Handle Unaligned Accesses
1052
struct sigaction busHandler;
1053
busHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
1054
busHandler.sa_sigaction = WasmTrapHandler;
1055
sigemptyset(&busHandler.sa_mask);
1056
if (sigaction(SIGBUS, &busHandler, &sPrevSIGBUSHandler)) {
1057
MOZ_CRASH("unable to install sigbus handler");
1058
}
1059
# endif
1060
1061
// Install a handler to handle the instructions that are emitted to implement
1062
// wasm traps.
1063
struct sigaction wasmTrapHandler;
1064
wasmTrapHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
1065
wasmTrapHandler.sa_sigaction = WasmTrapHandler;
1066
sigemptyset(&wasmTrapHandler.sa_mask);
1067
if (sigaction(kWasmTrapSignal, &wasmTrapHandler, &sPrevWasmTrapHandler)) {
1068
MOZ_CRASH("unable to install wasm trap handler");
1069
}
1070
#endif
1071
1072
eagerInstallState->success = true;
1073
}
1074
1075
static ExclusiveData<InstallState> sLazyInstallState(
1076
mutexid::WasmSignalInstallState);
1077
1078
static bool EnsureLazyProcessSignalHandlers() {
1079
auto lazyInstallState = sLazyInstallState.lock();
1080
if (lazyInstallState->tried) {
1081
return lazyInstallState->success;
1082
}
1083
1084
lazyInstallState->tried = true;
1085
MOZ_RELEASE_ASSERT(lazyInstallState->success == false);
1086
1087
#ifdef XP_DARWIN
1088
// Create the port that all JSContext threads will redirect their traps to.
1089
kern_return_t kret;
1090
kret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
1091
&sMachDebugPort);
1092
if (kret != KERN_SUCCESS) {
1093
return false;
1094
}
1095
kret = mach_port_insert_right(mach_task_self(), sMachDebugPort,
1096
sMachDebugPort, MACH_MSG_TYPE_MAKE_SEND);
1097
if (kret != KERN_SUCCESS) {
1098
return false;
1099
}
1100
1101
// Create the thread that will wait on and service sMachDebugPort.
1102
// It's not useful to destroy this thread on process shutdown so
1103
// immediately detach on successful start.
1104
Thread handlerThread;
1105
if (!handlerThread.init(MachExceptionHandlerThread)) {
1106
return false;
1107
}
1108
handlerThread.detach();
1109
#endif
1110
1111
lazyInstallState->success = true;
1112
return true;
1113
}
1114
1115
bool wasm::EnsureFullSignalHandlers(JSContext* cx) {
1116
if (cx->wasmTriedToInstallSignalHandlers) {
1117
return cx->wasmHaveSignalHandlers;
1118
}
1119
1120
cx->wasmTriedToInstallSignalHandlers = true;
1121
MOZ_RELEASE_ASSERT(!cx->wasmHaveSignalHandlers);
1122
1123
{
1124
auto eagerInstallState = sEagerInstallState.lock();
1125
MOZ_RELEASE_ASSERT(eagerInstallState->tried);
1126
if (!eagerInstallState->success) {
1127
return false;
1128
}
1129
}
1130
1131
if (!EnsureLazyProcessSignalHandlers()) {
1132
return false;
1133
}
1134
1135
#ifdef XP_DARWIN
1136
// In addition to the process-wide signal handler setup, OSX needs each
1137
// thread configured to send its exceptions to sMachDebugPort. While there
1138
// are also task-level (i.e. process-level) exception ports, those are
1139
// "claimed" by breakpad and chaining Mach exceptions is dark magic that we
1140
// avoid by instead intercepting exceptions at the thread level before they
1141
// propagate to the process-level. This works because there are no other
1142
// uses of thread-level exception ports.
1143
MOZ_RELEASE_ASSERT(sMachDebugPort != MACH_PORT_NULL);
1144
thread_port_t thisThread = mach_thread_self();
1145
kern_return_t kret = thread_set_exception_ports(
1146
thisThread, EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION,
1147
sMachDebugPort, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
1148
THREAD_STATE_NONE);
1149
mach_port_deallocate(mach_task_self(), thisThread);
1150
if (kret != KERN_SUCCESS) {
1151
return false;
1152
}
1153
#endif
1154
1155
cx->wasmHaveSignalHandlers = true;
1156
return true;
1157
}
1158
1159
bool wasm::MemoryAccessTraps(const RegisterState& regs, uint8_t* addr,
1160
uint32_t numBytes, uint8_t** newPC) {
1161
const wasm::CodeSegment* codeSegment = wasm::LookupCodeSegment(regs.pc);
1162
if (!codeSegment || !codeSegment->isModule()) {
1163
return false;
1164
}
1165
1166
const wasm::ModuleSegment& segment = *codeSegment->asModule();
1167
1168
Trap trap;
1169
BytecodeOffset bytecode;
1170
if (!segment.code().lookupTrap(regs.pc, &trap, &bytecode) ||
1171
trap != Trap::OutOfBounds) {
1172
return false;
1173
}
1174
1175
Instance& instance = *reinterpret_cast<Frame*>(regs.fp)->tls->instance;
1176
MOZ_ASSERT(&instance.code() == &segment.code());
1177
1178
if (!instance.memoryAccessInGuardRegion((uint8_t*)addr, numBytes)) {
1179
return false;
1180
}
1181
1182
jit::JitActivation* activation = TlsContext.get()->activation()->asJit();
1183
activation->startWasmTrap(Trap::OutOfBounds, bytecode.offset(), regs);
1184
*newPC = segment.trapCode();
1185
return true;
1186
}
1187
1188
bool wasm::HandleIllegalInstruction(const RegisterState& regs,
1189
uint8_t** newPC) {
1190
const wasm::CodeSegment* codeSegment = wasm::LookupCodeSegment(regs.pc);
1191
if (!codeSegment || !codeSegment->isModule()) {
1192
return false;
1193
}
1194
1195
const wasm::ModuleSegment& segment = *codeSegment->asModule();
1196
1197
Trap trap;
1198
BytecodeOffset bytecode;
1199
if (!segment.code().lookupTrap(regs.pc, &trap, &bytecode)) {
1200
return false;
1201
}
1202
1203
jit::JitActivation* activation = TlsContext.get()->activation()->asJit();
1204
activation->startWasmTrap(trap, bytecode.offset(), regs);
1205
*newPC = segment.trapCode();
1206
return true;
1207
}
1208
1209
#undef WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS