Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/c-api/src/trap.rs
3054 views
1
use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t};
2
use std::cell::OnceCell;
3
use wasmtime::{Error, Trap, WasmBacktrace, format_err};
4
5
// Help ensure the Rust enum matches the C one. If any of these assertions
6
// fail, please update both this code and `trap.h` to sync them with
7
// `trap_encoding.rs`.
8
const _: () = {
9
assert!(Trap::StackOverflow as u8 == 0);
10
assert!(Trap::MemoryOutOfBounds as u8 == 1);
11
assert!(Trap::HeapMisaligned as u8 == 2);
12
assert!(Trap::TableOutOfBounds as u8 == 3);
13
assert!(Trap::IndirectCallToNull as u8 == 4);
14
assert!(Trap::BadSignature as u8 == 5);
15
assert!(Trap::IntegerOverflow as u8 == 6);
16
assert!(Trap::IntegerDivisionByZero as u8 == 7);
17
assert!(Trap::BadConversionToInteger as u8 == 8);
18
assert!(Trap::UnreachableCodeReached as u8 == 9);
19
assert!(Trap::Interrupt as u8 == 10);
20
assert!(Trap::OutOfFuel as u8 == 11);
21
assert!(Trap::AtomicWaitNonSharedMemory as u8 == 12);
22
assert!(Trap::NullReference as u8 == 13);
23
assert!(Trap::ArrayOutOfBounds as u8 == 14);
24
assert!(Trap::AllocationTooLarge as u8 == 15);
25
assert!(Trap::CastFailure as u8 == 16);
26
assert!(Trap::CannotEnterComponent as u8 == 17);
27
assert!(Trap::NoAsyncResult as u8 == 18);
28
assert!(Trap::UnhandledTag as u8 == 19);
29
assert!(Trap::ContinuationAlreadyConsumed as u8 == 20);
30
assert!(Trap::DisabledOpcode as u8 == 21);
31
assert!(Trap::AsyncDeadlock as u8 == 22);
32
assert!(Trap::CannotLeaveComponent as u8 == 23);
33
assert!(Trap::CannotBlockSyncTask as u8 == 24);
34
assert!(Trap::InvalidChar as u8 == 25);
35
assert!(Trap::DebugAssertStringEncodingFinished as u8 == 26);
36
assert!(Trap::DebugAssertEqualCodeUnits as u8 == 27);
37
assert!(Trap::DebugAssertPointerAligned as u8 == 28);
38
assert!(Trap::DebugAssertUpperBitsUnset as u8 == 29);
39
assert!(Trap::StringOutOfBounds as u8 == 30);
40
assert!(Trap::ListOutOfBounds as u8 == 31);
41
assert!(Trap::InvalidDiscriminant as u8 == 32);
42
assert!(Trap::UnalignedPointer as u8 == 33);
43
};
44
45
#[repr(C)]
46
pub struct wasm_trap_t {
47
pub(crate) error: Error,
48
}
49
50
// This is currently only needed for the `wasm_trap_copy` API in the C API.
51
//
52
// For now the impl here is "fake it til you make it" since this is losing
53
// context by only cloning the error string.
54
impl Clone for wasm_trap_t {
55
fn clone(&self) -> wasm_trap_t {
56
wasm_trap_t {
57
error: format_err!("{:?}", self.error),
58
}
59
}
60
}
61
62
wasmtime_c_api_macros::declare_ref!(wasm_trap_t);
63
64
impl wasm_trap_t {
65
pub(crate) fn new(error: Error) -> wasm_trap_t {
66
wasm_trap_t { error }
67
}
68
}
69
70
#[repr(C)]
71
#[derive(Clone)]
72
pub struct wasm_frame_t<'a> {
73
trace: &'a WasmBacktrace,
74
idx: usize,
75
func_name: OnceCell<Option<wasm_name_t>>,
76
module_name: OnceCell<Option<wasm_name_t>>,
77
}
78
79
wasmtime_c_api_macros::declare_own!(wasm_frame_t);
80
81
pub type wasm_message_t = wasm_name_t;
82
83
#[unsafe(no_mangle)]
84
pub extern "C" fn wasm_trap_new(
85
_store: &wasm_store_t,
86
message: &wasm_message_t,
87
) -> Box<wasm_trap_t> {
88
let message = message.as_slice();
89
if message[message.len() - 1] != 0 {
90
panic!("wasm_trap_new message stringz expected");
91
}
92
let message = String::from_utf8_lossy(&message[..message.len() - 1]);
93
Box::new(wasm_trap_t {
94
error: Error::msg(message.into_owned()),
95
})
96
}
97
98
#[unsafe(no_mangle)]
99
pub unsafe extern "C" fn wasmtime_trap_new(message: *const u8, len: usize) -> Box<wasm_trap_t> {
100
let bytes = crate::slice_from_raw_parts(message, len);
101
let message = String::from_utf8_lossy(&bytes);
102
Box::new(wasm_trap_t {
103
error: Error::msg(message.into_owned()),
104
})
105
}
106
107
#[unsafe(no_mangle)]
108
pub unsafe extern "C" fn wasmtime_trap_new_code(code: u8) -> Box<wasm_trap_t> {
109
let trap = Trap::from_u8(code).unwrap();
110
Box::new(wasm_trap_t {
111
error: Error::new(trap),
112
})
113
}
114
115
#[unsafe(no_mangle)]
116
pub extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out: &mut wasm_message_t) {
117
let mut buffer = Vec::new();
118
buffer.extend_from_slice(format!("{:?}", trap.error).as_bytes());
119
buffer.reserve_exact(1);
120
buffer.push(0);
121
out.set_buffer(buffer);
122
}
123
124
#[unsafe(no_mangle)]
125
pub extern "C" fn wasm_trap_origin(raw: &wasm_trap_t) -> Option<Box<wasm_frame_t<'_>>> {
126
let trace = match raw.error.downcast_ref::<WasmBacktrace>() {
127
Some(trap) => trap,
128
None => return None,
129
};
130
if trace.frames().len() > 0 {
131
Some(Box::new(wasm_frame_t {
132
trace,
133
idx: 0,
134
func_name: OnceCell::new(),
135
module_name: OnceCell::new(),
136
}))
137
} else {
138
None
139
}
140
}
141
142
#[unsafe(no_mangle)]
143
pub extern "C" fn wasm_trap_trace<'a>(raw: &'a wasm_trap_t, out: &mut wasm_frame_vec_t<'a>) {
144
error_trace(&raw.error, out)
145
}
146
147
pub(crate) fn error_trace<'a>(error: &'a Error, out: &mut wasm_frame_vec_t<'a>) {
148
let trace = match error.downcast_ref::<WasmBacktrace>() {
149
Some(trap) => trap,
150
None => return out.set_buffer(Vec::new()),
151
};
152
let vec = (0..trace.frames().len())
153
.map(|idx| {
154
Some(Box::new(wasm_frame_t {
155
trace,
156
idx,
157
func_name: OnceCell::new(),
158
module_name: OnceCell::new(),
159
}))
160
})
161
.collect();
162
out.set_buffer(vec);
163
}
164
165
#[unsafe(no_mangle)]
166
pub extern "C" fn wasmtime_trap_code(raw: &wasm_trap_t, code: &mut u8) -> bool {
167
let trap = match raw.error.downcast_ref::<Trap>() {
168
Some(trap) => trap,
169
None => return false,
170
};
171
*code = *trap as u8;
172
true
173
}
174
175
#[unsafe(no_mangle)]
176
pub extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t<'_>) -> u32 {
177
frame.trace.frames()[frame.idx].func_index()
178
}
179
180
#[unsafe(no_mangle)]
181
pub extern "C" fn wasmtime_frame_func_name<'a>(
182
frame: &'a wasm_frame_t<'_>,
183
) -> Option<&'a wasm_name_t> {
184
frame
185
.func_name
186
.get_or_init(|| {
187
frame.trace.frames()[frame.idx]
188
.func_name()
189
.map(|s| wasm_name_t::from(s.to_string().into_bytes()))
190
})
191
.as_ref()
192
}
193
194
#[unsafe(no_mangle)]
195
pub extern "C" fn wasmtime_frame_module_name<'a>(
196
frame: &'a wasm_frame_t<'_>,
197
) -> Option<&'a wasm_name_t> {
198
frame
199
.module_name
200
.get_or_init(|| {
201
frame.trace.frames()[frame.idx]
202
.module()
203
.name()
204
.map(|s| wasm_name_t::from(s.to_string().into_bytes()))
205
})
206
.as_ref()
207
}
208
209
#[unsafe(no_mangle)]
210
pub extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t<'_>) -> usize {
211
frame.trace.frames()[frame.idx]
212
.func_offset()
213
.unwrap_or(usize::MAX)
214
}
215
216
#[unsafe(no_mangle)]
217
pub extern "C" fn wasm_frame_instance(_arg1: *const wasm_frame_t<'_>) -> *mut wasm_instance_t {
218
unimplemented!("wasm_frame_instance")
219
}
220
221
#[unsafe(no_mangle)]
222
pub extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t<'_>) -> usize {
223
frame.trace.frames()[frame.idx]
224
.module_offset()
225
.unwrap_or(usize::MAX)
226
}
227
228
#[unsafe(no_mangle)]
229
pub extern "C" fn wasm_frame_copy<'a>(frame: &wasm_frame_t<'a>) -> Box<wasm_frame_t<'a>> {
230
Box::new(frame.clone())
231
}
232
233