Fix backtrace for mipsel

Signed-off-by: Harry Chen <i@harrychen.xyz>
master
Harry Chen 6 years ago
parent 6cc607e0c8
commit b75e388aa1

@ -22,7 +22,7 @@ _start:
mtc0 t0, $12 mtc0 t0, $12
# directly jump to main function # directly jump to main function
j rust_main jal rust_main
nop nop
.section .bss.stack .section .bss.stack

@ -24,8 +24,8 @@ pub fn fp() -> usize {
} }
#[cfg(any(target_arch = "mips"))] #[cfg(any(target_arch = "mips"))]
unsafe { unsafe {
// fp = $30 // read $sp
asm!("ori $0, $$30, 0" : "=r"(ptr)); asm!("ori $0, $$29, 0" : "=r"(ptr));
} }
ptr ptr
@ -57,22 +57,46 @@ pub fn lr() -> usize {
ptr ptr
} }
// Print the backtrace starting from the caller // Print the backtrace starting from the caller
pub fn backtrace() { pub fn backtrace() {
unsafe { unsafe {
let mut current_pc = lr(); let mut current_pc = lr();
let mut current_fp = fp(); let mut current_fp = fp();
let mut stack_num = 0; let mut stack_num = 0;
// adjust sp to the top address of backtrace() function
#[cfg(target_arch = "mips")]
{
let func_base = backtrace as *const isize;
let sp_offset = (*func_base << 16) >> 16;
current_fp = ((current_fp as isize) - sp_offset) as usize;
}
while current_pc >= stext as usize while current_pc >= stext as usize
&& current_pc <= etext as usize && current_pc <= etext as usize
&& current_fp as usize != 0 && current_fp as usize != 0
{ {
// print current backtrace
match size_of::<usize>() {
4 => {
println!( println!(
"#{} {:#018X} fp {:#018X}", "Stack #{:02} PC: {:#010X} FP: {:#010X}",
stack_num, stack_num,
current_pc - size_of::<usize>(), current_pc - size_of::<usize>(),
current_fp current_fp
); );
},
_ => {
println!(
"Stack #{:02} PC: {:#018X} FP: {:#018X}",
stack_num,
current_pc - size_of::<usize>(),
current_fp
);
}
}
stack_num = stack_num + 1; stack_num = stack_num + 1;
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
{ {
@ -86,6 +110,42 @@ pub fn backtrace() {
current_pc = *(current_fp as *const usize).offset(1); current_pc = *(current_fp as *const usize).offset(1);
} }
} }
#[cfg(target_arch = "mips")]
{
// the prologue of function is always like:
// main+0: 27bd____ addiu sp, sp, -____
// main+4: afbf____ sw ra, ____(sp)
let mut code_ptr = current_pc as *const isize;
code_ptr = code_ptr.offset(-1);
// get the stack size of last function
while (*code_ptr as usize >> 16) != 0x27bd {
code_ptr = code_ptr.offset(-1);
}
let sp_offset = (*code_ptr << 16) >> 16;
trace!("Found addiu sp @ {:08X}({:08x}) with sp offset {}", code_ptr as usize, *code_ptr, sp_offset);
// get the return address offset of last function
let mut last_fun_found = false;
while (code_ptr as usize) < current_pc {
if (*code_ptr as usize >> 16) == 0xafbf {
last_fun_found = true;
break;
}
code_ptr = code_ptr.offset(1);
}
if last_fun_found {
// unwind stack
let ra_offset = (*code_ptr << 16) >> 16;
trace!("Found sw ra @ {:08X}({:08x}) with ra offset {}", code_ptr as usize, *code_ptr, ra_offset);
current_pc = *(((current_fp as isize) + ra_offset) as *const usize);
current_fp = ((current_fp as isize) - sp_offset) as usize;
trace!("New PC {:08X} FP {:08X}", current_pc, current_fp);
continue;
} else {
break;
}
}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
{ {
// Kernel stack at 0x0000_57ac_0000_0000 (defined in bootloader crate) // Kernel stack at 0x0000_57ac_0000_0000 (defined in bootloader crate)

Loading…
Cancel
Save