Browse Source

c-api: add wasmtime_trap_code (#3086)

Eventually this should be added to the wasmtime-go binding, addressing
https://github.com/bytecodealliance/wasmtime-go/issues/63.

Added a snippet to examples/interrupt.c to verify that this works as
expected in manual testing.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
pull/3670/head
Stephan Renatus 3 years ago
committed by GitHub
parent
commit
f3b80ece5f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      crates/c-api/include/wasmtime/extern.h
  2. 46
      crates/c-api/include/wasmtime/trap.h
  3. 26
      crates/c-api/src/trap.rs
  4. 8
      crates/wasmtime/src/trap.rs
  5. 4
      examples/interrupt.c

2
crates/c-api/include/wasmtime/extern.h

@ -84,7 +84,7 @@ typedef struct wasmtime_global {
size_t index;
} wasmtime_global_t;
/// \brief Disciminant of #wasmtime_extern_t
/// \brief Discriminant of #wasmtime_extern_t
typedef uint8_t wasmtime_extern_kind_t;
/// \brief Value of #wasmtime_extern_kind_t meaning that #wasmtime_extern_t is a

46
crates/c-api/include/wasmtime/trap.h

@ -13,6 +13,41 @@
extern "C" {
#endif
/**
* \brief Code of an instruction trap.
*
* See #wasmtime_trap_code_enum for possible values.
*/
typedef uint8_t wasmtime_trap_code_t;
/**
* \brief Trap codes for instruction traps.
*/
enum wasmtime_trap_code_enum {
/// The current stack space was exhausted.
WASMTIME_TRAP_CODE_STACK_OVERFLOW,
/// An out-of-bounds memory access.
WASMTIME_TRAP_CODE_MEMORY_OUT_OF_BOUNDS,
/// A wasm atomic operation was presented with a not-naturally-aligned linear-memory address.
WASMTIME_TRAP_CODE_HEAP_MISALIGNED,
/// An out-of-bounds access to a table.
WASMTIME_TRAP_CODE_TABLE_OUT_OF_BOUNDS,
/// Indirect call to a null table entry.
WASMTIME_TRAP_CODE_INDIRECT_CALL_TO_NULL,
/// Signature mismatch on indirect call.
WASMTIME_TRAP_CODE_BAD_SIGNATURE,
/// An integer arithmetic operation caused an overflow.
WASMTIME_TRAP_CODE_INTEGER_OVERFLOW,
/// An integer division by zero.
WASMTIME_TRAP_CODE_INTEGER_DIVISION_BY_ZERO,
/// Failed float-to-int conversion.
WASMTIME_TRAP_CODE_BAD_CONVERSION_TO_INTEGER,
/// Code that was supposed to have been unreachable was reached.
WASMTIME_TRAP_CODE_UNREACHABLE_CODE_REACHED,
/// Execution has potentially run too long and may be interrupted.
WASMTIME_TRAP_CODE_INTERRUPT,
};
/**
* \brief Creates a new trap.
*
@ -23,6 +58,17 @@ extern "C" {
*/
WASM_API_EXTERN wasm_trap_t *wasmtime_trap_new(const char *msg, size_t msg_len);
/**
* \brief Attempts to extract the trap code from this trap.
*
* Returns `true` if the trap is an instruction trap triggered while
* executing Wasm. If `true` is returned then the trap code is returned
* through the `code` pointer. If `false` is returned then this is not
* an instruction trap -- traps can also be created using wasm_trap_new,
* or occur with WASI modules exiting with a certain exit code.
*/
WASM_API_EXTERN bool wasmtime_trap_code(const wasm_trap_t*, wasmtime_trap_code_t *code);
/**
* \brief Attempts to extract a WASI-specific exit status from this trap.
*

26
crates/c-api/src/trap.rs

@ -1,6 +1,6 @@
use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t};
use once_cell::unsync::OnceCell;
use wasmtime::Trap;
use wasmtime::{Trap, TrapCode};
#[repr(C)]
#[derive(Clone)]
@ -91,6 +91,30 @@ pub extern "C" fn wasm_trap_trace(raw: &wasm_trap_t, out: &mut wasm_frame_vec_t)
out.set_buffer(vec);
}
#[no_mangle]
pub extern "C" fn wasmtime_trap_code(raw: &wasm_trap_t, code: &mut i32) -> bool {
match raw.trap.trap_code() {
Some(c) => {
*code = match c {
TrapCode::StackOverflow => 0,
TrapCode::MemoryOutOfBounds => 1,
TrapCode::HeapMisaligned => 2,
TrapCode::TableOutOfBounds => 3,
TrapCode::IndirectCallToNull => 4,
TrapCode::BadSignature => 5,
TrapCode::IntegerOverflow => 6,
TrapCode::IntegerDivisionByZero => 7,
TrapCode::BadConversionToInteger => 8,
TrapCode::UnreachableCodeReached => 9,
TrapCode::Interrupt => 10,
_ => unreachable!(),
};
true
}
None => false,
}
}
#[no_mangle]
pub extern "C" fn wasmtime_trap_exit_status(raw: &wasm_trap_t, status: &mut i32) -> bool {
match raw.trap.i32_exit_status() {

8
crates/wasmtime/src/trap.rs

@ -42,6 +42,14 @@ impl fmt::Display for TrapReason {
/// A trap code describing the reason for a trap.
///
/// All trap instructions have an explicit trap code.
///
/// The code can be accessed from the c-api, where the possible values are translated
/// into enum values defined there:
///
/// * `wasm_trap_code` in c-api/src/trap.rs, and
/// * `wasmtime_trap_code_enum` in c-api/include/wasmtime/trap.h.
///
/// These need to be kept in sync.
#[non_exhaustive]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum TrapCode {

4
examples/interrupt.c

@ -118,6 +118,10 @@ int main() {
printf("Got a trap!...\n");
// `trap` can be inspected here to see the trap message has an interrupt in it
wasmtime_trap_code_t code;
ok = wasmtime_trap_code(trap, &code);
assert(ok);
assert(code == WASMTIME_TRAP_CODE_INTERRUPT);
wasm_trap_delete(trap);
wasmtime_store_delete(store);

Loading…
Cancel
Save