1pub mod raw {
5 use std::ffi::c_void;
7
8 #[cfg(target_arch = "x86_64")]
9 extern "C" {
10 pub fn run_on_alternative_stack(stack_end: *mut u64, stack_begin: *mut u64) -> u64;
12 pub fn register_preservation_trampoline(); }
15
16 #[cfg(not(target_arch = "x86_64"))]
18 pub extern "C" fn register_preservation_trampoline() {
19 unimplemented!("register_preservation_trampoline");
20 }
21
22 extern "C" {
23 pub fn setjmp(env: *mut c_void) -> i32;
25 pub fn longjmp(env: *mut c_void, val: i32) -> !;
27 }
28}
29
30use crate::codegen::{BreakpointInfo, BreakpointMap};
31use crate::error::{InvokeError, RuntimeError};
32use crate::state::x64::{build_instance_image, read_stack, X64Register, GPR};
33use crate::state::{CodeVersion, ExecutionStateImage};
34use crate::vm;
35use libc::{mmap, mprotect, siginfo_t, MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
36#[cfg(feature = "managed")]
37use nix::sys::signal::SIGINT;
38use nix::sys::signal::{
39 sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
40 SIGTRAP,
41};
42use std::cell::{Cell, RefCell, UnsafeCell};
43use std::ffi::c_void;
44#[cfg(feature = "managed")]
45use std::process;
46#[cfg(feature = "managed")]
47use std::sync::atomic::{AtomicBool, Ordering};
48use std::sync::Once;
49
50#[cfg(target_arch = "x86_64")]
51pub(crate) unsafe fn run_on_alternative_stack(stack_end: *mut u64, stack_begin: *mut u64) -> u64 {
52 raw::run_on_alternative_stack(stack_end, stack_begin)
53}
54
55#[cfg(not(target_arch = "x86_64"))]
56pub(crate) unsafe fn run_on_alternative_stack(_stack_end: *mut u64, _stack_begin: *mut u64) -> u64 {
57 unimplemented!("run_on_alternative_stack");
58}
59
60const TRAP_STACK_SIZE: usize = 1048576; const SETJMP_BUFFER_LEN: usize = 128;
63type SetJmpBuffer = [i32; SETJMP_BUFFER_LEN];
64
65struct UnwindInfo {
66 jmpbuf: SetJmpBuffer, breakpoints: Option<BreakpointMap>,
68 payload: Option<Box<RuntimeError>>, }
70
71#[repr(packed)]
73#[derive(Default, Copy, Clone)]
74pub struct BoundaryRegisterPreservation {
75 pub r15: u64,
77 pub r14: u64,
79 pub r13: u64,
81 pub r12: u64,
83 pub rbx: u64,
85}
86
87thread_local! {
88 static UNWIND: UnsafeCell<Option<UnwindInfo>> = UnsafeCell::new(None);
89 static CURRENT_CTX: UnsafeCell<*mut vm::Ctx> = UnsafeCell::new(::std::ptr::null_mut());
90 static CURRENT_CODE_VERSIONS: RefCell<Vec<CodeVersion>> = RefCell::new(vec![]);
91 #[cfg(feature = "managed")]
92 static WAS_SIGINT_TRIGGERED: Cell<bool> = Cell::new(false);
93 static BOUNDARY_REGISTER_PRESERVATION: UnsafeCell<BoundaryRegisterPreservation> = UnsafeCell::new(BoundaryRegisterPreservation::default());
94}
95
96#[no_mangle]
98pub unsafe extern "C" fn get_boundary_register_preservation() -> *mut BoundaryRegisterPreservation {
99 BOUNDARY_REGISTER_PRESERVATION.with(|x| x.get())
100}
101
102struct InterruptSignalMem(*mut u8);
103unsafe impl Send for InterruptSignalMem {}
104unsafe impl Sync for InterruptSignalMem {}
105
106const INTERRUPT_SIGNAL_MEM_SIZE: usize = 4096;
107
108lazy_static! {
109 static ref INTERRUPT_SIGNAL_MEM: InterruptSignalMem = {
110 let ptr = unsafe {
111 mmap(
112 ::std::ptr::null_mut(),
113 INTERRUPT_SIGNAL_MEM_SIZE,
114 PROT_READ | PROT_WRITE,
115 MAP_PRIVATE | MAP_ANON,
116 -1,
117 0,
118 )
119 };
120 if ptr as isize == -1 {
121 panic!("cannot allocate code memory");
122 }
123 InterruptSignalMem(ptr as _)
124 };
125}
126#[cfg(feature = "managed")]
127static INTERRUPT_SIGNAL_DELIVERED: AtomicBool = AtomicBool::new(false);
128
129#[cfg(feature = "managed")]
131pub fn was_sigint_triggered_fault() -> bool {
132 WAS_SIGINT_TRIGGERED.with(|x| x.get())
133}
134
135pub unsafe fn with_ctx<R, F: FnOnce() -> R>(ctx: *mut vm::Ctx, cb: F) -> R {
137 let addr = CURRENT_CTX.with(|x| x.get());
138 let old = *addr;
139 *addr = ctx;
140 let ret = cb();
141 *addr = old;
142 ret
143}
144
145pub fn push_code_version(version: CodeVersion) {
147 CURRENT_CODE_VERSIONS.with(|x| x.borrow_mut().push(version));
148}
149
150pub fn pop_code_version() -> Option<CodeVersion> {
152 CURRENT_CODE_VERSIONS.with(|x| x.borrow_mut().pop())
153}
154
155pub unsafe fn get_wasm_interrupt_signal_mem() -> *mut u8 {
157 INTERRUPT_SIGNAL_MEM.0
158}
159
160pub unsafe fn set_wasm_interrupt_on_ctx(ctx: *mut vm::Ctx) {
162 if mprotect(
163 (&*ctx).internal.interrupt_signal_mem as _,
164 INTERRUPT_SIGNAL_MEM_SIZE,
165 PROT_NONE,
166 ) < 0
167 {
168 panic!("cannot set PROT_NONE on signal mem");
169 }
170}
171
172pub unsafe fn set_wasm_interrupt() {
174 let mem: *mut u8 = INTERRUPT_SIGNAL_MEM.0;
175 if mprotect(mem as _, INTERRUPT_SIGNAL_MEM_SIZE, PROT_NONE) < 0 {
176 panic!("cannot set PROT_NONE on signal mem");
177 }
178}
179
180pub unsafe fn clear_wasm_interrupt() {
182 let mem: *mut u8 = INTERRUPT_SIGNAL_MEM.0;
183 if mprotect(mem as _, INTERRUPT_SIGNAL_MEM_SIZE, PROT_READ | PROT_WRITE) < 0 {
184 panic!("cannot set PROT_READ | PROT_WRITE on signal mem");
185 }
186}
187
188pub unsafe fn catch_unsafe_unwind<R, F: FnOnce() -> R>(
190 f: F,
191 breakpoints: Option<BreakpointMap>,
192) -> Result<R, RuntimeError> {
193 let old = UNWIND.with(|x| -> Option<UnwindInfo> {
194 let val = x.get();
195 let old = val.as_mut().unwrap().take();
196 *val = Some(UnwindInfo {
197 jmpbuf: [0; SETJMP_BUFFER_LEN],
198 breakpoints: breakpoints,
199 payload: None,
200 });
201 old
202 });
203
204 let unwind = UNWIND.with(|x| x.get());
205 if raw::setjmp(&mut (*unwind).as_mut().unwrap().jmpbuf as *mut SetJmpBuffer as *mut _) != 0 {
206 let ret = UNWIND.with(|x| -> RuntimeError {
208 let val = x.get();
209 let current = val.as_mut().unwrap().take().unwrap();
210 *val = old;
211 *current.payload.unwrap()
212 });
213 Err(ret)
214 } else {
215 let ret = f();
216 UNWIND.with(|x| *x.get() = old);
218 Ok(ret)
219 }
220}
221
222pub unsafe fn begin_unsafe_unwind(e: Box<RuntimeError>) -> ! {
224 let unwind = UNWIND.with(|x| x.get());
225 let inner = (*unwind)
226 .as_mut()
227 .expect("not within a catch_unsafe_unwind scope");
228 inner.payload = Some(e);
229 raw::longjmp(&mut inner.jmpbuf as *mut SetJmpBuffer as *mut _, 0xffff);
230}
231
232unsafe fn with_breakpoint_map<R, F: FnOnce(Option<&BreakpointMap>) -> R>(f: F) -> R {
233 let unwind = UNWIND.with(|x| x.get());
234 let inner = (*unwind)
235 .as_mut()
236 .expect("not within a catch_unsafe_unwind scope");
237 f(inner.breakpoints.as_ref())
238}
239
240#[cfg(not(target_arch = "x86_64"))]
241pub fn allocate_and_run<R, F: FnOnce() -> R>(_size: usize, f: F) -> R {
243 f()
244}
245
246#[cfg(target_arch = "x86_64")]
247pub fn allocate_and_run<R, F: FnOnce() -> R>(size: usize, f: F) -> R {
249 struct Context<F: FnOnce() -> R, R> {
250 f: Option<F>,
251 ret: Option<R>,
252 }
253
254 extern "C" fn invoke<F: FnOnce() -> R, R>(ctx: &mut Context<F, R>) {
255 let f = ctx.f.take().unwrap();
256 ctx.ret = Some(f());
257 }
258
259 unsafe {
260 let mut ctx = Context {
261 f: Some(f),
262 ret: None,
263 };
264 assert!(size % 16 == 0);
265 assert!(size >= 4096);
266
267 let mut stack: Vec<u64> = vec![0; size / 8];
268 let end_offset = stack.len();
269
270 stack[end_offset - 4] = invoke::<F, R> as usize as u64;
271
272 stack[end_offset - 4 - 10] = &mut ctx as *mut Context<F, R> as usize as u64; const NUM_SAVED_REGISTERS: usize = 31;
275 let stack_begin = stack.as_mut_ptr().add(end_offset - 4 - NUM_SAVED_REGISTERS);
276 let stack_end = stack.as_mut_ptr().add(end_offset);
277
278 raw::run_on_alternative_stack(stack_end, stack_begin);
279 ctx.ret.take().unwrap()
280 }
281}
282
283extern "C" fn signal_trap_handler(
284 signum: ::nix::libc::c_int,
285 siginfo: *mut siginfo_t,
286 ucontext: *mut c_void,
287) {
288 use crate::backend::{Architecture, InlineBreakpointType};
289
290 #[cfg(target_arch = "x86_64")]
291 static ARCH: Architecture = Architecture::X64;
292
293 #[cfg(target_arch = "aarch64")]
294 static ARCH: Architecture = Architecture::Aarch64;
295
296 let mut should_unwind = false;
297 let mut unwind_result: Option<Box<RuntimeError>> = None;
298 let get_unwind_result = |uw_result: Option<Box<RuntimeError>>| -> Box<RuntimeError> {
299 uw_result
300 .unwrap_or_else(|| Box::new(RuntimeError::InvokeError(InvokeError::FailedWithNoError)))
301 };
302
303 unsafe {
304 let fault = get_fault_info(siginfo as _, ucontext);
305 let early_return = allocate_and_run(TRAP_STACK_SIZE, || {
306 CURRENT_CODE_VERSIONS.with(|versions| {
307 let versions = versions.borrow();
308 for v in versions.iter() {
309 let magic_size =
310 if let Some(x) = v.runnable_module.get_inline_breakpoint_size(ARCH) {
311 x
312 } else {
313 continue;
314 };
315 let ip = fault.ip.get();
316 let end = v.base + v.msm.total_size;
317 if ip >= v.base && ip < end && ip + magic_size <= end {
318 if let Some(ib) = v.runnable_module.read_inline_breakpoint(
319 ARCH,
320 std::slice::from_raw_parts(ip as *const u8, magic_size),
321 ) {
322 match ib.ty {
323 InlineBreakpointType::Middleware => {
324 let out: Option<Result<(), RuntimeError>> =
325 with_breakpoint_map(|bkpt_map| {
326 bkpt_map.and_then(|x| x.get(&ip)).map(|x| {
327 x(BreakpointInfo {
328 fault: Some(&fault),
329 })
330 })
331 });
332 if let Some(Ok(())) = out {
333 } else if let Some(Err(e)) = out {
334 should_unwind = true;
335 unwind_result = Some(Box::new(e));
336 }
337 }
338 }
339
340 fault.ip.set(ip + magic_size);
341 return true;
342 }
343 break;
344 }
345 }
346 false
347 })
348 });
349 if should_unwind {
350 begin_unsafe_unwind(get_unwind_result(unwind_result));
351 }
352 if early_return {
353 return;
354 }
355
356 should_unwind = allocate_and_run(TRAP_STACK_SIZE, || {
357 let mut is_suspend_signal = false;
358
359 #[cfg(feature = "managed")]
360 WAS_SIGINT_TRIGGERED.with(|x| x.set(false));
361
362 match Signal::from_c_int(signum) {
363 Ok(SIGTRAP) => {
364 let out: Option<Result<(), RuntimeError>> =
366 with_breakpoint_map(|bkpt_map| -> Option<Result<(), RuntimeError>> {
367 bkpt_map.and_then(|x| x.get(&(fault.ip.get()))).map(
368 |x| -> Result<(), RuntimeError> {
369 x(BreakpointInfo {
370 fault: Some(&fault),
371 })
372 },
373 )
374 });
375 match out {
376 Some(Ok(())) => {
377 return false;
378 }
379 Some(Err(e)) => {
380 unwind_result = Some(Box::new(e));
381 return true;
382 }
383 None => {}
384 }
385 }
386 Ok(SIGSEGV) | Ok(SIGBUS) => {
387 if fault.faulting_addr as usize == get_wasm_interrupt_signal_mem() as usize {
388 is_suspend_signal = true;
389 clear_wasm_interrupt();
390 #[cfg(feature = "managed")]
391 if INTERRUPT_SIGNAL_DELIVERED.swap(false, Ordering::SeqCst) {
392 WAS_SIGINT_TRIGGERED.with(|x| x.set(true));
393 }
394 }
395 }
396 _ => {}
397 }
398
399 let ctx: &mut vm::Ctx = &mut **CURRENT_CTX.with(|x| x.get());
406 let es_image = fault
407 .read_stack(None)
408 .expect("fault.read_stack() failed. Broken invariants?");
409
410 if is_suspend_signal {
411 let image = build_instance_image(ctx, es_image);
413 unwind_result = Some(Box::new(RuntimeError::InstanceImage(Box::new(image))));
414 } else {
415 if !es_image.frames.is_empty() {
417 eprintln!(
418 "\n{}",
419 "Wasmer encountered an error while running your WebAssembly program."
420 );
421 es_image.print_backtrace_if_needed();
422 }
423
424 let exc_code = CURRENT_CODE_VERSIONS.with(|versions| {
426 let versions = versions.borrow();
427 for v in versions.iter() {
428 if let Some(table) = v.runnable_module.get_exception_table() {
429 let ip = fault.ip.get();
430 let end = v.base + v.msm.total_size;
431 if ip >= v.base && ip < end {
432 if let Some(exc_code) = table.offset_to_code.get(&(ip - v.base)) {
433 return Some(*exc_code);
434 }
435 }
436 }
437 }
438 None
439 });
440 if let Some(code) = exc_code {
441 unwind_result =
442 Some(Box::new(RuntimeError::InvokeError(InvokeError::TrapCode {
443 code,
444 srcloc: 0,
446 })));
447 }
448 }
449
450 true
451 });
452
453 if should_unwind {
454 begin_unsafe_unwind(get_unwind_result(unwind_result));
455 }
456 }
457}
458
459#[cfg(feature = "managed")]
460extern "C" fn sigint_handler(
461 _signum: ::nix::libc::c_int,
462 _siginfo: *mut siginfo_t,
463 _ucontext: *mut c_void,
464) {
465 if INTERRUPT_SIGNAL_DELIVERED.swap(true, Ordering::SeqCst) {
466 eprintln!("Got another SIGINT before trap is triggered on WebAssembly side, aborting");
467 process::abort();
468 }
469 unsafe {
470 set_wasm_interrupt();
471 }
472}
473
474pub fn ensure_sighandler() {
476 INSTALL_SIGHANDLER.call_once(|| unsafe {
477 install_sighandler();
478 });
479}
480
481static INSTALL_SIGHANDLER: Once = Once::new();
482
483unsafe fn install_sighandler() {
484 let sa_trap = SigAction::new(
485 SigHandler::SigAction(signal_trap_handler),
486 SaFlags::SA_ONSTACK,
487 SigSet::empty(),
488 );
489 sigaction(SIGFPE, &sa_trap).unwrap();
490 sigaction(SIGILL, &sa_trap).unwrap();
491 sigaction(SIGSEGV, &sa_trap).unwrap();
492 sigaction(SIGBUS, &sa_trap).unwrap();
493 sigaction(SIGTRAP, &sa_trap).unwrap();
494
495 #[cfg(feature = "managed")]
496 {
497 let sa_interrupt = SigAction::new(
498 SigHandler::SigAction(sigint_handler),
499 SaFlags::SA_ONSTACK,
500 SigSet::empty(),
501 );
502 sigaction(SIGINT, &sa_interrupt).unwrap();
503 }
504}
505
506#[derive(Debug, Clone)]
507pub struct FaultInfo {
509 pub faulting_addr: *const c_void,
511 pub ip: &'static Cell<usize>,
513 pub known_registers: [Option<u64>; 32],
515}
516
517impl FaultInfo {
518 pub unsafe fn read_stack(&self, max_depth: Option<usize>) -> Option<ExecutionStateImage> {
520 let rsp = self.known_registers[X64Register::GPR(GPR::RSP).to_index().0]?;
521
522 Some(CURRENT_CODE_VERSIONS.with(|versions| {
523 let versions = versions.borrow();
524 read_stack(
525 || versions.iter(),
526 rsp as usize as *const u64,
527 self.known_registers,
528 Some(self.ip.get() as u64),
529 max_depth,
530 )
531 }))
532 }
533}
534
535#[cfg(all(target_os = "freebsd", target_arch = "aarch64"))]
536pub unsafe fn get_fault_info(siginfo: *const c_void, ucontext: *mut c_void) -> FaultInfo {
538 #[repr(C)]
539 pub struct ucontext_t {
540 uc_sigmask: libc::sigset_t,
541 uc_mcontext: mcontext_t,
542 uc_link: *mut ucontext_t,
543 uc_stack: libc::stack_t,
544 uc_flags: i32,
545 __spare__: [i32; 4],
546 }
547 #[repr(C)]
548 pub struct gpregs {
549 gp_x: [u64; 30],
550 gp_lr: u64,
551 gp_sp: u64,
552 gp_elr: u64,
553 gp_spsr: u64,
554 gp_pad: i32,
555 };
556 #[repr(C)]
557 pub struct fpregs {
558 fp_q: [u128; 32],
559 fp_sr: u32,
560 fp_cr: u32,
561 fp_flags: i32,
562 fp_pad: i32,
563 };
564 #[repr(C)]
565 pub struct mcontext_t {
566 mc_gpregs: gpregs,
567 mc_fpregs: fpregs,
568 mc_flags: i32,
569 mc_pad: i32,
570 mc_spare: [u64; 8],
571 }
572
573 let siginfo = siginfo as *const siginfo_t;
574 let si_addr = (*siginfo).si_addr;
575
576 let ucontext = ucontext as *mut ucontext_t;
577 let gregs = &(*ucontext).uc_mcontext.mc_gpregs;
578
579 let mut known_registers: [Option<u64>; 32] = [None; 32];
580
581 known_registers[X64Register::GPR(GPR::R15).to_index().0] = Some(gregs.gp_x[15] as _);
582 known_registers[X64Register::GPR(GPR::R14).to_index().0] = Some(gregs.gp_x[14] as _);
583 known_registers[X64Register::GPR(GPR::R13).to_index().0] = Some(gregs.gp_x[13] as _);
584 known_registers[X64Register::GPR(GPR::R12).to_index().0] = Some(gregs.gp_x[12] as _);
585 known_registers[X64Register::GPR(GPR::R11).to_index().0] = Some(gregs.gp_x[11] as _);
586 known_registers[X64Register::GPR(GPR::R10).to_index().0] = Some(gregs.gp_x[10] as _);
587 known_registers[X64Register::GPR(GPR::R9).to_index().0] = Some(gregs.gp_x[9] as _);
588 known_registers[X64Register::GPR(GPR::R8).to_index().0] = Some(gregs.gp_x[8] as _);
589 known_registers[X64Register::GPR(GPR::RSI).to_index().0] = Some(gregs.gp_x[6] as _);
590 known_registers[X64Register::GPR(GPR::RDI).to_index().0] = Some(gregs.gp_x[7] as _);
591 known_registers[X64Register::GPR(GPR::RDX).to_index().0] = Some(gregs.gp_x[2] as _);
592 known_registers[X64Register::GPR(GPR::RCX).to_index().0] = Some(gregs.gp_x[1] as _);
593 known_registers[X64Register::GPR(GPR::RBX).to_index().0] = Some(gregs.gp_x[3] as _);
594 known_registers[X64Register::GPR(GPR::RAX).to_index().0] = Some(gregs.gp_x[0] as _);
595
596 known_registers[X64Register::GPR(GPR::RBP).to_index().0] = Some(gregs.gp_x[5] as _);
597 known_registers[X64Register::GPR(GPR::RSP).to_index().0] = Some(gregs.gp_x[28] as _);
598
599 FaultInfo {
600 faulting_addr: si_addr as usize as _,
601 ip: std::mem::transmute::<&mut u64, &'static Cell<usize>>(
602 &mut (*ucontext).uc_mcontext.mc_gpregs.gp_elr,
603 ),
604 known_registers,
605 }
606}
607
608#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
609pub unsafe fn get_fault_info(siginfo: *const c_void, ucontext: *mut c_void) -> FaultInfo {
611 use crate::state::x64::XMM;
612 #[repr(C)]
613 pub struct ucontext_t {
614 uc_sigmask: libc::sigset_t,
615 uc_mcontext: mcontext_t,
616 uc_link: *mut ucontext_t,
617 uc_stack: libc::stack_t,
618 uc_flags: i32,
619 __spare__: [i32; 4],
620 }
621 #[repr(C)]
622 pub struct mcontext_t {
623 mc_onstack: u64,
624 mc_rdi: u64,
625 mc_rsi: u64,
626 mc_rdx: u64,
627 mc_rcx: u64,
628 mc_r8: u64,
629 mc_r9: u64,
630 mc_rax: u64,
631 mc_rbx: u64,
632 mc_rbp: u64,
633 mc_r10: u64,
634 mc_r11: u64,
635 mc_r12: u64,
636 mc_r13: u64,
637 mc_r14: u64,
638 mc_r15: u64,
639 mc_trapno: u32,
640 mc_fs: u16,
641 mc_gs: u16,
642 mc_addr: u64,
643 mc_flags: u32,
644 mc_es: u16,
645 mc_ds: u16,
646 mc_err: u64,
647 mc_rip: u64,
648 mc_cs: u64,
649 mc_rflags: u64,
650 mc_rsp: u64,
651 mc_ss: u64,
652 mc_len: i64,
653
654 mc_fpformat: i64,
655 mc_ownedfp: i64,
656 mc_savefpu: *const savefpu,
657 mc_fpstate: [i64; 63], mc_fsbase: u64,
660 mc_gsbase: u64,
661
662 mc_xfpustate: u64,
663 mc_xfpustate_len: u64,
664
665 mc_spare: [i64; 4],
666 }
667 #[repr(C)]
668 pub struct xmmacc {
669 element: [u32; 4],
670 }
671 #[repr(C)]
672 pub struct __envxmm64 {
673 en_cw: u16,
674 en_sw: u16,
675 en_tw: u8,
676 en_zero: u8,
677 en_opcode: u16,
678 en_rip: u64,
679 en_rdp: u64,
680 en_mxcsr: u32,
681 en_mxcsr_mask: u32,
682 }
683 #[repr(C)]
684 pub struct fpacc87 {
685 fp_bytes: [u8; 10],
686 }
687 #[repr(C)]
688 pub struct sv_fp {
689 fp_acc: fpacc87,
690 fp_pad: [u8; 6],
691 }
692 #[repr(C, align(16))]
693 pub struct savefpu {
694 sv_env: __envxmm64,
695 sv_fp_t: [sv_fp; 8],
696 sv_xmm: [xmmacc; 16],
697 sv_pad: [u8; 96],
698 }
699
700 let siginfo = siginfo as *const siginfo_t;
701 let si_addr = (*siginfo).si_addr;
702
703 let ucontext = ucontext as *mut ucontext_t;
704 let gregs = &mut (*ucontext).uc_mcontext;
705
706 fn read_xmm(reg: &xmmacc) -> u64 {
707 (reg.element[0] as u64) | ((reg.element[1] as u64) << 32)
708 }
709
710 let mut known_registers: [Option<u64>; 32] = [None; 32];
711 known_registers[X64Register::GPR(GPR::R15).to_index().0] = Some(gregs.mc_r15);
712 known_registers[X64Register::GPR(GPR::R14).to_index().0] = Some(gregs.mc_r14);
713 known_registers[X64Register::GPR(GPR::R13).to_index().0] = Some(gregs.mc_r13);
714 known_registers[X64Register::GPR(GPR::R12).to_index().0] = Some(gregs.mc_r12);
715 known_registers[X64Register::GPR(GPR::R11).to_index().0] = Some(gregs.mc_r11);
716 known_registers[X64Register::GPR(GPR::R10).to_index().0] = Some(gregs.mc_r10);
717 known_registers[X64Register::GPR(GPR::R9).to_index().0] = Some(gregs.mc_r9);
718 known_registers[X64Register::GPR(GPR::R8).to_index().0] = Some(gregs.mc_r8);
719 known_registers[X64Register::GPR(GPR::RSI).to_index().0] = Some(gregs.mc_rsi);
720 known_registers[X64Register::GPR(GPR::RDI).to_index().0] = Some(gregs.mc_rdi);
721 known_registers[X64Register::GPR(GPR::RDX).to_index().0] = Some(gregs.mc_rdx);
722 known_registers[X64Register::GPR(GPR::RCX).to_index().0] = Some(gregs.mc_rcx);
723 known_registers[X64Register::GPR(GPR::RBX).to_index().0] = Some(gregs.mc_rbx);
724 known_registers[X64Register::GPR(GPR::RAX).to_index().0] = Some(gregs.mc_rax);
725
726 known_registers[X64Register::GPR(GPR::RBP).to_index().0] = Some(gregs.mc_rbp);
727 known_registers[X64Register::GPR(GPR::RSP).to_index().0] = Some(gregs.mc_rsp);
728
729 const _MC_HASFPXSTATE: u32 = 0x4;
732 if (gregs.mc_flags & _MC_HASFPXSTATE) == 0 {
733 let fpregs = &*(*ucontext).uc_mcontext.mc_savefpu;
735 known_registers[X64Register::XMM(XMM::XMM0).to_index().0] =
736 Some(read_xmm(&fpregs.sv_xmm[0]));
737 known_registers[X64Register::XMM(XMM::XMM1).to_index().0] =
738 Some(read_xmm(&fpregs.sv_xmm[1]));
739 known_registers[X64Register::XMM(XMM::XMM2).to_index().0] =
740 Some(read_xmm(&fpregs.sv_xmm[2]));
741 known_registers[X64Register::XMM(XMM::XMM3).to_index().0] =
742 Some(read_xmm(&fpregs.sv_xmm[3]));
743 known_registers[X64Register::XMM(XMM::XMM4).to_index().0] =
744 Some(read_xmm(&fpregs.sv_xmm[4]));
745 known_registers[X64Register::XMM(XMM::XMM5).to_index().0] =
746 Some(read_xmm(&fpregs.sv_xmm[5]));
747 known_registers[X64Register::XMM(XMM::XMM6).to_index().0] =
748 Some(read_xmm(&fpregs.sv_xmm[6]));
749 known_registers[X64Register::XMM(XMM::XMM7).to_index().0] =
750 Some(read_xmm(&fpregs.sv_xmm[7]));
751 known_registers[X64Register::XMM(XMM::XMM8).to_index().0] =
752 Some(read_xmm(&fpregs.sv_xmm[8]));
753 known_registers[X64Register::XMM(XMM::XMM9).to_index().0] =
754 Some(read_xmm(&fpregs.sv_xmm[9]));
755 known_registers[X64Register::XMM(XMM::XMM10).to_index().0] =
756 Some(read_xmm(&fpregs.sv_xmm[10]));
757 known_registers[X64Register::XMM(XMM::XMM11).to_index().0] =
758 Some(read_xmm(&fpregs.sv_xmm[11]));
759 known_registers[X64Register::XMM(XMM::XMM12).to_index().0] =
760 Some(read_xmm(&fpregs.sv_xmm[12]));
761 known_registers[X64Register::XMM(XMM::XMM13).to_index().0] =
762 Some(read_xmm(&fpregs.sv_xmm[13]));
763 known_registers[X64Register::XMM(XMM::XMM14).to_index().0] =
764 Some(read_xmm(&fpregs.sv_xmm[14]));
765 known_registers[X64Register::XMM(XMM::XMM15).to_index().0] =
766 Some(read_xmm(&fpregs.sv_xmm[15]));
767 }
768
769 FaultInfo {
770 faulting_addr: si_addr,
771 ip: std::mem::transmute::<&mut u64, &'static Cell<usize>>(
772 &mut (*ucontext).uc_mcontext.mc_rip,
773 ),
774 known_registers,
775 }
776}
777
778#[cfg(all(
779 any(target_os = "linux", target_os = "android"),
780 target_arch = "aarch64"
781))]
782pub unsafe fn get_fault_info(siginfo: *const c_void, ucontext: *mut c_void) -> FaultInfo {
784 #[allow(dead_code)]
785 #[allow(non_camel_case_types)]
786 #[repr(packed)]
787 struct sigcontext {
788 fault_address: u64,
789 regs: [u64; 31],
790 sp: u64,
791 pc: u64,
792 pstate: u64,
793 reserved: [u8; 4096],
794 }
795
796 #[allow(dead_code)]
797 #[allow(non_camel_case_types)]
798 #[repr(packed)]
799 struct ucontext {
800 unknown: [u8; 176],
801 uc_mcontext: sigcontext,
802 }
803
804 #[allow(dead_code)]
805 #[allow(non_camel_case_types)]
806 #[repr(C)]
807 struct siginfo_t {
808 si_signo: i32,
809 si_errno: i32,
810 si_code: i32,
811 si_addr: u64,
812 }
814
815 let siginfo = siginfo as *const siginfo_t;
816 let si_addr = (*siginfo).si_addr;
817
818 let ucontext = ucontext as *mut ucontext;
819 let gregs = &(*ucontext).uc_mcontext.regs;
820
821 let mut known_registers: [Option<u64>; 32] = [None; 32];
822
823 known_registers[X64Register::GPR(GPR::R15).to_index().0] = Some(gregs[15] as _);
824 known_registers[X64Register::GPR(GPR::R14).to_index().0] = Some(gregs[14] as _);
825 known_registers[X64Register::GPR(GPR::R13).to_index().0] = Some(gregs[13] as _);
826 known_registers[X64Register::GPR(GPR::R12).to_index().0] = Some(gregs[12] as _);
827 known_registers[X64Register::GPR(GPR::R11).to_index().0] = Some(gregs[11] as _);
828 known_registers[X64Register::GPR(GPR::R10).to_index().0] = Some(gregs[10] as _);
829 known_registers[X64Register::GPR(GPR::R9).to_index().0] = Some(gregs[9] as _);
830 known_registers[X64Register::GPR(GPR::R8).to_index().0] = Some(gregs[8] as _);
831 known_registers[X64Register::GPR(GPR::RSI).to_index().0] = Some(gregs[6] as _);
832 known_registers[X64Register::GPR(GPR::RDI).to_index().0] = Some(gregs[7] as _);
833 known_registers[X64Register::GPR(GPR::RDX).to_index().0] = Some(gregs[2] as _);
834 known_registers[X64Register::GPR(GPR::RCX).to_index().0] = Some(gregs[1] as _);
835 known_registers[X64Register::GPR(GPR::RBX).to_index().0] = Some(gregs[3] as _);
836 known_registers[X64Register::GPR(GPR::RAX).to_index().0] = Some(gregs[0] as _);
837
838 known_registers[X64Register::GPR(GPR::RBP).to_index().0] = Some(gregs[5] as _);
839 known_registers[X64Register::GPR(GPR::RSP).to_index().0] = Some(gregs[28] as _);
840
841 FaultInfo {
842 faulting_addr: si_addr as usize as _,
843 ip: std::mem::transmute::<&mut u64, &'static Cell<usize>>(&mut (*ucontext).uc_mcontext.pc),
844 known_registers,
845 }
846}
847
848#[cfg(all(
849 any(target_os = "linux", target_os = "android"),
850 target_arch = "x86_64"
851))]
852pub unsafe fn get_fault_info(siginfo: *const c_void, ucontext: *mut c_void) -> FaultInfo {
854 use libc::{
855 ucontext_t, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_R8, REG_R9, REG_RAX,
856 REG_RBP, REG_RBX, REG_RCX, REG_RDI, REG_RDX, REG_RIP, REG_RSI, REG_RSP,
857 };
858
859 #[cfg(not(target_env = "musl"))]
860 fn read_xmm(reg: &libc::_libc_xmmreg) -> u64 {
861 (reg.element[0] as u64) | ((reg.element[1] as u64) << 32)
862 }
863
864 #[allow(dead_code)]
865 #[repr(C)]
866 struct siginfo_t {
867 si_signo: i32,
868 si_errno: i32,
869 si_code: i32,
870 si_addr: u64,
871 }
873
874 let siginfo = siginfo as *const siginfo_t;
875 let si_addr = (*siginfo).si_addr;
876
877 let ucontext = ucontext as *mut ucontext_t;
878 let gregs = &mut (*ucontext).uc_mcontext.gregs;
879
880 let mut known_registers: [Option<u64>; 32] = [None; 32];
881 known_registers[X64Register::GPR(GPR::R15).to_index().0] = Some(gregs[REG_R15 as usize] as _);
882 known_registers[X64Register::GPR(GPR::R14).to_index().0] = Some(gregs[REG_R14 as usize] as _);
883 known_registers[X64Register::GPR(GPR::R13).to_index().0] = Some(gregs[REG_R13 as usize] as _);
884 known_registers[X64Register::GPR(GPR::R12).to_index().0] = Some(gregs[REG_R12 as usize] as _);
885 known_registers[X64Register::GPR(GPR::R11).to_index().0] = Some(gregs[REG_R11 as usize] as _);
886 known_registers[X64Register::GPR(GPR::R10).to_index().0] = Some(gregs[REG_R10 as usize] as _);
887 known_registers[X64Register::GPR(GPR::R9).to_index().0] = Some(gregs[REG_R9 as usize] as _);
888 known_registers[X64Register::GPR(GPR::R8).to_index().0] = Some(gregs[REG_R8 as usize] as _);
889 known_registers[X64Register::GPR(GPR::RSI).to_index().0] = Some(gregs[REG_RSI as usize] as _);
890 known_registers[X64Register::GPR(GPR::RDI).to_index().0] = Some(gregs[REG_RDI as usize] as _);
891 known_registers[X64Register::GPR(GPR::RDX).to_index().0] = Some(gregs[REG_RDX as usize] as _);
892 known_registers[X64Register::GPR(GPR::RCX).to_index().0] = Some(gregs[REG_RCX as usize] as _);
893 known_registers[X64Register::GPR(GPR::RBX).to_index().0] = Some(gregs[REG_RBX as usize] as _);
894 known_registers[X64Register::GPR(GPR::RAX).to_index().0] = Some(gregs[REG_RAX as usize] as _);
895
896 known_registers[X64Register::GPR(GPR::RBP).to_index().0] = Some(gregs[REG_RBP as usize] as _);
897 known_registers[X64Register::GPR(GPR::RSP).to_index().0] = Some(gregs[REG_RSP as usize] as _);
898
899 #[cfg(not(target_env = "musl"))]
902 {
903 use crate::state::x64::XMM;
904 if !(*ucontext).uc_mcontext.fpregs.is_null() {
905 let fpregs = &*(*ucontext).uc_mcontext.fpregs;
906 known_registers[X64Register::XMM(XMM::XMM0).to_index().0] =
907 Some(read_xmm(&fpregs._xmm[0]));
908 known_registers[X64Register::XMM(XMM::XMM1).to_index().0] =
909 Some(read_xmm(&fpregs._xmm[1]));
910 known_registers[X64Register::XMM(XMM::XMM2).to_index().0] =
911 Some(read_xmm(&fpregs._xmm[2]));
912 known_registers[X64Register::XMM(XMM::XMM3).to_index().0] =
913 Some(read_xmm(&fpregs._xmm[3]));
914 known_registers[X64Register::XMM(XMM::XMM4).to_index().0] =
915 Some(read_xmm(&fpregs._xmm[4]));
916 known_registers[X64Register::XMM(XMM::XMM5).to_index().0] =
917 Some(read_xmm(&fpregs._xmm[5]));
918 known_registers[X64Register::XMM(XMM::XMM6).to_index().0] =
919 Some(read_xmm(&fpregs._xmm[6]));
920 known_registers[X64Register::XMM(XMM::XMM7).to_index().0] =
921 Some(read_xmm(&fpregs._xmm[7]));
922 known_registers[X64Register::XMM(XMM::XMM8).to_index().0] =
923 Some(read_xmm(&fpregs._xmm[8]));
924 known_registers[X64Register::XMM(XMM::XMM9).to_index().0] =
925 Some(read_xmm(&fpregs._xmm[9]));
926 known_registers[X64Register::XMM(XMM::XMM10).to_index().0] =
927 Some(read_xmm(&fpregs._xmm[10]));
928 known_registers[X64Register::XMM(XMM::XMM11).to_index().0] =
929 Some(read_xmm(&fpregs._xmm[11]));
930 known_registers[X64Register::XMM(XMM::XMM12).to_index().0] =
931 Some(read_xmm(&fpregs._xmm[12]));
932 known_registers[X64Register::XMM(XMM::XMM13).to_index().0] =
933 Some(read_xmm(&fpregs._xmm[13]));
934 known_registers[X64Register::XMM(XMM::XMM14).to_index().0] =
935 Some(read_xmm(&fpregs._xmm[14]));
936 known_registers[X64Register::XMM(XMM::XMM15).to_index().0] =
937 Some(read_xmm(&fpregs._xmm[15]));
938 }
939 }
940
941 FaultInfo {
942 faulting_addr: si_addr as usize as _,
943 ip: std::mem::transmute::<&mut i64, &'static Cell<usize>>(&mut gregs[REG_RIP as usize]),
944 known_registers,
945 }
946}
947
948#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
950pub unsafe fn get_fault_info(siginfo: *const c_void, ucontext: *mut c_void) -> FaultInfo {
951 use crate::state::x64::XMM;
952 #[allow(dead_code)]
953 #[repr(C)]
954 struct ucontext_t {
955 uc_onstack: u32,
956 uc_sigmask: u32,
957 uc_stack: libc::stack_t,
958 uc_link: *const ucontext_t,
959 uc_mcsize: u64,
960 uc_mcontext: *mut mcontext_t,
961 }
962 #[repr(C)]
963 struct exception_state {
964 trapno: u16,
965 cpu: u16,
966 err: u32,
967 faultvaddr: u64,
968 }
969 #[repr(C)]
970 struct regs {
971 rax: u64,
972 rbx: u64,
973 rcx: u64,
974 rdx: u64,
975 rdi: u64,
976 rsi: u64,
977 rbp: u64,
978 rsp: u64,
979 r8: u64,
980 r9: u64,
981 r10: u64,
982 r11: u64,
983 r12: u64,
984 r13: u64,
985 r14: u64,
986 r15: u64,
987 rip: u64,
988 rflags: u64,
989 cs: u64,
990 fs: u64,
991 gs: u64,
992 }
993 #[repr(C)]
994 struct fpstate {
995 _cwd: u16,
996 _swd: u16,
997 _ftw: u16,
998 _fop: u16,
999 _rip: u64,
1000 _rdp: u64,
1001 _mxcsr: u32,
1002 _mxcr_mask: u32,
1003 _st: [[u16; 8]; 8],
1004 xmm: [[u64; 2]; 16],
1005 _padding: [u32; 24],
1006 }
1007 #[allow(dead_code)]
1008 #[repr(C)]
1009 struct mcontext_t {
1010 es: exception_state,
1011 ss: regs,
1012 fs: fpstate,
1013 }
1014
1015 let siginfo = siginfo as *const siginfo_t;
1016 let si_addr = (*siginfo).si_addr;
1017
1018 let ucontext = ucontext as *mut ucontext_t;
1019 let ss = &mut (*(*ucontext).uc_mcontext).ss;
1020 let fs = &(*(*ucontext).uc_mcontext).fs;
1021
1022 let mut known_registers: [Option<u64>; 32] = [None; 32];
1023
1024 known_registers[X64Register::GPR(GPR::R15).to_index().0] = Some(ss.r15);
1025 known_registers[X64Register::GPR(GPR::R14).to_index().0] = Some(ss.r14);
1026 known_registers[X64Register::GPR(GPR::R13).to_index().0] = Some(ss.r13);
1027 known_registers[X64Register::GPR(GPR::R12).to_index().0] = Some(ss.r12);
1028 known_registers[X64Register::GPR(GPR::R11).to_index().0] = Some(ss.r11);
1029 known_registers[X64Register::GPR(GPR::R10).to_index().0] = Some(ss.r10);
1030 known_registers[X64Register::GPR(GPR::R9).to_index().0] = Some(ss.r9);
1031 known_registers[X64Register::GPR(GPR::R8).to_index().0] = Some(ss.r8);
1032 known_registers[X64Register::GPR(GPR::RSI).to_index().0] = Some(ss.rsi);
1033 known_registers[X64Register::GPR(GPR::RDI).to_index().0] = Some(ss.rdi);
1034 known_registers[X64Register::GPR(GPR::RDX).to_index().0] = Some(ss.rdx);
1035 known_registers[X64Register::GPR(GPR::RCX).to_index().0] = Some(ss.rcx);
1036 known_registers[X64Register::GPR(GPR::RBX).to_index().0] = Some(ss.rbx);
1037 known_registers[X64Register::GPR(GPR::RAX).to_index().0] = Some(ss.rax);
1038
1039 known_registers[X64Register::GPR(GPR::RBP).to_index().0] = Some(ss.rbp);
1040 known_registers[X64Register::GPR(GPR::RSP).to_index().0] = Some(ss.rsp);
1041
1042 known_registers[X64Register::XMM(XMM::XMM0).to_index().0] = Some(fs.xmm[0][0]);
1043 known_registers[X64Register::XMM(XMM::XMM1).to_index().0] = Some(fs.xmm[1][0]);
1044 known_registers[X64Register::XMM(XMM::XMM2).to_index().0] = Some(fs.xmm[2][0]);
1045 known_registers[X64Register::XMM(XMM::XMM3).to_index().0] = Some(fs.xmm[3][0]);
1046 known_registers[X64Register::XMM(XMM::XMM4).to_index().0] = Some(fs.xmm[4][0]);
1047 known_registers[X64Register::XMM(XMM::XMM5).to_index().0] = Some(fs.xmm[5][0]);
1048 known_registers[X64Register::XMM(XMM::XMM6).to_index().0] = Some(fs.xmm[6][0]);
1049 known_registers[X64Register::XMM(XMM::XMM7).to_index().0] = Some(fs.xmm[7][0]);
1050 known_registers[X64Register::XMM(XMM::XMM8).to_index().0] = Some(fs.xmm[8][0]);
1051 known_registers[X64Register::XMM(XMM::XMM9).to_index().0] = Some(fs.xmm[9][0]);
1052 known_registers[X64Register::XMM(XMM::XMM10).to_index().0] = Some(fs.xmm[10][0]);
1053 known_registers[X64Register::XMM(XMM::XMM11).to_index().0] = Some(fs.xmm[11][0]);
1054 known_registers[X64Register::XMM(XMM::XMM12).to_index().0] = Some(fs.xmm[12][0]);
1055 known_registers[X64Register::XMM(XMM::XMM13).to_index().0] = Some(fs.xmm[13][0]);
1056 known_registers[X64Register::XMM(XMM::XMM14).to_index().0] = Some(fs.xmm[14][0]);
1057 known_registers[X64Register::XMM(XMM::XMM15).to_index().0] = Some(fs.xmm[15][0]);
1058
1059 FaultInfo {
1060 faulting_addr: si_addr,
1061 ip: std::mem::transmute::<&mut u64, &'static Cell<usize>>(&mut ss.rip),
1062 known_registers,
1063 }
1064}