Skip to content

Commit ea762c4

Browse files
committed
documenting the exception logic to implement #110
1 parent 2bdd94a commit ea762c4

File tree

1 file changed

+64
-5
lines changed

1 file changed

+64
-5
lines changed

crates/libmwemu/src/emu/exception_handlers.rs

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,72 @@ impl Emu {
3939
/// Support SEH, VEH and UEF
4040
pub fn exception(&mut self, ex_type: ExceptionType) {
4141
/*
42-
Priority: VEH → SEH → UEF
42+
43+
If the handler return the search constant will jump to next handler in this order:
44+
VEH -> SEH1 -> SEH2 -> ... -> SEHn -> UEF -> terminate process
45+
46+
47+
unhandling:
48+
VEH:
49+
- the api RemoveVectoredExceptionHandler removes the handler
50+
SEH:
51+
- automatically when is triggered. SEH point to next SEH.
52+
UEF:
53+
- SetUnhandledExceptionFilter
54+
55+
56+
Responses:
57+
58+
VEH:
59+
- EXCEPTION_CONTINUE_EXECUTION (continue to eip/rip which could be modified)
60+
- EXCEPTION_CONTINUE_SEARCH (jump to next handler SEH -> UEF -> end proces)
61+
62+
SEH:
63+
- EXCEPTION_CONTINUE_EXECUTION (continue and not jump to except)
64+
- EXCEPTION_CONTINUE_SEARCH (jump to next handler SEH -> UEF -> end process)
65+
- EXCEPTION_EXECUTE_HANDLER (jump to except)
66+
67+
UEF:
68+
- EXCEPTION_CONTINUE_EXECUTION (continue to eip/rip which could be modified)
69+
- EXCEPTION_CONTINUE_SEARCH (end process)
70+
71+
64bits SEH:
72+
- is not a stack chain
73+
- search RUNTIME_FUNCTION entry in the .pdata table using BeginAddress ≤ RIP < EndAddress
74+
- in that entry there is the RVA of UNWIND_INFO struct on the .xdata
75+
76+
77+
- at .pdata, 12 bytes of runtime entries:
78+
79+
typedef struct _RUNTIME_FUNCTION {
80+
DWORD BeginAddress;
81+
DWORD EndAddress;
82+
DWORD UnwindInfo; // RVA to UNWIND_INFO at .xdata
83+
} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
84+
85+
- unwind info in the .xdata:
86+
87+
typedef struct _UNWIND_INFO {
88+
UBYTE Version : 3; // always 1
89+
UBYTE Flags : 5; // 0, EHANDLER, UHANDLER, etc.
90+
UBYTE SizeOfProlog;
91+
UBYTE CountOfCodes; // Nº of UNWIND_CODE
92+
UBYTE FrameRegister : 4; // (ie. RBP=5)
93+
UBYTE FrameOffset : 4; // frame scale
94+
UNWIND_CODE UnwindCode[]; // descriptors
95+
// opcional:
96+
// DWORD ExceptionHandler; // RVA to handler if Flags indicate it
97+
// DWORD ExceptionData[]; // extra data for handler
98+
} UNWIND_INFO, *PUNWIND_INFO;
99+
100+
43101
*/
44102

45103

46104
let addr: u64;
47105
let next: u64;
48106

107+
// hook
49108
let handle_exception: bool = match self.hooks.hook_on_exception {
50109
Some(hook_fn) => hook_fn(self, self.regs().rip, ex_type),
51110
None => true,
@@ -61,14 +120,14 @@ impl Emu {
61120
return;
62121
}
63122

123+
// hook replaced handler
64124
if !handle_exception {
65125
log::info!("cancelled exception handling from hook.");
66126
return;
67127
}
68128

129+
// VEH
69130
if self.veh() > 0 {
70-
// VEH
71-
72131
addr = self.veh();
73132

74133
exception::enter(self, ex_type);
@@ -79,16 +138,16 @@ impl Emu {
79138
self.set_eip(addr, false);
80139
}
81140

141+
// SEH
82142
} else if self.seh() > 0 {
83-
// SEH
84-
85143

86144
if self.cfg.is_64bits {
87145
// 64bits seh
88146

89147
unimplemented!("check .pdata if exists");
90148

91149
} else {
150+
92151
// 32bits seh
93152
next = match self.maps.read_dword(self.seh()) {
94153
Some(value) => value.into(),

0 commit comments

Comments
 (0)