Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/c-api/src/trap.rs
1692 views
1
use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t};
2
use anyhow::{Error, anyhow};
3
use std::cell::OnceCell;
4
use wasmtime::{Trap, WasmBacktrace};
5
6
#[repr(C)]
7
pub struct wasm_trap_t {
8
pub(crate) error: Error,
9
}
10
11
// This is currently only needed for the `wasm_trap_copy` API in the C API.
12
//
13
// For now the impl here is "fake it til you make it" since this is losing
14
// context by only cloning the error string.
15
impl Clone for wasm_trap_t {
16
fn clone(&self) -> wasm_trap_t {
17
wasm_trap_t {
18
error: anyhow!("{:?}", self.error),
19
}
20
}
21
}
22
23
wasmtime_c_api_macros::declare_ref!(wasm_trap_t);
24
25
impl wasm_trap_t {
26
pub(crate) fn new(error: Error) -> wasm_trap_t {
27
wasm_trap_t { error }
28
}
29
}
30
31
#[repr(C)]
32
#[derive(Clone)]
33
pub struct wasm_frame_t<'a> {
34
trace: &'a WasmBacktrace,
35
idx: usize,
36
func_name: OnceCell<Option<wasm_name_t>>,
37
module_name: OnceCell<Option<wasm_name_t>>,
38
}
39
40
wasmtime_c_api_macros::declare_own!(wasm_frame_t);
41
42
pub type wasm_message_t = wasm_name_t;
43
44
#[unsafe(no_mangle)]
45
pub extern "C" fn wasm_trap_new(
46
_store: &wasm_store_t,
47
message: &wasm_message_t,
48
) -> Box<wasm_trap_t> {
49
let message = message.as_slice();
50
if message[message.len() - 1] != 0 {
51
panic!("wasm_trap_new message stringz expected");
52
}
53
let message = String::from_utf8_lossy(&message[..message.len() - 1]);
54
Box::new(wasm_trap_t {
55
error: Error::msg(message.into_owned()),
56
})
57
}
58
59
#[unsafe(no_mangle)]
60
pub unsafe extern "C" fn wasmtime_trap_new(message: *const u8, len: usize) -> Box<wasm_trap_t> {
61
let bytes = crate::slice_from_raw_parts(message, len);
62
let message = String::from_utf8_lossy(&bytes);
63
Box::new(wasm_trap_t {
64
error: Error::msg(message.into_owned()),
65
})
66
}
67
68
#[unsafe(no_mangle)]
69
pub unsafe extern "C" fn wasmtime_trap_new_code(code: u8) -> Box<wasm_trap_t> {
70
let trap = Trap::from_u8(code).unwrap();
71
Box::new(wasm_trap_t {
72
error: Error::new(trap),
73
})
74
}
75
76
#[unsafe(no_mangle)]
77
pub extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out: &mut wasm_message_t) {
78
let mut buffer = Vec::new();
79
buffer.extend_from_slice(format!("{:?}", trap.error).as_bytes());
80
buffer.reserve_exact(1);
81
buffer.push(0);
82
out.set_buffer(buffer);
83
}
84
85
#[unsafe(no_mangle)]
86
pub extern "C" fn wasm_trap_origin(raw: &wasm_trap_t) -> Option<Box<wasm_frame_t<'_>>> {
87
let trace = match raw.error.downcast_ref::<WasmBacktrace>() {
88
Some(trap) => trap,
89
None => return None,
90
};
91
if trace.frames().len() > 0 {
92
Some(Box::new(wasm_frame_t {
93
trace,
94
idx: 0,
95
func_name: OnceCell::new(),
96
module_name: OnceCell::new(),
97
}))
98
} else {
99
None
100
}
101
}
102
103
#[unsafe(no_mangle)]
104
pub extern "C" fn wasm_trap_trace<'a>(raw: &'a wasm_trap_t, out: &mut wasm_frame_vec_t<'a>) {
105
error_trace(&raw.error, out)
106
}
107
108
pub(crate) fn error_trace<'a>(error: &'a Error, out: &mut wasm_frame_vec_t<'a>) {
109
let trace = match error.downcast_ref::<WasmBacktrace>() {
110
Some(trap) => trap,
111
None => return out.set_buffer(Vec::new()),
112
};
113
let vec = (0..trace.frames().len())
114
.map(|idx| {
115
Some(Box::new(wasm_frame_t {
116
trace,
117
idx,
118
func_name: OnceCell::new(),
119
module_name: OnceCell::new(),
120
}))
121
})
122
.collect();
123
out.set_buffer(vec);
124
}
125
126
#[unsafe(no_mangle)]
127
pub extern "C" fn wasmtime_trap_code(raw: &wasm_trap_t, code: &mut u8) -> bool {
128
let trap = match raw.error.downcast_ref::<Trap>() {
129
Some(trap) => trap,
130
None => return false,
131
};
132
*code = *trap as u8;
133
true
134
}
135
136
#[unsafe(no_mangle)]
137
pub extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t<'_>) -> u32 {
138
frame.trace.frames()[frame.idx].func_index()
139
}
140
141
#[unsafe(no_mangle)]
142
pub extern "C" fn wasmtime_frame_func_name<'a>(
143
frame: &'a wasm_frame_t<'_>,
144
) -> Option<&'a wasm_name_t> {
145
frame
146
.func_name
147
.get_or_init(|| {
148
frame.trace.frames()[frame.idx]
149
.func_name()
150
.map(|s| wasm_name_t::from(s.to_string().into_bytes()))
151
})
152
.as_ref()
153
}
154
155
#[unsafe(no_mangle)]
156
pub extern "C" fn wasmtime_frame_module_name<'a>(
157
frame: &'a wasm_frame_t<'_>,
158
) -> Option<&'a wasm_name_t> {
159
frame
160
.module_name
161
.get_or_init(|| {
162
frame.trace.frames()[frame.idx]
163
.module()
164
.name()
165
.map(|s| wasm_name_t::from(s.to_string().into_bytes()))
166
})
167
.as_ref()
168
}
169
170
#[unsafe(no_mangle)]
171
pub extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t<'_>) -> usize {
172
frame.trace.frames()[frame.idx]
173
.func_offset()
174
.unwrap_or(usize::MAX)
175
}
176
177
#[unsafe(no_mangle)]
178
pub extern "C" fn wasm_frame_instance(_arg1: *const wasm_frame_t<'_>) -> *mut wasm_instance_t {
179
unimplemented!("wasm_frame_instance")
180
}
181
182
#[unsafe(no_mangle)]
183
pub extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t<'_>) -> usize {
184
frame.trace.frames()[frame.idx]
185
.module_offset()
186
.unwrap_or(usize::MAX)
187
}
188
189
#[unsafe(no_mangle)]
190
pub extern "C" fn wasm_frame_copy<'a>(frame: &wasm_frame_t<'a>) -> Box<wasm_frame_t<'a>> {
191
Box::new(frame.clone())
192
}
193
194