firmware: adjust backtrace addresses correctly.

This commit is contained in:
whitequark 2018-05-17 08:13:39 +00:00
parent d4f074b1e1
commit 5744d97d59
3 changed files with 13 additions and 6 deletions

View File

@ -32,9 +32,7 @@ pub fn backtrace<F>(f: F) -> Result<(), uw::_Unwind_Reason_Code>
trace_context.prev_sp = cur_sp;
}
// GetIP gives us the return address, i.e. the address after the delay slot,
// but we're interested in the call instruction.
(trace_context.step_fn)(uw::_Unwind_GetIP(context) - 2 * 4);
(trace_context.step_fn)(uw::_Unwind_GetIP(context));
uw::_URC_NO_REASON
}
}

View File

@ -313,7 +313,9 @@ pub extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str,
println!("backtrace for software version {}:",
include_str!(concat!(env!("OUT_DIR"), "/git-describe")));
let _ = unwind_backtrace::backtrace(|ip| {
println!("{:#08x}", ip);
// Backtrace gives us the return address, i.e. the address after the delay slot,
// but we're interested in the call instruction.
println!("{:#08x}", ip - 2 * 4);
});
if config::read_str("panic_reset", |r| r == Ok("1")) {

View File

@ -201,7 +201,7 @@ mod imp {
const SKIP_FRAMES: i32 = 3;
#[inline(always)] // make the top of backtrace predictable
fn record(profile: &mut Profile, pc: usize) -> Result<(), ()> {
fn record(profile: &mut Profile, exn_pc: usize) -> Result<(), ()> {
let mut result = Ok(());
let mut frame = -SKIP_FRAMES;
@ -212,6 +212,12 @@ mod imp {
if profile.has_edges() {
let mut prev_pc = 0;
let _ = backtrace(|pc| {
// Backtrace gives us the return address, i.e. the address after the delay slot,
// but we're interested in the call instruction, *except* when going through
// the frame directly below the exception frame, which has the address that's
// being executed.
let pc = if pc != exn_pc { pc - 2 * 4 } else { pc };
if frame == 0 {
result = result.and_then(|()|
profile.record_hit(Address::new(pc)));
@ -221,6 +227,7 @@ mod imp {
profile.record_edge(Address::new(pc),
Address::new(prev_pc)));
}
prev_pc = pc;
frame += 1;
});
@ -229,7 +236,7 @@ mod imp {
// If we couldn't get anything useful out of a backtrace, at least
// record a hit at the exception PC.
if frame <= 0 {
result = profile.record_hit(Address::new(pc));
result = profile.record_hit(Address::new(exn_pc));
}
result