Change save_context to invoke callback instead
This commit is contained in:
parent
6dc1ed4d80
commit
a9bec9e719
@ -59,25 +59,34 @@ impl ops::IndexMut<gimli::Register> for Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
pub extern "C-unwind" fn save_context() -> Context {
|
pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), ptr: *mut ()) {
|
||||||
// No need to save caller-saved registers here.
|
// No need to save caller-saved registers here.
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
"
|
"
|
||||||
stp d8, d9, [x8, 0x140]
|
stp x29, x30, [sp, -16]!
|
||||||
stp d10, d11, [x8, 0x150]
|
sub sp, sp, 512
|
||||||
stp d12, d13, [x8, 0x160]
|
mov x8, x0
|
||||||
stp d14, d15, [x8, 0x170]
|
|
||||||
|
|
||||||
str x19, [x8, 0x98]
|
|
||||||
stp x20, x21, [x8, 0xA0]
|
|
||||||
stp x22, x23, [x8, 0xB0]
|
|
||||||
stp x24, x25, [x8, 0xC0]
|
|
||||||
stp x26, x27, [x8, 0xD0]
|
|
||||||
stp x28, x29, [x8, 0xE0]
|
|
||||||
mov x0, sp
|
mov x0, sp
|
||||||
stp x30, x0, [x8, 0xF0]
|
|
||||||
|
|
||||||
|
stp d8, d9, [sp, 0x140]
|
||||||
|
stp d10, d11, [sp, 0x150]
|
||||||
|
stp d12, d13, [sp, 0x160]
|
||||||
|
stp d14, d15, [sp, 0x170]
|
||||||
|
|
||||||
|
str x19, [sp, 0x98]
|
||||||
|
stp x20, x21, [sp, 0xA0]
|
||||||
|
stp x22, x23, [sp, 0xB0]
|
||||||
|
stp x24, x25, [sp, 0xC0]
|
||||||
|
stp x26, x27, [sp, 0xD0]
|
||||||
|
stp x28, x29, [sp, 0xE0]
|
||||||
|
add x2, sp, 528
|
||||||
|
stp x30, x2, [sp, 0xF0]
|
||||||
|
|
||||||
|
blr x8
|
||||||
|
|
||||||
|
add sp, sp, 512
|
||||||
|
ldp x29, x30, [sp], 16
|
||||||
ret
|
ret
|
||||||
",
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
|
@ -61,39 +61,39 @@ impl ops::IndexMut<gimli::Register> for Context {
|
|||||||
macro_rules! code {
|
macro_rules! code {
|
||||||
(save_gp) => {
|
(save_gp) => {
|
||||||
"
|
"
|
||||||
sw x0, 0x00(a0)
|
sw x0, 0x00(sp)
|
||||||
sw ra, 0x04(a0)
|
sw ra, 0x04(sp)
|
||||||
sw sp, 0x08(a0)
|
sw t0, 0x08(sp)
|
||||||
sw gp, 0x0C(a0)
|
sw gp, 0x0C(sp)
|
||||||
sw tp, 0x10(a0)
|
sw tp, 0x10(sp)
|
||||||
sw s0, 0x20(a0)
|
sw s0, 0x20(sp)
|
||||||
sw s1, 0x24(a0)
|
sw s1, 0x24(sp)
|
||||||
sw s2, 0x48(a0)
|
sw s2, 0x48(sp)
|
||||||
sw s3, 0x4C(a0)
|
sw s3, 0x4C(sp)
|
||||||
sw s4, 0x50(a0)
|
sw s4, 0x50(sp)
|
||||||
sw s5, 0x54(a0)
|
sw s5, 0x54(sp)
|
||||||
sw s6, 0x58(a0)
|
sw s6, 0x58(sp)
|
||||||
sw s7, 0x5C(a0)
|
sw s7, 0x5C(sp)
|
||||||
sw s8, 0x60(a0)
|
sw s8, 0x60(sp)
|
||||||
sw s9, 0x64(a0)
|
sw s9, 0x64(sp)
|
||||||
sw s10, 0x68(a0)
|
sw s10, 0x68(sp)
|
||||||
sw s11, 0x6C(a0)
|
sw s11, 0x6C(sp)
|
||||||
"
|
"
|
||||||
};
|
};
|
||||||
(save_fp) => {
|
(save_fp) => {
|
||||||
"
|
"
|
||||||
fsd fs0, 0xC0(a0)
|
fsd fs0, 0xC0(sp)
|
||||||
fsd fs1, 0xC8(a0)
|
fsd fs1, 0xC8(sp)
|
||||||
fsd fs2, 0x110(a0)
|
fsd fs2, 0x110(sp)
|
||||||
fsd fs3, 0x118(a0)
|
fsd fs3, 0x118(sp)
|
||||||
fsd fs4, 0x120(a0)
|
fsd fs4, 0x120(sp)
|
||||||
fsd fs5, 0x128(a0)
|
fsd fs5, 0x128(sp)
|
||||||
fsd fs6, 0x130(a0)
|
fsd fs6, 0x130(sp)
|
||||||
fsd fs7, 0x138(a0)
|
fsd fs7, 0x138(sp)
|
||||||
fsd fs8, 0x140(a0)
|
fsd fs8, 0x140(sp)
|
||||||
fsd fs9, 0x148(a0)
|
fsd fs9, 0x148(sp)
|
||||||
fsd fs10, 0x150(a0)
|
fsd fs10, 0x150(sp)
|
||||||
fsd fs11, 0x158(a0)
|
fsd fs11, 0x158(sp)
|
||||||
"
|
"
|
||||||
};
|
};
|
||||||
(restore_gp) => {
|
(restore_gp) => {
|
||||||
@ -169,18 +169,48 @@ macro_rules! code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
pub extern "C-unwind" fn save_context() -> Context {
|
pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), ptr: *mut ()) {
|
||||||
// No need to save caller-saved registers here.
|
// No need to save caller-saved registers here.
|
||||||
#[cfg(target_feature = "d")]
|
#[cfg(target_feature = "d")]
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
concat!(code!(save_gp), code!(save_fp), "ret"),
|
"
|
||||||
|
mv t0, sp
|
||||||
|
add sp, sp, -0x188
|
||||||
|
sw ra, 0x180(sp)
|
||||||
|
",
|
||||||
|
code!(save_gp),
|
||||||
|
code!(save_fp),
|
||||||
|
"
|
||||||
|
mv t0, a0
|
||||||
|
mv a0, sp
|
||||||
|
jalr t0
|
||||||
|
lw ra, 0x180(sp)
|
||||||
|
add sp, sp, 0x188
|
||||||
|
ret
|
||||||
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[cfg(not(target_feature = "d"))]
|
#[cfg(not(target_feature = "d"))]
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(concat!(code!(save_gp), "ret"), options(noreturn));
|
asm!(
|
||||||
|
"
|
||||||
|
mv t0, sp
|
||||||
|
add sp, sp, -0x88
|
||||||
|
sw ra, 0x80(sp)
|
||||||
|
",
|
||||||
|
code!(save_gp),
|
||||||
|
"
|
||||||
|
mv t0, a0
|
||||||
|
mv a0, sp
|
||||||
|
jalr t0
|
||||||
|
lw ra, 0x80(sp)
|
||||||
|
add sp, sp, 0x88
|
||||||
|
ret
|
||||||
|
",
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,14 +219,23 @@ pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! {
|
|||||||
#[cfg(target_feature = "d")]
|
#[cfg(target_feature = "d")]
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
concat!(code!(restore_fp), code!(restore_gp), "lw a0, 0x28(a0)\nret"),
|
code!(restore_fp),
|
||||||
|
code!(restore_gp),
|
||||||
|
"
|
||||||
|
lw a0, 0x28(a0)
|
||||||
|
ret
|
||||||
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[cfg(not(target_feature = "d"))]
|
#[cfg(not(target_feature = "d"))]
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
concat!(code!(restore_gp), "lw a0, 0x28(a0)\nret"),
|
code!(restore_gp),
|
||||||
|
"
|
||||||
|
lw a0, 0x28(a0)
|
||||||
|
ret
|
||||||
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -61,39 +61,39 @@ impl ops::IndexMut<gimli::Register> for Context {
|
|||||||
macro_rules! code {
|
macro_rules! code {
|
||||||
(save_gp) => {
|
(save_gp) => {
|
||||||
"
|
"
|
||||||
sd x0, 0x00(a0)
|
sd x0, 0x00(sp)
|
||||||
sd ra, 0x08(a0)
|
sd ra, 0x08(sp)
|
||||||
sd sp, 0x10(a0)
|
sd t0, 0x10(sp)
|
||||||
sd gp, 0x18(a0)
|
sd gp, 0x18(sp)
|
||||||
sd tp, 0x20(a0)
|
sd tp, 0x20(sp)
|
||||||
sd s0, 0x40(a0)
|
sd s0, 0x40(sp)
|
||||||
sd s1, 0x48(a0)
|
sd s1, 0x48(sp)
|
||||||
sd s2, 0x90(a0)
|
sd s2, 0x90(sp)
|
||||||
sd s3, 0x98(a0)
|
sd s3, 0x98(sp)
|
||||||
sd s4, 0xA0(a0)
|
sd s4, 0xA0(sp)
|
||||||
sd s5, 0xA8(a0)
|
sd s5, 0xA8(sp)
|
||||||
sd s6, 0xB0(a0)
|
sd s6, 0xB0(sp)
|
||||||
sd s7, 0xB8(a0)
|
sd s7, 0xB8(sp)
|
||||||
sd s8, 0xC0(a0)
|
sd s8, 0xC0(sp)
|
||||||
sd s9, 0xC8(a0)
|
sd s9, 0xC8(sp)
|
||||||
sd s10, 0xD0(a0)
|
sd s10, 0xD0(sp)
|
||||||
sd s11, 0xD8(a0)
|
sd s11, 0xD8(sp)
|
||||||
"
|
"
|
||||||
};
|
};
|
||||||
(save_fp) => {
|
(save_fp) => {
|
||||||
"
|
"
|
||||||
fsd fs0, 0x140(a0)
|
fsd fs0, 0x140(sp)
|
||||||
fsd fs1, 0x148(a0)
|
fsd fs1, 0x148(sp)
|
||||||
fsd fs2, 0x190(a0)
|
fsd fs2, 0x190(sp)
|
||||||
fsd fs3, 0x198(a0)
|
fsd fs3, 0x198(sp)
|
||||||
fsd fs4, 0x1A0(a0)
|
fsd fs4, 0x1A0(sp)
|
||||||
fsd fs5, 0x1A8(a0)
|
fsd fs5, 0x1A8(sp)
|
||||||
fsd fs6, 0x1B0(a0)
|
fsd fs6, 0x1B0(sp)
|
||||||
fsd fs7, 0x1B8(a0)
|
fsd fs7, 0x1B8(sp)
|
||||||
fsd fs8, 0x1C0(a0)
|
fsd fs8, 0x1C0(sp)
|
||||||
fsd fs9, 0x1C8(a0)
|
fsd fs9, 0x1C8(sp)
|
||||||
fsd fs10, 0x1D0(a0)
|
fsd fs10, 0x1D0(sp)
|
||||||
fsd fs11, 0x1D8(a0)
|
fsd fs11, 0x1D8(sp)
|
||||||
"
|
"
|
||||||
};
|
};
|
||||||
(restore_gp) => {
|
(restore_gp) => {
|
||||||
@ -169,18 +169,48 @@ macro_rules! code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
pub extern "C-unwind" fn save_context() -> Context {
|
pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), ptr: *mut ()) {
|
||||||
// No need to save caller-saved registers here.
|
// No need to save caller-saved registers here.
|
||||||
#[cfg(target_feature = "d")]
|
#[cfg(target_feature = "d")]
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
concat!(code!(save_gp), code!(save_fp), "ret"),
|
"
|
||||||
|
mv t0, sp
|
||||||
|
add sp, sp, -0x210
|
||||||
|
sd ra, 0x200(sp)
|
||||||
|
",
|
||||||
|
code!(save_gp),
|
||||||
|
code!(save_fp),
|
||||||
|
"
|
||||||
|
mv t0, a0
|
||||||
|
mv a0, sp
|
||||||
|
jalr t0
|
||||||
|
ld ra, 0x200(sp)
|
||||||
|
add sp, sp, 0x210
|
||||||
|
ret
|
||||||
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[cfg(not(target_feature = "d"))]
|
#[cfg(not(target_feature = "d"))]
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(concat!(code!(save_gp), "ret"), options(noreturn));
|
asm!(
|
||||||
|
"
|
||||||
|
mv t0, sp
|
||||||
|
add sp, sp, -0x110
|
||||||
|
sd ra, 0x100(sp)
|
||||||
|
",
|
||||||
|
code!(save_gp),
|
||||||
|
"
|
||||||
|
mv t0, a0
|
||||||
|
mv a0, sp
|
||||||
|
jalr t0
|
||||||
|
ld ra, 0x100(sp)
|
||||||
|
add sp, sp, 0x110
|
||||||
|
ret
|
||||||
|
",
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,14 +219,23 @@ pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! {
|
|||||||
#[cfg(target_feature = "d")]
|
#[cfg(target_feature = "d")]
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
concat!(code!(restore_fp), code!(restore_gp), "ld a0, 0x50(a0)\nret"),
|
code!(restore_fp),
|
||||||
|
code!(restore_gp),
|
||||||
|
"
|
||||||
|
ld a0, 0x50(a0)
|
||||||
|
ret
|
||||||
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[cfg(not(target_feature = "d"))]
|
#[cfg(not(target_feature = "d"))]
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
concat!(code!(restore_gp), "ld a0, 0x50(a0)\nret"),
|
code!(restore_gp),
|
||||||
|
"
|
||||||
|
ld a0, 0x50(a0)
|
||||||
|
ret
|
||||||
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -56,28 +56,40 @@ impl ops::IndexMut<gimli::Register> for Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
pub extern "C-unwind" fn save_context() -> Context {
|
pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), ptr: *mut ()) {
|
||||||
// No need to save caller-saved registers here.
|
// No need to save caller-saved registers here.
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
"
|
"
|
||||||
mov eax, [esp + 4]
|
sub esp, 44
|
||||||
mov [eax + 4], ecx
|
|
||||||
mov [eax + 8], edx
|
mov [esp + 4], ecx
|
||||||
mov [eax + 12], ebx
|
mov [esp + 8], edx
|
||||||
mov [eax + 20], ebp
|
mov [esp + 12], ebx
|
||||||
mov [eax + 24], esi
|
|
||||||
mov [eax + 28], edi
|
|
||||||
|
|
||||||
/* Adjust the stack to account for the return address */
|
/* Adjust the stack to account for the return address */
|
||||||
lea edx, [esp + 4]
|
lea eax, [esp + 48]
|
||||||
mov [eax + 16], edx
|
mov [esp + 16], eax
|
||||||
|
|
||||||
mov edx, [esp]
|
mov [esp + 20], ebp
|
||||||
mov [eax + 32], edx
|
mov [esp + 24], esi
|
||||||
stmxcsr [eax + 36]
|
mov [esp + 28], edi
|
||||||
fnstcw [eax + 40]
|
|
||||||
ret 4
|
/* Return address */
|
||||||
|
mov eax, [esp + 44]
|
||||||
|
mov [esp + 32], eax
|
||||||
|
|
||||||
|
stmxcsr [esp + 36]
|
||||||
|
fnstcw [esp + 40]
|
||||||
|
|
||||||
|
mov eax, [esp + 52]
|
||||||
|
mov ecx, esp
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
call [esp + 56]
|
||||||
|
|
||||||
|
add esp, 52
|
||||||
|
ret
|
||||||
",
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
);
|
);
|
||||||
|
@ -58,27 +58,35 @@ impl ops::IndexMut<gimli::Register> for Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
pub extern "C-unwind" fn save_context() -> Context {
|
pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), ptr: *mut ()) {
|
||||||
// No need to save caller-saved registers here.
|
// No need to save caller-saved registers here.
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!(
|
asm!(
|
||||||
"
|
"
|
||||||
mov rax, rdi
|
sub rsp, 0x98
|
||||||
mov [rax + 0x18], rbx
|
mov [rsp + 0x18], rbx
|
||||||
mov [rax + 0x30], rbp
|
mov [rsp + 0x30], rbp
|
||||||
|
|
||||||
/* Adjust the stack to account for the return address */
|
/* Adjust the stack to account for the return address */
|
||||||
lea rdi, [rsp + 8]
|
lea rax, [rsp + 0xA0]
|
||||||
mov [rax + 0x38], rdi
|
mov [rsp + 0x38], rax
|
||||||
|
|
||||||
mov [rax + 0x60], r12
|
mov [rsp + 0x60], r12
|
||||||
mov [rax + 0x68], r13
|
mov [rsp + 0x68], r13
|
||||||
mov [rax + 0x70], r14
|
mov [rsp + 0x70], r14
|
||||||
mov [rax + 0x78], r15
|
mov [rsp + 0x78], r15
|
||||||
mov rdx, [rsp]
|
|
||||||
mov [rax + 0x80], rdx
|
/* Return address */
|
||||||
stmxcsr [rax + 0x88]
|
mov rax, [rsp + 0x98]
|
||||||
fnstcw [rax + 0x90]
|
mov [rsp + 0x80], rax
|
||||||
|
|
||||||
|
stmxcsr [rsp + 0x88]
|
||||||
|
fnstcw [rsp + 0x90]
|
||||||
|
|
||||||
|
mov rax, rdi
|
||||||
|
mov rdi, rsp
|
||||||
|
call rax
|
||||||
|
add rsp, 0x98
|
||||||
ret
|
ret
|
||||||
",
|
",
|
||||||
options(noreturn)
|
options(noreturn)
|
||||||
|
@ -16,6 +16,33 @@ use frame::Frame;
|
|||||||
#[cfg(feature = "fde-custom")]
|
#[cfg(feature = "fde-custom")]
|
||||||
pub use find_fde::custom_eh_frame_finder;
|
pub use find_fde::custom_eh_frame_finder;
|
||||||
|
|
||||||
|
// Helper function to turn `save_context` which takes function pointer to a closure-taking function.
|
||||||
|
fn with_context<T, F: FnOnce(&mut Context) -> T>(f: F) -> T {
|
||||||
|
use core::mem::ManuallyDrop;
|
||||||
|
|
||||||
|
union Data<T, F> {
|
||||||
|
f: ManuallyDrop<F>,
|
||||||
|
t: ManuallyDrop<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" fn delegate<T, F: FnOnce(&mut Context) -> T>(ctx: &mut Context, ptr: *mut ()) {
|
||||||
|
// SAFETY: This function is called exactly once; it extracts the function, call it and
|
||||||
|
// store the return value. This function is `extern "C"` so we don't need to worry about
|
||||||
|
// unwinding past it.
|
||||||
|
unsafe {
|
||||||
|
let data = &mut *ptr.cast::<Data<T, F>>();
|
||||||
|
let t = ManuallyDrop::take(&mut data.f)(ctx);
|
||||||
|
data.t = ManuallyDrop::new(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut data = Data {
|
||||||
|
f: ManuallyDrop::new(f),
|
||||||
|
};
|
||||||
|
save_context(delegate::<T, F>, ptr::addr_of_mut!(data).cast());
|
||||||
|
unsafe { ManuallyDrop::into_inner(data.t) }
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct UnwindException {
|
pub struct UnwindException {
|
||||||
pub exception_class: u64,
|
pub exception_class: u64,
|
||||||
@ -125,53 +152,52 @@ macro_rules! try2 {
|
|||||||
pub extern "C-unwind" fn _Unwind_RaiseException(
|
pub extern "C-unwind" fn _Unwind_RaiseException(
|
||||||
exception: &mut UnwindException,
|
exception: &mut UnwindException,
|
||||||
) -> UnwindReasonCode {
|
) -> UnwindReasonCode {
|
||||||
let saved_ctx = save_context();
|
with_context(|saved_ctx| {
|
||||||
|
// Phase 1: Search for handler
|
||||||
|
let mut ctx = saved_ctx.clone();
|
||||||
|
let mut signal = false;
|
||||||
|
loop {
|
||||||
|
if let Some(frame) = try1!(Frame::from_context(&ctx, signal)) {
|
||||||
|
if let Some(personality) = frame.personality() {
|
||||||
|
let result = personality(
|
||||||
|
1,
|
||||||
|
UnwindAction::SEARCH_PHASE,
|
||||||
|
exception.exception_class,
|
||||||
|
exception,
|
||||||
|
&mut UnwindContext {
|
||||||
|
frame: Some(&frame),
|
||||||
|
ctx: &mut ctx,
|
||||||
|
signal,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Phase 1: Search for handler
|
match result {
|
||||||
let mut ctx = saved_ctx.clone();
|
UnwindReasonCode::CONTINUE_UNWIND => (),
|
||||||
let mut signal = false;
|
UnwindReasonCode::HANDLER_FOUND => {
|
||||||
loop {
|
break;
|
||||||
if let Some(frame) = try1!(Frame::from_context(&ctx, signal)) {
|
}
|
||||||
if let Some(personality) = frame.personality() {
|
_ => return UnwindReasonCode::FATAL_PHASE1_ERROR,
|
||||||
let result = personality(
|
|
||||||
1,
|
|
||||||
UnwindAction::SEARCH_PHASE,
|
|
||||||
exception.exception_class,
|
|
||||||
exception,
|
|
||||||
&mut UnwindContext {
|
|
||||||
frame: Some(&frame),
|
|
||||||
ctx: &mut ctx,
|
|
||||||
signal,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
match result {
|
|
||||||
UnwindReasonCode::CONTINUE_UNWIND => (),
|
|
||||||
UnwindReasonCode::HANDLER_FOUND => {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
_ => return UnwindReasonCode::FATAL_PHASE1_ERROR,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx = try1!(frame.unwind(&ctx));
|
||||||
|
signal = frame.is_signal_trampoline();
|
||||||
|
} else {
|
||||||
|
return UnwindReasonCode::END_OF_STACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = try1!(frame.unwind(&ctx));
|
|
||||||
signal = frame.is_signal_trampoline();
|
|
||||||
} else {
|
|
||||||
return UnwindReasonCode::END_OF_STACK;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Disambiguate normal frame and signal frame.
|
// Disambiguate normal frame and signal frame.
|
||||||
let handler_cfa = ctx[Arch::SP] - signal as usize;
|
let handler_cfa = ctx[Arch::SP] - signal as usize;
|
||||||
exception.private_1 = None;
|
exception.private_1 = None;
|
||||||
exception.private_2 = handler_cfa;
|
exception.private_2 = handler_cfa;
|
||||||
|
|
||||||
let mut ctx = saved_ctx;
|
let code = raise_exception_phase2(exception, saved_ctx, handler_cfa);
|
||||||
let code = raise_exception_phase2(exception, &mut ctx, handler_cfa);
|
match code {
|
||||||
match code {
|
UnwindReasonCode::INSTALL_CONTEXT => unsafe { restore_context(saved_ctx) },
|
||||||
UnwindReasonCode::INSTALL_CONTEXT => unsafe { restore_context(&ctx) },
|
_ => code,
|
||||||
_ => code,
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raise_exception_phase2(
|
fn raise_exception_phase2(
|
||||||
@ -225,16 +251,16 @@ pub extern "C-unwind" fn _Unwind_ForcedUnwind(
|
|||||||
stop: UnwindStopFn,
|
stop: UnwindStopFn,
|
||||||
stop_arg: *mut c_void,
|
stop_arg: *mut c_void,
|
||||||
) -> UnwindReasonCode {
|
) -> UnwindReasonCode {
|
||||||
let mut ctx = save_context();
|
with_context(|ctx| {
|
||||||
|
exception.private_1 = Some(stop);
|
||||||
|
exception.private_2 = stop_arg as _;
|
||||||
|
|
||||||
exception.private_1 = Some(stop);
|
let code = force_unwind_phase2(exception, ctx, stop, stop_arg);
|
||||||
exception.private_2 = stop_arg as _;
|
match code {
|
||||||
|
UnwindReasonCode::INSTALL_CONTEXT => unsafe { restore_context(ctx) },
|
||||||
let code = force_unwind_phase2(exception, &mut ctx, stop, stop_arg);
|
_ => code,
|
||||||
match code {
|
}
|
||||||
UnwindReasonCode::INSTALL_CONTEXT => unsafe { restore_context(&ctx) },
|
})
|
||||||
_ => code,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn force_unwind_phase2(
|
fn force_unwind_phase2(
|
||||||
@ -304,21 +330,21 @@ fn force_unwind_phase2(
|
|||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C-unwind" fn _Unwind_Resume(exception: &mut UnwindException) -> ! {
|
pub extern "C-unwind" fn _Unwind_Resume(exception: &mut UnwindException) -> ! {
|
||||||
let mut ctx = save_context();
|
with_context(|ctx| {
|
||||||
|
let code = match exception.private_1 {
|
||||||
|
None => {
|
||||||
|
let handler_cfa = exception.private_2;
|
||||||
|
raise_exception_phase2(exception, ctx, handler_cfa)
|
||||||
|
}
|
||||||
|
Some(stop) => {
|
||||||
|
let stop_arg = exception.private_2 as _;
|
||||||
|
force_unwind_phase2(exception, ctx, stop, stop_arg)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assert!(code == UnwindReasonCode::INSTALL_CONTEXT);
|
||||||
|
|
||||||
let code = match exception.private_1 {
|
unsafe { restore_context(ctx) }
|
||||||
None => {
|
})
|
||||||
let handler_cfa = exception.private_2;
|
|
||||||
raise_exception_phase2(exception, &mut ctx, handler_cfa)
|
|
||||||
}
|
|
||||||
Some(stop) => {
|
|
||||||
let stop_arg = exception.private_2 as _;
|
|
||||||
force_unwind_phase2(exception, &mut ctx, stop, stop_arg)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
assert!(code == UnwindReasonCode::INSTALL_CONTEXT);
|
|
||||||
|
|
||||||
unsafe { restore_context(&ctx) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
@ -331,13 +357,13 @@ pub extern "C-unwind" fn _Unwind_Resume_or_Rethrow(
|
|||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut ctx = save_context();
|
with_context(|ctx| {
|
||||||
|
let stop_arg = exception.private_2 as _;
|
||||||
|
let code = force_unwind_phase2(exception, ctx, stop, stop_arg);
|
||||||
|
assert!(code == UnwindReasonCode::INSTALL_CONTEXT);
|
||||||
|
|
||||||
let stop_arg = exception.private_2 as _;
|
unsafe { restore_context(ctx) }
|
||||||
let code = force_unwind_phase2(exception, &mut ctx, stop, stop_arg);
|
})
|
||||||
assert!(code == UnwindReasonCode::INSTALL_CONTEXT);
|
|
||||||
|
|
||||||
unsafe { restore_context(&ctx) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -353,36 +379,38 @@ pub extern "C-unwind" fn _Unwind_Backtrace(
|
|||||||
trace: UnwindTraceFn,
|
trace: UnwindTraceFn,
|
||||||
trace_argument: *mut c_void,
|
trace_argument: *mut c_void,
|
||||||
) -> UnwindReasonCode {
|
) -> UnwindReasonCode {
|
||||||
let mut ctx = save_context();
|
with_context(|ctx| {
|
||||||
let mut signal = false;
|
let mut ctx = ctx.clone();
|
||||||
let mut skipping = cfg!(feature = "hide-trace");
|
let mut signal = false;
|
||||||
|
let mut skipping = cfg!(feature = "hide-trace");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let frame = try1!(Frame::from_context(&ctx, signal));
|
let frame = try1!(Frame::from_context(&ctx, signal));
|
||||||
if !skipping {
|
if !skipping {
|
||||||
let code = trace(
|
let code = trace(
|
||||||
&mut UnwindContext {
|
&mut UnwindContext {
|
||||||
frame: frame.as_ref(),
|
frame: frame.as_ref(),
|
||||||
ctx: &mut ctx,
|
ctx: &mut ctx,
|
||||||
signal,
|
signal,
|
||||||
},
|
},
|
||||||
trace_argument,
|
trace_argument,
|
||||||
);
|
);
|
||||||
match code {
|
match code {
|
||||||
UnwindReasonCode::NO_REASON => (),
|
UnwindReasonCode::NO_REASON => (),
|
||||||
_ => return UnwindReasonCode::FATAL_PHASE1_ERROR,
|
_ => return UnwindReasonCode::FATAL_PHASE1_ERROR,
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(frame) = frame {
|
|
||||||
if skipping {
|
|
||||||
if frame.initial_address() == _Unwind_Backtrace as usize {
|
|
||||||
skipping = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx = try1!(frame.unwind(&ctx));
|
if let Some(frame) = frame {
|
||||||
signal = frame.is_signal_trampoline();
|
if skipping {
|
||||||
} else {
|
if frame.initial_address() == _Unwind_Backtrace as usize {
|
||||||
return UnwindReasonCode::END_OF_STACK;
|
skipping = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx = try1!(frame.unwind(&ctx));
|
||||||
|
signal = frame.is_signal_trampoline();
|
||||||
|
} else {
|
||||||
|
return UnwindReasonCode::END_OF_STACK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user