xref: /wasmtime-44.0.1/crates/c-api/src/trap.rs (revision f1225dfd)
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