1 use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t}; 2 use once_cell::unsync::OnceCell; 3 use wasmtime::{Trap, TrapCode}; 4 5 #[repr(C)] 6 #[derive(Clone)] 7 pub struct wasm_trap_t { 8 pub(crate) trap: Trap, 9 } 10 11 wasmtime_c_api_macros::declare_ref!(wasm_trap_t); 12 13 impl wasm_trap_t { 14 pub(crate) fn new(trap: Trap) -> wasm_trap_t { 15 wasm_trap_t { trap: trap } 16 } 17 } 18 19 #[repr(C)] 20 #[derive(Clone)] 21 pub struct wasm_frame_t { 22 trap: Trap, 23 idx: usize, 24 func_name: OnceCell<Option<wasm_name_t>>, 25 module_name: OnceCell<Option<wasm_name_t>>, 26 } 27 28 wasmtime_c_api_macros::declare_own!(wasm_frame_t); 29 30 pub type wasm_message_t = wasm_name_t; 31 32 #[no_mangle] 33 pub extern "C" fn wasm_trap_new( 34 _store: &wasm_store_t, 35 message: &wasm_message_t, 36 ) -> Box<wasm_trap_t> { 37 let message = message.as_slice(); 38 if message[message.len() - 1] != 0 { 39 panic!("wasm_trap_new message stringz expected"); 40 } 41 let message = String::from_utf8_lossy(&message[..message.len() - 1]); 42 Box::new(wasm_trap_t { 43 trap: Trap::new(message), 44 }) 45 } 46 47 #[no_mangle] 48 pub unsafe extern "C" fn wasmtime_trap_new(message: *const u8, len: usize) -> Box<wasm_trap_t> { 49 let bytes = crate::slice_from_raw_parts(message, len); 50 let message = String::from_utf8_lossy(&bytes); 51 Box::new(wasm_trap_t { 52 trap: Trap::new(message), 53 }) 54 } 55 56 #[no_mangle] 57 pub extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out: &mut wasm_message_t) { 58 let mut buffer = Vec::new(); 59 buffer.extend_from_slice(trap.trap.to_string().as_bytes()); 60 buffer.reserve_exact(1); 61 buffer.push(0); 62 out.set_buffer(buffer); 63 } 64 65 #[no_mangle] 66 pub extern "C" fn wasm_trap_origin(raw: &wasm_trap_t) -> Option<Box<wasm_frame_t>> { 67 if raw.trap.trace().len() > 0 { 68 Some(Box::new(wasm_frame_t { 69 trap: raw.trap.clone(), 70 idx: 0, 71 func_name: OnceCell::new(), 72 module_name: OnceCell::new(), 73 })) 74 } else { 75 None 76 } 77 } 78 79 #[no_mangle] 80 pub extern "C" fn wasm_trap_trace(raw: &wasm_trap_t, out: &mut wasm_frame_vec_t) { 81 let vec = (0..raw.trap.trace().len()) 82 .map(|idx| { 83 Some(Box::new(wasm_frame_t { 84 trap: raw.trap.clone(), 85 idx, 86 func_name: OnceCell::new(), 87 module_name: OnceCell::new(), 88 })) 89 }) 90 .collect(); 91 out.set_buffer(vec); 92 } 93 94 #[no_mangle] 95 pub extern "C" fn wasmtime_trap_code(raw: &wasm_trap_t, code: &mut i32) -> bool { 96 match raw.trap.trap_code() { 97 Some(c) => { 98 *code = match c { 99 TrapCode::StackOverflow => 0, 100 TrapCode::MemoryOutOfBounds => 1, 101 TrapCode::HeapMisaligned => 2, 102 TrapCode::TableOutOfBounds => 3, 103 TrapCode::IndirectCallToNull => 4, 104 TrapCode::BadSignature => 5, 105 TrapCode::IntegerOverflow => 6, 106 TrapCode::IntegerDivisionByZero => 7, 107 TrapCode::BadConversionToInteger => 8, 108 TrapCode::UnreachableCodeReached => 9, 109 TrapCode::Interrupt => 10, 110 _ => unreachable!(), 111 }; 112 true 113 } 114 None => false, 115 } 116 } 117 118 #[no_mangle] 119 pub extern "C" fn wasmtime_trap_exit_status(raw: &wasm_trap_t, status: &mut i32) -> bool { 120 match raw.trap.i32_exit_status() { 121 Some(i) => { 122 *status = i; 123 true 124 } 125 None => false, 126 } 127 } 128 129 #[no_mangle] 130 pub extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t) -> u32 { 131 frame.trap.trace()[frame.idx].func_index() 132 } 133 134 #[no_mangle] 135 pub extern "C" fn wasmtime_frame_func_name(frame: &wasm_frame_t) -> Option<&wasm_name_t> { 136 frame 137 .func_name 138 .get_or_init(|| { 139 frame.trap.trace()[frame.idx] 140 .func_name() 141 .map(|s| wasm_name_t::from(s.to_string().into_bytes())) 142 }) 143 .as_ref() 144 } 145 146 #[no_mangle] 147 pub extern "C" fn wasmtime_frame_module_name(frame: &wasm_frame_t) -> Option<&wasm_name_t> { 148 frame 149 .module_name 150 .get_or_init(|| { 151 frame.trap.trace()[frame.idx] 152 .module_name() 153 .map(|s| wasm_name_t::from(s.to_string().into_bytes())) 154 }) 155 .as_ref() 156 } 157 158 #[no_mangle] 159 pub extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t) -> usize { 160 frame.trap.trace()[frame.idx] 161 .func_offset() 162 .unwrap_or(usize::MAX) 163 } 164 165 #[no_mangle] 166 pub extern "C" fn wasm_frame_instance(_arg1: *const wasm_frame_t) -> *mut wasm_instance_t { 167 unimplemented!("wasm_frame_instance") 168 } 169 170 #[no_mangle] 171 pub extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize { 172 frame.trap.trace()[frame.idx] 173 .module_offset() 174 .unwrap_or(usize::MAX) 175 } 176 177 #[no_mangle] 178 pub extern "C" fn wasm_frame_copy(frame: &wasm_frame_t) -> Box<wasm_frame_t> { 179 Box::new(frame.clone()) 180 } 181