Fixed stack unwind bugs (works!)
This commit is contained in:
@@ -36,6 +36,7 @@ use crate::{
|
||||
use arch::x86_64::memory::mapping;
|
||||
use core::arch::asm;
|
||||
use limine::BaseRevision;
|
||||
use std::unwind::UNWINDER;
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
pub mod arch;
|
||||
@@ -144,5 +145,7 @@ pub fn boot() -> Result<(), &'static str> {
|
||||
x86_64::instructions::interrupts::enable();
|
||||
debugln!("[Success]");
|
||||
|
||||
UNWINDER.lock(); // Initialises the Unwinder once and only once :fingers_crossed:.
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
use core::arch::asm;
|
||||
|
||||
use eh_info::ELF;
|
||||
use spin::{Lazy, Mutex};
|
||||
use unwinder::{RegisterSet, Unwinder};
|
||||
|
||||
pub mod eh_info;
|
||||
pub mod panic;
|
||||
pub mod unwinder;
|
||||
|
||||
/// We should initialise on program start.
|
||||
pub static UNWINDER: Lazy<Mutex<Unwinder>> = Lazy::new(|| {
|
||||
// Setup stack traces and proper panic handler. TODO: Handle panics
|
||||
// differently if not initialised.
|
||||
let eh_frame_ptr = ELF
|
||||
.get_section_addr(".eh_frame_hdr")
|
||||
.expect("Could not get `.eh_frame_hdr` address.");
|
||||
|
||||
let eh_info = unsafe { eh_info::EhInfo::from_hdr_ptr(eh_frame_ptr) };
|
||||
let mut registers = RegisterSet::default();
|
||||
|
||||
Mutex::new(Unwinder::new(eh_info, registers))
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ use super::unwinder::Unwinder;
|
||||
use crate::{
|
||||
hcf,
|
||||
prelude::*,
|
||||
std::unwind::{eh_info::ELF, unwinder::RegisterSet},
|
||||
std::unwind::{UNWINDER, eh_info::ELF, unwinder::RegisterSet},
|
||||
};
|
||||
|
||||
#[panic_handler]
|
||||
@@ -19,27 +19,18 @@ pub fn panic_handler(info: &PanicInfo<'_>) -> ! {
|
||||
println!("Kernel panic: {}", info);
|
||||
serial_println!("Kernel panic: {}", info);
|
||||
|
||||
// Setup stack traces and proper panic handler. TODO: Handle panics
|
||||
// differently if not initialised.
|
||||
let eh_frame_ptr = ELF
|
||||
.get_section_addr(".eh_frame_hdr")
|
||||
.expect("Could not get `.eh_frame_hdr` address.");
|
||||
|
||||
let eh_info = unsafe { super::eh_info::EhInfo::from_hdr_ptr(eh_frame_ptr) };
|
||||
let mut registers = RegisterSet::default();
|
||||
|
||||
let mut rip: u64;
|
||||
let mut rsp: u64;
|
||||
|
||||
unsafe {
|
||||
asm!("lea {0}, [rip]",
|
||||
"mov {1}, rsp",
|
||||
out(reg) rip, out(reg) rsp);
|
||||
}
|
||||
registers.set_pc(rip);
|
||||
registers.set_stack_ptr(rsp);
|
||||
|
||||
let mut unwinder = Unwinder::new(eh_info, registers);
|
||||
let mut unwinder = UNWINDER.lock();
|
||||
unwinder.regs.set_pc(rip);
|
||||
unwinder.regs.set_stack_ptr(rsp);
|
||||
|
||||
while let Some(call_frame) = unwinder.next().unwrap_or_else(|err| {
|
||||
// If an unwind error occurred.
|
||||
eprintln!("{:?}", err);
|
||||
|
||||
@@ -27,7 +27,7 @@ pub struct Unwinder {
|
||||
unwind_ctx: UnwindContext<usize, StoreOnHeap>,
|
||||
/// The current values of ABI/architecture independent registers. There are
|
||||
/// used by DWARF.
|
||||
regs: RegisterSet,
|
||||
pub regs: RegisterSet,
|
||||
/// The current CFA address.
|
||||
cfa: u64,
|
||||
/// Is this the first iteration?
|
||||
@@ -112,7 +112,10 @@ impl FallibleIterator for Unwinder {
|
||||
};
|
||||
|
||||
// REVIEWME: Must be a nicer way of doing this.
|
||||
let pc = pc - 1;
|
||||
let Some(pc) = pc.checked_sub(1) else {
|
||||
// REVIEWME: This should handle underflow now.
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
self.regs.set_pc(pc);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user