Next Generation WASM Microkernel Operating System
at trap_handler 166 lines 6.9 kB view raw
1// Copyright 2025 Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8use core::fmt; 9use cranelift_codegen::ir::TrapCode; 10 11const TRAP_OFFSET: u8 = 1; 12pub const TRAP_INTERNAL_ASSERT: TrapCode = 13 TrapCode::unwrap_user(TrapKind::InternalAssertionFailed as u8 + TRAP_OFFSET); 14pub const TRAP_HEAP_MISALIGNED: TrapCode = 15 TrapCode::unwrap_user(TrapKind::HeapMisaligned as u8 + TRAP_OFFSET); 16pub const TRAP_TABLE_OUT_OF_BOUNDS: TrapCode = 17 TrapCode::unwrap_user(TrapKind::TableOutOfBounds as u8 + TRAP_OFFSET); 18pub const TRAP_INDIRECT_CALL_TO_NULL: TrapCode = 19 TrapCode::unwrap_user(TrapKind::IndirectCallToNull as u8 + TRAP_OFFSET); 20pub const TRAP_BAD_SIGNATURE: TrapCode = 21 TrapCode::unwrap_user(TrapKind::BadSignature as u8 + TRAP_OFFSET); 22pub const TRAP_UNREACHABLE: TrapCode = 23 TrapCode::unwrap_user(TrapKind::UnreachableCodeReached as u8 + TRAP_OFFSET); 24pub const TRAP_NULL_REFERENCE: TrapCode = 25 TrapCode::unwrap_user(TrapKind::NullReference as u8 + TRAP_OFFSET); 26pub const TRAP_I31_NULL_REFERENCE: TrapCode = 27 TrapCode::unwrap_user(TrapKind::NullI31Ref as u8 + TRAP_OFFSET); 28pub const TRAP_ATOMIC_WAIT_NON_SHARED_MEMORY: TrapCode = 29 TrapCode::unwrap_user(TrapKind::AtomicWaitNonSharedMemory as u8 + TRAP_OFFSET); 30 31#[derive(Debug, Copy, Clone)] 32pub enum TrapKind { 33 /// Internal assertion failed 34 InternalAssertionFailed, 35 /// A wasm atomic operation was presented with a not-naturally-aligned linear-memory address. 36 HeapMisaligned, 37 /// Out-of-bounds access to a table. 38 TableOutOfBounds, 39 /// Indirect call to a null table entry. 40 IndirectCallToNull, 41 /// Signature mismatch on indirect call. 42 BadSignature, 43 /// Code that was supposed to have been unreachable was reached. 44 UnreachableCodeReached, 45 /// Call to a null reference. 46 NullReference, 47 /// Attempt to get the bits of a null `i31ref`. 48 NullI31Ref, 49 50 /// The current stack space was exhausted. 51 StackOverflow, 52 /// An out-of-bounds memory access. 53 MemoryOutOfBounds, 54 /// An integer arithmetic operation caused an overflow. 55 IntegerOverflow, 56 /// An integer division by zero. 57 IntegerDivisionByZero, 58 /// Failed float-to-int conversion. 59 BadConversionToInteger, 60 61 /// Used to indicate that a trap was raised by atomic wait operations on non shared memory. 62 AtomicWaitNonSharedMemory, 63} 64 65impl fmt::Display for TrapKind { 66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 67 match self { 68 TrapKind::InternalAssertionFailed => f.write_str("internal assertion failed"), 69 TrapKind::HeapMisaligned => f.write_str("unaligned atomic operation"), 70 TrapKind::TableOutOfBounds => f.write_str("out of bounds table access"), 71 TrapKind::IndirectCallToNull => f.write_str("accessed uninitialized table element"), 72 TrapKind::BadSignature => f.write_str("indirect call signature mismatch"), 73 TrapKind::UnreachableCodeReached => f.write_str("unreachable code executed"), 74 TrapKind::NullReference => f.write_str("null reference called"), 75 TrapKind::NullI31Ref => f.write_str("null i32 reference called"), 76 77 TrapKind::StackOverflow => f.write_str("call stack exhausted"), 78 TrapKind::MemoryOutOfBounds => f.write_str("out of bounds memory access"), 79 TrapKind::IntegerOverflow => f.write_str("integer overflow"), 80 TrapKind::IntegerDivisionByZero => f.write_str("integer divide by zero"), 81 TrapKind::BadConversionToInteger => f.write_str("invalid conversion to integer"), 82 83 TrapKind::AtomicWaitNonSharedMemory => f.write_str("atomic wait on non-shared memory"), 84 } 85 } 86} 87 88impl core::error::Error for TrapKind {} 89 90impl TrapKind { 91 pub(crate) fn from_trap_code(code: TrapCode) -> Option<Self> { 92 match code { 93 TrapCode::STACK_OVERFLOW => Some(TrapKind::StackOverflow), 94 TrapCode::HEAP_OUT_OF_BOUNDS => Some(TrapKind::MemoryOutOfBounds), 95 TrapCode::INTEGER_OVERFLOW => Some(TrapKind::IntegerOverflow), 96 TrapCode::INTEGER_DIVISION_BY_ZERO => Some(TrapKind::IntegerDivisionByZero), 97 TrapCode::BAD_CONVERSION_TO_INTEGER => Some(TrapKind::BadConversionToInteger), 98 99 TRAP_INTERNAL_ASSERT => Some(TrapKind::InternalAssertionFailed), 100 TRAP_HEAP_MISALIGNED => Some(TrapKind::HeapMisaligned), 101 TRAP_TABLE_OUT_OF_BOUNDS => Some(TrapKind::TableOutOfBounds), 102 TRAP_INDIRECT_CALL_TO_NULL => Some(TrapKind::IndirectCallToNull), 103 TRAP_BAD_SIGNATURE => Some(TrapKind::BadSignature), 104 TRAP_UNREACHABLE => Some(TrapKind::UnreachableCodeReached), 105 TRAP_NULL_REFERENCE => Some(TrapKind::NullReference), 106 TRAP_I31_NULL_REFERENCE => Some(TrapKind::NullI31Ref), 107 108 TRAP_ATOMIC_WAIT_NON_SHARED_MEMORY => Some(TrapKind::AtomicWaitNonSharedMemory), 109 110 c => { 111 tracing::warn!("unknown trap code {c}"); 112 None 113 } 114 } 115 } 116} 117 118impl From<TrapKind> for u8 { 119 fn from(value: TrapKind) -> Self { 120 match value { 121 TrapKind::InternalAssertionFailed => 0, 122 TrapKind::HeapMisaligned => 1, 123 TrapKind::TableOutOfBounds => 2, 124 TrapKind::IndirectCallToNull => 3, 125 TrapKind::BadSignature => 4, 126 TrapKind::UnreachableCodeReached => 5, 127 TrapKind::NullReference => 6, 128 TrapKind::NullI31Ref => 7, 129 130 TrapKind::StackOverflow => 8, 131 TrapKind::MemoryOutOfBounds => 9, 132 TrapKind::IntegerOverflow => 10, 133 TrapKind::IntegerDivisionByZero => 11, 134 TrapKind::BadConversionToInteger => 12, 135 136 TrapKind::AtomicWaitNonSharedMemory => 13, 137 } 138 } 139} 140 141impl TryFrom<u8> for TrapKind { 142 type Error = (); 143 144 fn try_from(value: u8) -> Result<Self, Self::Error> { 145 match value { 146 0 => Ok(Self::InternalAssertionFailed), 147 1 => Ok(Self::HeapMisaligned), 148 2 => Ok(Self::TableOutOfBounds), 149 3 => Ok(Self::IndirectCallToNull), 150 4 => Ok(Self::BadSignature), 151 5 => Ok(Self::UnreachableCodeReached), 152 6 => Ok(Self::NullReference), 153 7 => Ok(Self::NullI31Ref), 154 155 8 => Ok(Self::StackOverflow), 156 9 => Ok(Self::MemoryOutOfBounds), 157 10 => Ok(Self::IntegerOverflow), 158 11 => Ok(Self::IntegerDivisionByZero), 159 12 => Ok(Self::BadConversionToInteger), 160 161 13 => Ok(Self::AtomicWaitNonSharedMemory), 162 163 _ => Err(()), 164 } 165 } 166}