Handle signal frame
This commit is contained in:
parent
10dccf7dc4
commit
41e805c1cf
@ -17,7 +17,7 @@ pub struct Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
pub fn from_context(ctx: &Context) -> Result<Option<Self>, gimli::Error> {
|
pub fn from_context(ctx: &Context, signal: bool) -> Result<Option<Self>, gimli::Error> {
|
||||||
let mut ra = ctx[Arch::RA];
|
let mut ra = ctx[Arch::RA];
|
||||||
|
|
||||||
// Reached end of stack
|
// Reached end of stack
|
||||||
@ -26,7 +26,9 @@ impl Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RA points to the *next* instruction, so move it back 1 byte for the call instruction.
|
// RA points to the *next* instruction, so move it back 1 byte for the call instruction.
|
||||||
ra -= 1;
|
if !signal {
|
||||||
|
ra -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
let fde_result = match find_fde::get_finder().find_fde(ra as _) {
|
let fde_result = match find_fde::get_finder().find_fde(ra as _) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
@ -153,4 +155,8 @@ impl Frame {
|
|||||||
pub fn initial_address(&self) -> usize {
|
pub fn initial_address(&self) -> usize {
|
||||||
self.fde_result.fde.initial_address() as _
|
self.fde_result.fde.initial_address() as _
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_signal_trampoline(&self) -> bool {
|
||||||
|
self.fde_result.fde.is_signal_trampoline()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ pub struct UnwindException {
|
|||||||
pub struct UnwindContext<'a> {
|
pub struct UnwindContext<'a> {
|
||||||
frame: Option<&'a Frame>,
|
frame: Option<&'a Frame>,
|
||||||
ctx: &'a mut Context,
|
ctx: &'a mut Context,
|
||||||
|
signal: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -52,7 +53,7 @@ pub extern "C" fn _Unwind_GetIPInfo(
|
|||||||
unwind_ctx: &UnwindContext<'_>,
|
unwind_ctx: &UnwindContext<'_>,
|
||||||
ip_before_insn: &mut c_int,
|
ip_before_insn: &mut c_int,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
*ip_before_insn = 0;
|
*ip_before_insn = unwind_ctx.signal as _;
|
||||||
unwind_ctx.ctx[Arch::RA]
|
unwind_ctx.ctx[Arch::RA]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,8 +125,9 @@ pub extern "C-unwind" fn _Unwind_RaiseException(
|
|||||||
|
|
||||||
// Phase 1: Search for handler
|
// Phase 1: Search for handler
|
||||||
let mut ctx = saved_ctx.clone();
|
let mut ctx = saved_ctx.clone();
|
||||||
let handler_cfa = loop {
|
let mut signal = false;
|
||||||
if let Some(frame) = try1!(Frame::from_context(&ctx)) {
|
loop {
|
||||||
|
if let Some(frame) = try1!(Frame::from_context(&ctx, signal)) {
|
||||||
if let Some(personality) = frame.personality() {
|
if let Some(personality) = frame.personality() {
|
||||||
let result = personality(
|
let result = personality(
|
||||||
1,
|
1,
|
||||||
@ -135,25 +137,30 @@ pub extern "C-unwind" fn _Unwind_RaiseException(
|
|||||||
&mut UnwindContext {
|
&mut UnwindContext {
|
||||||
frame: Some(&frame),
|
frame: Some(&frame),
|
||||||
ctx: &mut ctx,
|
ctx: &mut ctx,
|
||||||
|
signal,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
UnwindReasonCode::CONTINUE_UNWIND => (),
|
UnwindReasonCode::CONTINUE_UNWIND => (),
|
||||||
UnwindReasonCode::HANDLER_FOUND => {
|
UnwindReasonCode::HANDLER_FOUND => {
|
||||||
exception.private_1 = None;
|
break;
|
||||||
exception.private_2 = ctx[Arch::SP];
|
|
||||||
break ctx[Arch::SP];
|
|
||||||
}
|
}
|
||||||
_ => return UnwindReasonCode::FATAL_PHASE1_ERROR,
|
_ => return UnwindReasonCode::FATAL_PHASE1_ERROR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = try1!(frame.unwind(&ctx));
|
ctx = try1!(frame.unwind(&ctx));
|
||||||
|
signal = frame.is_signal_trampoline();
|
||||||
} else {
|
} else {
|
||||||
return UnwindReasonCode::END_OF_STACK;
|
return UnwindReasonCode::END_OF_STACK;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
// Disambiguate normal frame and signal frame.
|
||||||
|
let handler_cfa = ctx[Arch::SP] - signal as usize;
|
||||||
|
exception.private_1 = None;
|
||||||
|
exception.private_2 = handler_cfa;
|
||||||
|
|
||||||
let mut ctx = saved_ctx;
|
let mut ctx = saved_ctx;
|
||||||
let code = raise_exception_phase2(exception, &mut ctx, handler_cfa);
|
let code = raise_exception_phase2(exception, &mut ctx, handler_cfa);
|
||||||
@ -168,14 +175,15 @@ fn raise_exception_phase2(
|
|||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
handler_cfa: usize,
|
handler_cfa: usize,
|
||||||
) -> UnwindReasonCode {
|
) -> UnwindReasonCode {
|
||||||
|
let mut signal = false;
|
||||||
loop {
|
loop {
|
||||||
if let Some(frame) = try2!(Frame::from_context(ctx)) {
|
if let Some(frame) = try2!(Frame::from_context(ctx, signal)) {
|
||||||
let is_handler = ctx[Arch::SP] == handler_cfa;
|
let frame_cfa = ctx[Arch::SP] - signal as usize;
|
||||||
if let Some(personality) = frame.personality() {
|
if let Some(personality) = frame.personality() {
|
||||||
let code = personality(
|
let code = personality(
|
||||||
1,
|
1,
|
||||||
UnwindAction::CLEANUP_PHASE
|
UnwindAction::CLEANUP_PHASE
|
||||||
| if is_handler {
|
| if frame_cfa == handler_cfa {
|
||||||
UnwindAction::HANDLER_FRAME
|
UnwindAction::HANDLER_FRAME
|
||||||
} else {
|
} else {
|
||||||
UnwindAction::empty()
|
UnwindAction::empty()
|
||||||
@ -185,6 +193,7 @@ fn raise_exception_phase2(
|
|||||||
&mut UnwindContext {
|
&mut UnwindContext {
|
||||||
frame: Some(&frame),
|
frame: Some(&frame),
|
||||||
ctx,
|
ctx,
|
||||||
|
signal,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -196,6 +205,7 @@ fn raise_exception_phase2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
*ctx = try2!(frame.unwind(ctx));
|
*ctx = try2!(frame.unwind(ctx));
|
||||||
|
signal = frame.is_signal_trampoline();
|
||||||
} else {
|
} else {
|
||||||
return UnwindReasonCode::FATAL_PHASE2_ERROR;
|
return UnwindReasonCode::FATAL_PHASE2_ERROR;
|
||||||
}
|
}
|
||||||
@ -228,8 +238,9 @@ fn force_unwind_phase2(
|
|||||||
stop: UnwindStopFn,
|
stop: UnwindStopFn,
|
||||||
stop_arg: *mut c_void,
|
stop_arg: *mut c_void,
|
||||||
) -> UnwindReasonCode {
|
) -> UnwindReasonCode {
|
||||||
|
let mut signal = false;
|
||||||
loop {
|
loop {
|
||||||
let frame = try2!(Frame::from_context(ctx));
|
let frame = try2!(Frame::from_context(ctx, signal));
|
||||||
|
|
||||||
let code = stop(
|
let code = stop(
|
||||||
1,
|
1,
|
||||||
@ -245,6 +256,7 @@ fn force_unwind_phase2(
|
|||||||
&mut UnwindContext {
|
&mut UnwindContext {
|
||||||
frame: frame.as_ref(),
|
frame: frame.as_ref(),
|
||||||
ctx,
|
ctx,
|
||||||
|
signal,
|
||||||
},
|
},
|
||||||
stop_arg,
|
stop_arg,
|
||||||
);
|
);
|
||||||
@ -263,6 +275,7 @@ fn force_unwind_phase2(
|
|||||||
&mut UnwindContext {
|
&mut UnwindContext {
|
||||||
frame: Some(&frame),
|
frame: Some(&frame),
|
||||||
ctx,
|
ctx,
|
||||||
|
signal,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -274,6 +287,7 @@ fn force_unwind_phase2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
*ctx = try2!(frame.unwind(ctx));
|
*ctx = try2!(frame.unwind(ctx));
|
||||||
|
signal = frame.is_signal_trampoline();
|
||||||
} else {
|
} else {
|
||||||
return UnwindReasonCode::END_OF_STACK;
|
return UnwindReasonCode::END_OF_STACK;
|
||||||
}
|
}
|
||||||
@ -333,15 +347,17 @@ pub extern "C-unwind" fn _Unwind_Backtrace(
|
|||||||
trace_argument: *mut c_void,
|
trace_argument: *mut c_void,
|
||||||
) -> UnwindReasonCode {
|
) -> UnwindReasonCode {
|
||||||
let mut ctx = save_context();
|
let mut ctx = save_context();
|
||||||
|
let mut signal = false;
|
||||||
let mut skipping = cfg!(feature = "hide-trace");
|
let mut skipping = cfg!(feature = "hide-trace");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let frame = try1!(Frame::from_context(&ctx));
|
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,
|
||||||
},
|
},
|
||||||
trace_argument,
|
trace_argument,
|
||||||
);
|
);
|
||||||
@ -357,6 +373,7 @@ pub extern "C-unwind" fn _Unwind_Backtrace(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx = try1!(frame.unwind(&ctx));
|
ctx = try1!(frame.unwind(&ctx));
|
||||||
|
signal = frame.is_signal_trampoline();
|
||||||
} else {
|
} else {
|
||||||
return UnwindReasonCode::END_OF_STACK;
|
return UnwindReasonCode::END_OF_STACK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user