1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#![allow(bad_style)]
#![allow(private_no_mangle_fns)]
use alloc::boxed::Box;
use core::any::Any;
use core::intrinsics;
use core::ptr;
use dwarf::eh::{EHContext, EHAction, find_eh_action};
use windows as c;
const ETYPE: c::DWORD = 0b1110_u32 << 28;
const MAGIC: c::DWORD = 0x525354;
const RUST_PANIC: c::DWORD = ETYPE | (1 << 24) | MAGIC;
#[repr(C)]
struct PanicData {
data: Box<Any + Send>,
}
pub unsafe fn panic(data: Box<Any + Send>) -> u32 {
let panic_ctx = Box::new(PanicData { data: data });
let params = [Box::into_raw(panic_ctx) as c::ULONG_PTR];
c::RaiseException(RUST_PANIC,
c::EXCEPTION_NONCONTINUABLE,
params.len() as c::DWORD,
¶ms as *const c::ULONG_PTR);
u32::max_value()
}
pub fn payload() -> *mut u8 {
ptr::null_mut()
}
pub unsafe fn cleanup(ptr: *mut u8) -> Box<Any + Send> {
let panic_ctx = Box::from_raw(ptr as *mut PanicData);
return panic_ctx.data;
}
#[lang = "eh_personality"]
#[cfg(not(test))]
unsafe extern "C" fn rust_eh_personality(exceptionRecord: *mut c::EXCEPTION_RECORD,
establisherFrame: c::LPVOID,
contextRecord: *mut c::CONTEXT,
dispatcherContext: *mut c::DISPATCHER_CONTEXT)
-> c::EXCEPTION_DISPOSITION {
let er = &*exceptionRecord;
let dc = &*dispatcherContext;
if er.ExceptionFlags & c::EXCEPTION_UNWIND == 0 {
if er.ExceptionCode == RUST_PANIC {
if let Some(lpad) = find_landing_pad(dc) {
c::RtlUnwindEx(establisherFrame,
lpad as c::LPVOID,
exceptionRecord,
er.ExceptionInformation[0] as c::LPVOID,
contextRecord,
dc.HistoryTable);
}
}
}
c::ExceptionContinueSearch
}
#[lang = "eh_unwind_resume"]
#[unwind]
unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: c::LPVOID) -> ! {
let params = [panic_ctx as c::ULONG_PTR];
c::RaiseException(RUST_PANIC,
c::EXCEPTION_NONCONTINUABLE,
params.len() as c::DWORD,
¶ms as *const c::ULONG_PTR);
intrinsics::abort();
}
unsafe fn find_landing_pad(dc: &c::DISPATCHER_CONTEXT) -> Option<usize> {
let eh_ctx = EHContext {
ip: dc.ControlPc as usize - 1,
func_start: dc.ImageBase as usize + (*dc.FunctionEntry).BeginAddress as usize,
get_text_start: &|| dc.ImageBase as usize,
get_data_start: &|| unimplemented!(),
};
match find_eh_action(dc.HandlerData, &eh_ctx) {
EHAction::None => None,
EHAction::Cleanup(lpad) |
EHAction::Catch(lpad) => Some(lpad),
EHAction::Terminate => intrinsics::abort(),
}
}