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