Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/environ/src/fact/traps.rs
1692 views
1
//! Module used to encode failure messages associated with traps in an adapter
2
//! module.
3
//!
4
//! This module is a bit forward-looking in an attempt to help assist with
5
//! debugging issues with adapter modules and their implementation. This isn't
6
//! actually wired up to any decoder at this time and may end up getting deleted
7
//! entirely depending on how things go.
8
//!
9
//! Currently in core wasm the `unreachable` instruction and other traps have no
10
//! ability to assign failure messages with traps. This means that if an adapter
11
//! fails all you have is the program counter into the wasm function, but
12
//! there's not actually any source corresponding to wasm adapters either. This
13
//! module is an attempt to assign optional string messages to `unreachable`
14
//! trap instructions so, when sufficient debugging options are enabled, these
15
//! trap messages could be displayed instead of a bland "unreachable" trap
16
//! message.
17
//!
18
//! This information is currently encoded as a custom section in the wasm
19
//! module.
20
21
use crate::prelude::*;
22
use std::collections::HashMap;
23
use std::fmt;
24
use wasm_encoder::Encode;
25
26
#[derive(Hash, PartialEq, Eq, Copy, Clone)]
27
pub enum Trap {
28
CannotLeave,
29
CannotEnter,
30
UnalignedPointer,
31
InvalidDiscriminant,
32
InvalidChar,
33
ListByteLengthOverflow,
34
StringLengthTooBig,
35
StringLengthOverflow,
36
AssertFailed(&'static str),
37
}
38
39
#[derive(Default)]
40
pub struct TrapSection {
41
trap_to_index: HashMap<Trap, usize>,
42
trap_list: Vec<Trap>,
43
function_traps: Vec<(u32, Vec<(usize, usize)>)>,
44
}
45
46
impl TrapSection {
47
/// Appends a list of traps found within a function.
48
///
49
/// The `func` is the core wasm function index that is being described. The
50
/// `traps` is a list of `(offset, trap)` where `offset` is the offset
51
/// within the function body itself and `trap` is the description of the
52
/// trap of the opcode at that offset.
53
pub fn append(&mut self, func: u32, traps: Vec<(usize, Trap)>) {
54
if traps.is_empty() {
55
return;
56
}
57
58
// Deduplicate `Trap` annotations to avoid repeating the trap string
59
// internally within the custom section.
60
let traps = traps
61
.into_iter()
62
.map(|(offset, trap)| {
63
let trap = *self.trap_to_index.entry(trap).or_insert_with(|| {
64
let idx = self.trap_list.len();
65
self.trap_list.push(trap);
66
idx
67
});
68
(offset, trap)
69
})
70
.collect();
71
self.function_traps.push((func, traps));
72
}
73
74
/// Creates the custom section payload of this section to be encoded into a
75
/// core wasm module.
76
pub fn finish(self) -> Vec<u8> {
77
let mut data = Vec::new();
78
79
// First append all trap messages which will be indexed below.
80
self.trap_list.len().encode(&mut data);
81
for trap in self.trap_list.iter() {
82
trap.to_string().encode(&mut data);
83
}
84
85
// Afterwards encode trap information for all known functions where
86
// offsets are relative to the body of the function index specified and
87
// the trap message is a pointer into the table built above this.
88
self.function_traps.len().encode(&mut data);
89
for (func, traps) in self.function_traps.iter() {
90
func.encode(&mut data);
91
traps.len().encode(&mut data);
92
for (func_offset, trap_message) in traps {
93
func_offset.encode(&mut data);
94
trap_message.encode(&mut data);
95
}
96
}
97
98
data
99
}
100
}
101
102
impl fmt::Display for Trap {
103
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104
match self {
105
Trap::CannotLeave => "cannot leave instance".fmt(f),
106
Trap::CannotEnter => "cannot enter instance".fmt(f),
107
Trap::UnalignedPointer => "pointer not aligned correctly".fmt(f),
108
Trap::InvalidDiscriminant => "invalid variant discriminant".fmt(f),
109
Trap::InvalidChar => "invalid char value specified".fmt(f),
110
Trap::ListByteLengthOverflow => "byte size of list too large for i32".fmt(f),
111
Trap::StringLengthTooBig => "string byte size exceeds maximum".fmt(f),
112
Trap::StringLengthOverflow => "string byte size overflows i32".fmt(f),
113
Trap::AssertFailed(s) => write!(f, "assertion failure: {s}"),
114
}
115
}
116
}
117
118