Skip to content

Commit

Permalink
Merge pull request #26 from philipc/unwinder-cleanup
Browse files Browse the repository at this point in the history
Unwinder cleanup
  • Loading branch information
main-- authored Feb 27, 2019
2 parents 3b90740 + 986d8ed commit 313c7ff
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 26 deletions.
16 changes: 8 additions & 8 deletions unwind/src/glue.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
use gimli::X86_64;
use super::{UnwindPayload, StackFrames};
use registers::Registers;

type UnwindPayload<'a> = &'a mut dyn FnMut(Registers);

pub fn registers<F>(mut f: F) where F: FnMut(Registers) {
let mut f = &mut f as UnwindPayload;
unsafe { unwind_trampoline(&mut f) };
}

#[allow(improper_ctypes)] // trampoline just forwards the ptr
extern "C" {
#[cfg(not(feature = "asm"))]
Expand Down Expand Up @@ -106,13 +112,7 @@ pub unsafe extern "C" fn unwind_recorder(payload: *mut UnwindPayload, stack: u64
registers[X86_64::R15] = Some(saved_regs.r15);
registers[X86_64::RA] = Some(*(stack as *const u64));

let mut frames = StackFrames {
unwinder: payload.unwinder,
registers,
state: None,
};

(payload.tracer)(&mut frames);
payload(registers);
}

pub unsafe fn land(regs: &Registers) {
Expand Down
24 changes: 12 additions & 12 deletions unwind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,23 +82,15 @@ impl Default for DwarfUnwinder {
}
}

pub struct UnwindPayload<'a> {
unwinder: &'a mut DwarfUnwinder,
tracer: &'a mut FnMut(&mut StackFrames),
}

impl Unwinder for DwarfUnwinder {
fn trace<F>(&mut self, mut f: F) where F: FnMut(&mut StackFrames) {
let mut payload = UnwindPayload {
unwinder: self,
tracer: &mut f,
};

unsafe { glue::unwind_trampoline(&mut payload) };
glue::registers(|registers| {
let mut frames = StackFrames::new(self, registers);
f(&mut frames)
});
}
}


struct UnwindInfo<R: Reader> {
row: UnwindTableRow<R>,
personality: Option<Pointer>,
Expand Down Expand Up @@ -156,6 +148,14 @@ unsafe fn deref_ptr(ptr: Pointer) -> u64 {


impl<'a> StackFrames<'a> {
pub fn new(unwinder: &'a mut DwarfUnwinder, registers: Registers) -> Self {
StackFrames {
unwinder,
registers,
state: None,
}
}

pub fn registers(&mut self) -> &mut Registers {
&mut self.registers
}
Expand Down
24 changes: 18 additions & 6 deletions unwind/src/libunwind_shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use fallible_iterator::FallibleIterator;
use gimli::X86_64;

use registers::Registers;
use super::{DwarfUnwinder, Unwinder};
use super::{DwarfUnwinder, Unwinder, StackFrames};

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

Expand Down Expand Up @@ -120,19 +124,26 @@ pub unsafe extern "C" fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut
#[no_mangle]
pub unsafe extern "C" fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
(*exception).private_contptr = None;
DwarfUnwinder::default().trace(|frames| unwind_tracer(frames, exception));
::glue::registers(|registers| {
if let Some(registers) = unwind_tracer(registers, exception) {
::glue::land(&registers);
}
});
unreachable!();
}

unsafe fn unwind_tracer(frames: &mut ::StackFrames, exception: *mut _Unwind_Exception) {
unsafe fn unwind_tracer(registers: Registers, exception: *mut _Unwind_Exception) -> Option<Registers> {
let mut unwinder = DwarfUnwinder::default();
let mut frames = StackFrames::new(&mut unwinder, registers);

if let Some(contptr) = (*exception).private_contptr {
loop {
if let Some(frame) = frames.next().unwrap() {
if frames.registers()[X86_64::RSP].unwrap() == contptr {
break;
}
} else {
return;
return None;
}
}
}
Expand All @@ -155,11 +166,12 @@ unsafe fn unwind_tracer(frames: &mut ::StackFrames, exception: *mut _Unwind_Exce
match personality(1, _Unwind_Action::_UA_CLEANUP_PHASE as c_int, (*exception).exception_class,
exception, &mut ctx) {
_Unwind_Reason_Code::_URC_CONTINUE_UNWIND => (),
_Unwind_Reason_Code::_URC_INSTALL_CONTEXT => ::glue::land(frames.registers()),
_Unwind_Reason_Code::_URC_INSTALL_CONTEXT => return Some(frames.registers),
x => panic!("wtf reason code {:?}", x),
}
}
}
None
}

#[no_mangle]
Expand Down

0 comments on commit 313c7ff

Please sign in to comment.