@@ -2,6 +2,7 @@ use crate::obj::ELF_WASMTIME_TRAPS;
22use object:: write:: { Object , StandardSegment } ;
33use object:: { Bytes , LittleEndian , SectionKind , U32Bytes } ;
44use std:: convert:: TryFrom ;
5+ use std:: fmt;
56use std:: ops:: Range ;
67
78/// A helper structure to build the custom-encoded section of a wasmtime
@@ -26,29 +27,30 @@ pub struct TrapInformation {
2627 pub code_offset : u32 ,
2728
2829 /// Code of the trap.
29- pub trap_code : TrapCode ,
30+ pub trap_code : Trap ,
3031}
3132
32- /// A trap code describing the reason for a trap.
33- ///
34- /// All trap instructions have an explicit trap code.
33+ // The code can be accessed from the c-api, where the possible values are
34+ // translated into enum values defined there:
35+ //
36+ // * `wasm_trap_code` in c-api/src/trap.rs, and
37+ // * `wasmtime_trap_code_enum` in c-api/include/wasmtime/trap.h.
38+ //
39+ // These need to be kept in sync.
40+ #[ non_exhaustive]
3541#[ derive( Clone , Copy , PartialEq , Eq , Debug , Hash ) ]
36- #[ repr ( u8 ) ]
37- pub enum TrapCode {
42+ #[ allow ( missing_docs ) ]
43+ pub enum Trap {
3844 /// The current stack space was exhausted.
3945 StackOverflow ,
4046
41- /// A `heap_addr` instruction detected an out-of-bounds error.
42- ///
43- /// Note that not all out-of-bounds heap accesses are reported this way;
44- /// some are detected by a segmentation fault on the heap unmapped or
45- /// offset-guard pages.
46- HeapOutOfBounds ,
47+ /// An out-of-bounds memory access.
48+ MemoryOutOfBounds ,
4749
4850 /// A wasm atomic operation was presented with a not-naturally-aligned linear-memory address.
4951 HeapMisaligned ,
5052
51- /// A `table_addr` instruction detected an out-of-bounds error .
53+ /// An out-of-bounds access to a table .
5254 TableOutOfBounds ,
5355
5456 /// Indirect call to a null table entry.
@@ -70,15 +72,45 @@ pub enum TrapCode {
7072 UnreachableCodeReached ,
7173
7274 /// Execution has potentially run too long and may be interrupted.
73- /// This trap is resumable.
7475 Interrupt ,
7576
76- /// Used for the component model when functions are lifted/lowered in a way
77- /// that generates a function that always traps.
77+ /// When the `component-model` feature is enabled this trap represents a
78+ /// function that was `canon lift`'d, then `canon lower`'d, then called.
79+ /// This combination of creation of a function in the component model
80+ /// generates a function that always traps and, when called, produces this
81+ /// flavor of trap.
7882 AlwaysTrapAdapter ,
79- // if adding a variant here be sure to update the `check!` macro below
83+
84+ /// When wasm code is configured to consume fuel and it runs out of fuel
85+ /// then this trap will be raised.
86+ OutOfFuel ,
8087}
8188
89+ impl fmt:: Display for Trap {
90+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
91+ use Trap :: * ;
92+
93+ let desc = match self {
94+ StackOverflow => "call stack exhausted" ,
95+ MemoryOutOfBounds => "out of bounds memory access" ,
96+ HeapMisaligned => "misaligned memory access" ,
97+ TableOutOfBounds => "undefined element: out of bounds table access" ,
98+ IndirectCallToNull => "uninitialized element" ,
99+ BadSignature => "indirect call type mismatch" ,
100+ IntegerOverflow => "integer overflow" ,
101+ IntegerDivisionByZero => "integer divide by zero" ,
102+ BadConversionToInteger => "invalid conversion to integer" ,
103+ UnreachableCodeReached => "wasm `unreachable` instruction executed" ,
104+ Interrupt => "interrupt" ,
105+ AlwaysTrapAdapter => "degenerate component adapter called" ,
106+ OutOfFuel => "all fuel consumed by WebAssembly" ,
107+ } ;
108+ write ! ( f, "wasm trap: {desc}" )
109+ }
110+ }
111+
112+ impl std:: error:: Error for Trap { }
113+
82114impl TrapEncodingBuilder {
83115 /// Appends trap information about a function into this section.
84116 ///
@@ -136,7 +168,7 @@ impl TrapEncodingBuilder {
136168/// The `section` provided is expected to have been built by
137169/// `TrapEncodingBuilder` above. Additionally the `offset` should be a relative
138170/// offset within the text section of the compilation image.
139- pub fn lookup_trap_code ( section : & [ u8 ] , offset : usize ) -> Option < TrapCode > {
171+ pub fn lookup_trap_code ( section : & [ u8 ] , offset : usize ) -> Option < Trap > {
140172 let mut section = Bytes ( section) ;
141173 // NB: this matches the encoding written by `append_to` above.
142174 let count = section. read :: < U32Bytes < LittleEndian > > ( ) . ok ( ) ?;
@@ -164,16 +196,16 @@ pub fn lookup_trap_code(section: &[u8], offset: usize) -> Option<TrapCode> {
164196 // FIXME: this could use some sort of derive-like thing to avoid having to
165197 // deduplicate the names here.
166198 //
167- // This simply converts from the `trap`, a `u8`, to the `TrapCode ` enum.
199+ // This simply converts from the `trap`, a `u8`, to the `Trap ` enum.
168200 macro_rules! check {
169- ( $( $name: ident) * ) => ( $( if trap == TrapCode :: $name as u8 {
170- return Some ( TrapCode :: $name) ;
201+ ( $( $name: ident) * ) => ( $( if trap == Trap :: $name as u8 {
202+ return Some ( Trap :: $name) ;
171203 } ) * ) ;
172204 }
173205
174206 check ! {
175207 StackOverflow
176- HeapOutOfBounds
208+ MemoryOutOfBounds
177209 HeapMisaligned
178210 TableOutOfBounds
179211 IndirectCallToNull
@@ -184,6 +216,7 @@ pub fn lookup_trap_code(section: &[u8], offset: usize) -> Option<TrapCode> {
184216 UnreachableCodeReached
185217 Interrupt
186218 AlwaysTrapAdapter
219+ OutOfFuel
187220 }
188221
189222 if cfg ! ( debug_assertions) {
0 commit comments