Skip to content

Commit 313c7ff

Browse files
authored
Merge pull request #26 from philipc/unwinder-cleanup
Unwinder cleanup
2 parents 3b90740 + 986d8ed commit 313c7ff

File tree

3 files changed

+38
-26
lines changed

3 files changed

+38
-26
lines changed

unwind/src/glue.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
use gimli::X86_64;
2-
use super::{UnwindPayload, StackFrames};
32
use registers::Registers;
43

4+
type UnwindPayload<'a> = &'a mut dyn FnMut(Registers);
5+
6+
pub fn registers<F>(mut f: F) where F: FnMut(Registers) {
7+
let mut f = &mut f as UnwindPayload;
8+
unsafe { unwind_trampoline(&mut f) };
9+
}
10+
511
#[allow(improper_ctypes)] // trampoline just forwards the ptr
612
extern "C" {
713
#[cfg(not(feature = "asm"))]
@@ -106,13 +112,7 @@ pub unsafe extern "C" fn unwind_recorder(payload: *mut UnwindPayload, stack: u64
106112
registers[X86_64::R15] = Some(saved_regs.r15);
107113
registers[X86_64::RA] = Some(*(stack as *const u64));
108114

109-
let mut frames = StackFrames {
110-
unwinder: payload.unwinder,
111-
registers,
112-
state: None,
113-
};
114-
115-
(payload.tracer)(&mut frames);
115+
payload(registers);
116116
}
117117

118118
pub unsafe fn land(regs: &Registers) {

unwind/src/lib.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,23 +82,15 @@ impl Default for DwarfUnwinder {
8282
}
8383
}
8484

85-
pub struct UnwindPayload<'a> {
86-
unwinder: &'a mut DwarfUnwinder,
87-
tracer: &'a mut FnMut(&mut StackFrames),
88-
}
89-
9085
impl Unwinder for DwarfUnwinder {
9186
fn trace<F>(&mut self, mut f: F) where F: FnMut(&mut StackFrames) {
92-
let mut payload = UnwindPayload {
93-
unwinder: self,
94-
tracer: &mut f,
95-
};
96-
97-
unsafe { glue::unwind_trampoline(&mut payload) };
87+
glue::registers(|registers| {
88+
let mut frames = StackFrames::new(self, registers);
89+
f(&mut frames)
90+
});
9891
}
9992
}
10093

101-
10294
struct UnwindInfo<R: Reader> {
10395
row: UnwindTableRow<R>,
10496
personality: Option<Pointer>,
@@ -156,6 +148,14 @@ unsafe fn deref_ptr(ptr: Pointer) -> u64 {
156148

157149

158150
impl<'a> StackFrames<'a> {
151+
pub fn new(unwinder: &'a mut DwarfUnwinder, registers: Registers) -> Self {
152+
StackFrames {
153+
unwinder,
154+
registers,
155+
state: None,
156+
}
157+
}
158+
159159
pub fn registers(&mut self) -> &mut Registers {
160160
&mut self.registers
161161
}

unwind/src/libunwind_shim.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use fallible_iterator::FallibleIterator;
55
use gimli::X86_64;
66

77
use registers::Registers;
8-
use super::{DwarfUnwinder, Unwinder};
8+
use super::{DwarfUnwinder, Unwinder, StackFrames};
99

1010
#[repr(C)]
1111
#[derive(Copy, Clone, PartialEq)]
@@ -58,7 +58,11 @@ type PersonalityRoutine = extern "C" fn(version: c_int, actions: c_int, class: u
5858
// it never needs any cleanup. Currently this is not true.
5959
#[no_mangle]
6060
pub unsafe extern "C" fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> ! {
61-
DwarfUnwinder::default().trace(|frames| unwind_tracer(frames, exception));
61+
::glue::registers(|registers| {
62+
if let Some(registers) = unwind_tracer(registers, exception) {
63+
::glue::land(&registers);
64+
}
65+
});
6266
unreachable!();
6367
}
6468

@@ -120,19 +124,26 @@ pub unsafe extern "C" fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut
120124
#[no_mangle]
121125
pub unsafe extern "C" fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
122126
(*exception).private_contptr = None;
123-
DwarfUnwinder::default().trace(|frames| unwind_tracer(frames, exception));
127+
::glue::registers(|registers| {
128+
if let Some(registers) = unwind_tracer(registers, exception) {
129+
::glue::land(&registers);
130+
}
131+
});
124132
unreachable!();
125133
}
126134

127-
unsafe fn unwind_tracer(frames: &mut ::StackFrames, exception: *mut _Unwind_Exception) {
135+
unsafe fn unwind_tracer(registers: Registers, exception: *mut _Unwind_Exception) -> Option<Registers> {
136+
let mut unwinder = DwarfUnwinder::default();
137+
let mut frames = StackFrames::new(&mut unwinder, registers);
138+
128139
if let Some(contptr) = (*exception).private_contptr {
129140
loop {
130141
if let Some(frame) = frames.next().unwrap() {
131142
if frames.registers()[X86_64::RSP].unwrap() == contptr {
132143
break;
133144
}
134145
} else {
135-
return;
146+
return None;
136147
}
137148
}
138149
}
@@ -155,11 +166,12 @@ unsafe fn unwind_tracer(frames: &mut ::StackFrames, exception: *mut _Unwind_Exce
155166
match personality(1, _Unwind_Action::_UA_CLEANUP_PHASE as c_int, (*exception).exception_class,
156167
exception, &mut ctx) {
157168
_Unwind_Reason_Code::_URC_CONTINUE_UNWIND => (),
158-
_Unwind_Reason_Code::_URC_INSTALL_CONTEXT => ::glue::land(frames.registers()),
169+
_Unwind_Reason_Code::_URC_INSTALL_CONTEXT => return Some(frames.registers),
159170
x => panic!("wtf reason code {:?}", x),
160171
}
161172
}
162173
}
174+
None
163175
}
164176

165177
#[no_mangle]

0 commit comments

Comments
 (0)