tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WasmSignalHandlers.cpp (37679B)


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