1 /**
2 * \file wasmtime/trap.hh
3 */
4
5 #ifndef WASMTIME_TRAP_HH
6 #define WASMTIME_TRAP_HH
7
8 #include <wasmtime/error.hh>
9 #include <wasmtime/trap.h>
10
11 namespace wasmtime {
12
13 /**
14 * \brief Non-owning reference to a WebAssembly function frame as part of a
15 * `Trace`
16 *
17 * A `FrameRef` represents a WebAssembly function frame on the stack which was
18 * collected as part of a trap.
19 */
20 class FrameRef {
21 wasm_frame_t *frame;
22
23 public:
24 /// Returns the WebAssembly function index of this function, in the original
25 /// module.
func_index() const26 uint32_t func_index() const { return wasm_frame_func_index(frame); }
27 /// Returns the offset, in bytes from the start of the function in the
28 /// original module, to this frame's program counter.
func_offset() const29 size_t func_offset() const { return wasm_frame_func_offset(frame); }
30 /// Returns the offset, in bytes from the start of the original module,
31 /// to this frame's program counter.
module_offset() const32 size_t module_offset() const { return wasm_frame_module_offset(frame); }
33
34 /// Returns the name, if present, associated with this function.
35 ///
36 /// Note that this requires that the `name` section is present in the original
37 /// WebAssembly binary.
func_name() const38 std::optional<std::string_view> func_name() const {
39 const auto *name = wasmtime_frame_func_name(frame);
40 if (name != nullptr) {
41 return std::string_view(name->data, name->size);
42 }
43 return std::nullopt;
44 }
45
46 /// Returns the name, if present, associated with this function's module.
47 ///
48 /// Note that this requires that the `name` section is present in the original
49 /// WebAssembly binary.
module_name() const50 std::optional<std::string_view> module_name() const {
51 const auto *name = wasmtime_frame_module_name(frame);
52 if (name != nullptr) {
53 return std::string_view(name->data, name->size);
54 }
55 return std::nullopt;
56 }
57 };
58
59 /**
60 * \brief An owned vector of `FrameRef` instances representing the WebAssembly
61 * call-stack on a trap.
62 *
63 * This can be used to iterate over the frames of a trap and determine what was
64 * running when a trap happened.
65 */
66 class Trace {
67 friend class Trap;
68 friend class Error;
69
70 wasm_frame_vec_t vec;
71
Trace(wasm_frame_vec_t vec)72 Trace(wasm_frame_vec_t vec) : vec(vec) {}
73
74 public:
~Trace()75 ~Trace() { wasm_frame_vec_delete(&vec); }
76
77 Trace(const Trace &other) = delete;
78 Trace(Trace &&other) = delete;
79 Trace &operator=(const Trace &other) = delete;
80 Trace &operator=(Trace &&other) = delete;
81
82 /// Iterator used to iterate over this trace.
83 typedef const FrameRef *iterator;
84
85 /// Returns the start of iteration
begin() const86 iterator begin() const {
87 return reinterpret_cast<FrameRef *>(&vec.data[0]); // NOLINT
88 }
89 /// Returns the end of iteration
end() const90 iterator end() const {
91 return reinterpret_cast<FrameRef *>(&vec.data[vec.size]); // NOLINT
92 }
93 /// Returns the size of this trace, or how many frames it contains.
size() const94 size_t size() const { return vec.size; }
95 };
96
trace() const97 inline Trace Error::trace() const {
98 wasm_frame_vec_t frames;
99 wasmtime_error_wasm_trace(ptr.get(), &frames);
100 return Trace(frames);
101 }
102
103 /**
104 * \brief Information about a WebAssembly trap.
105 *
106 * Traps can happen during normal wasm execution (such as the `unreachable`
107 * instruction) but they can also happen in host-provided functions to a host
108 * function can simulate raising a trap.
109 *
110 * Traps have a message associated with them as well as a trace of WebAssembly
111 * frames on the stack.
112 */
113 class Trap {
114 WASMTIME_OWN_WRAPPER(Trap, wasm_trap);
115
116 /// Creates a new host-defined trap with the specified message.
Trap(std::string_view msg)117 explicit Trap(std::string_view msg)
118 : Trap(wasmtime_trap_new(msg.data(), msg.size())) {}
119
120 /// Creates a new trap with the given wasmtime trap code.
Trap(wasmtime_trap_code_enum code)121 Trap(wasmtime_trap_code_enum code) : Trap(wasmtime_trap_new_code(code)) {}
122
123 /// Returns the descriptive message associated with this trap.
message() const124 std::string message() const {
125 wasm_byte_vec_t msg;
126 wasm_trap_message(ptr.get(), &msg);
127 std::string ret(msg.data, msg.size - 1);
128 wasm_byte_vec_delete(&msg);
129 return ret;
130 }
131
132 /// Returns the trace of WebAssembly frames associated with this trap.
133 ///
134 /// Note that the `trace` cannot outlive this error object.
trace() const135 Trace trace() const {
136 wasm_frame_vec_t frames;
137 wasm_trap_trace(ptr.get(), &frames);
138 return Trace(frames);
139 }
140
141 /// \brief Returns the trap code associated with this trap, or nothing if
142 /// it was a manually created trap.
code() const143 std::optional<wasmtime_trap_code_t> code() const {
144 wasmtime_trap_code_t code;
145 bool present = wasmtime_trap_code(ptr.get(), &code);
146 if (present)
147 return code;
148 return std::nullopt;
149 }
150 };
151
152 /// Structure used to represent either a `Trap` or an `Error`.
153 struct TrapError {
154 /// Storage for what this trap represents.
155 std::variant<Trap, Error> data;
156
157 /// Creates a new `TrapError` from a `Trap`
TrapErrorwasmtime::TrapError158 TrapError(Trap t) : data(std::move(t)) {}
159 /// Creates a new `TrapError` from an `Error`
TrapErrorwasmtime::TrapError160 TrapError(Error e) : data(std::move(e)) {}
161
162 /// Dispatches internally to return the message associated with this error.
messagewasmtime::TrapError163 std::string message() const {
164 if (const auto *trap = std::get_if<Trap>(&data)) {
165 return trap->message();
166 }
167 if (const auto *error = std::get_if<Error>(&data)) {
168 return std::string(error->message());
169 }
170 std::abort();
171 }
172 };
173
174 /// Result used by functions which can fail because of invariants being violated
175 /// (such as a type error) as well as because of a WebAssembly trap.
176 template <typename T> using TrapResult = Result<T, TrapError>;
177
178 } // namespace wasmtime
179
180 #endif // WASMTIME_TRAP_HH
181