History

Initial public commit for Dis VM

arr committed 10 years ago

Commit f95902eNo parent (first commit)40 files · +9358 −0Browse files

Showing the changes to src/vm/vm_exception_handler.cpp (1 of 40 files). Show all

Unified · Split

src/vm/vm_exception_handler.cpp+71−0
@@ -0,0 +1,71 @@
1//
2// Dis VM
3// File: vm_exception_handler.cpp
4// Author: arr
5//
6
7#include <cstdint>
8#include <runtime.h>
9#include <vm_memory.h>
10#include <exceptions.h>
11#include <debug.h>
12
13using namespace disvm;
14using namespace disvm::runtime;
15
16std::tuple<const handler_t *, vm_frame_t *, vm_pc_t> disvm::runtime::find_exception_handler(
17 const vm_stack_t &stack,
18 const vm_module_ref_t &faulting_module,
19 const vm_pc_t faulting_pc,
20 const vm_string_t &exception_id)
21{
22 auto unwind_depth = uint32_t{ 0 };
23 auto current_module = &faulting_module;
24 auto current_pc = faulting_pc;
25 auto current_frame = stack.peek_frame();
26
27 while (current_frame != nullptr)
28 {
29 debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "begin: handler: %d\n", unwind_depth);
30
31 auto &handler_section = current_module->module->handler_section;
32
33 for (auto &handler : handler_section)
34 {
35 // Outside pc range of this handler
36 if (current_pc < handler.begin_pc || handler.end_pc <= current_pc)
37 continue;
38
39 // Find the appropriate exception case
40 for (const auto &exception : handler.exception_table)
41 {
42 auto exception_name = exception.name.get();
43 if (exception_id.compare_to(exception_name) == 0)
44 {
45 debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "end: handler: match: %d\n", unwind_depth);
46 return std::tuple<const handler_t *, vm_frame_t *, std::size_t>{ &handler, current_frame, exception.pc };
47 }
48 else if (exception_name == nullptr && exception.pc != runtime_constants::invalid_program_counter)
49 {
50 debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "end: handler: fallback: %d\n", unwind_depth);
51 return std::tuple<const handler_t *, vm_frame_t *, std::size_t>{ &handler, current_frame, exception.pc };
52 }
53 }
54 }
55
56 // Decrement the frame program counter. See raise instruction for details.
57 current_pc = static_cast<word_t>(current_frame->prev_pc() - 1);
58
59 // Update the current module if it changes walking up the stack.
60 auto prev_mod_ref = current_frame->prev_module_ref();
61 if (prev_mod_ref != nullptr)
62 current_module = prev_mod_ref;
63
64 // Move up the stack.
65 current_frame = current_frame->prev_frame();
66 ++unwind_depth;
67 }
68
69 auto faulting_module_name = faulting_module.module->module_name->str();
70 throw unhandled_user_exception{ exception_id.str(), faulting_module_name, faulting_pc };
71}