stack trace uses saved registers, aka more useful stacktraces

This commit is contained in:
Zoe
2023-11-25 22:36:06 -06:00
parent b16f2152c2
commit 749ee0a0ba
18 changed files with 132 additions and 35152 deletions

4
.gitignore vendored
View File

@@ -1,6 +1,8 @@
/target
/bin
/scripts/*/**
# Bochs
bx_enh_dbg.ini
# limine
limine/

4
.gitmodules vendored
View File

@@ -1,4 +0,0 @@
[submodule "limine"]
path = limine
url = https://github.com/limine-bootloader/limine
branch = v5.x-branch-binary

View File

@@ -90,7 +90,7 @@ endif
build-iso: partition-iso
nm target/${ARCH}-unknown-none/${MODE}/CappuccinOS.elf > scripts/symbols.table
@if [ ! -d "scripts/rustc_demangle" ]; then \
echo "Cloning repository into scripts/rustc_demangle..."; \
echo "Cloning rustc_demangle.py into scripts/rustc_demangle/..."; \
git clone "https://github.com/juls0730/rustc_demangle.py" "scripts/rustc_demangle"; \
else \
echo "Folder scripts/rustc_demangle already exists. Skipping clone."; \
@@ -106,6 +106,12 @@ build-iso: partition-iso
mcopy -i ${IMAGE_PATH}@@1M -s ${ISO_PATH}/* ::/
compile-bootloader:
@if [ ! -d "limine" ]; then \
echo "Cloning Limine into limine/..."; \
git clone https://github.com/limine-bootloader/limine.git --branch=v5.x-branch-binary --depth=1; \
else \
echo "Folder limine already exists. Skipping clone."; \
fi
make -C limine
compile-binaries:

File diff suppressed because it is too large Load Diff

1
limine

Submodule limine deleted from 7563eb4dbe

1
scripts/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
rustc_demangle/

View File

@@ -1,2 +1,5 @@
# CappuccinOS/scripts
This folder is responsible for holding all the scripts that are necessary for building CappuccinOS
- **demangle-symbols.py**<br/>
This file takes in a symbols file generated by the `nm` program and outputs a symbol file with the symbol names demangled, it uses my library, [rustc_demangle.py](https://github.com/juls0730/rustc_demangle.py) which is a python port of the Rust symbol demangling library [rustc-demangle](https://github.com/rust-lang/rustc-demangle).

Submodule scripts/rustc_demangle deleted from 9c7b8459ec

View File

@@ -1,13 +1,11 @@
#[cfg(any(target_arch = "x86_64"))]
pub use self::imp::*;
pub use self::x86_64::*;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub use self::x86_common::*;
#[cfg(target_arch = "x86_64")]
mod x86_64;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod x86_common;
#[cfg(target_arch = "x86_64")]
#[path = "x86_64"]
mod imp {
pub mod interrupts;
}

View File

@@ -2,8 +2,46 @@ use super::idt_set_gate;
use crate::libs::util::hcf;
use crate::{log_error, log_info};
#[no_mangle]
pub extern "C" fn exception_handler(int: u64, eip: u64, cs: u64, eflags: u64) -> ! {
#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct Registers {
// Pushed by wrapper
int: usize,
// Pushed by push_gprs in crate::arch::x86_64
r15: usize,
r14: usize,
r13: usize,
r12: usize,
r11: usize,
r10: usize,
r9: usize,
r8: usize,
rbp: usize,
rdi: usize,
rsi: usize,
rdx: usize,
rcx: usize,
rbx: usize,
rax: usize,
// Pushed by interrupt
rip: usize,
cs: usize,
rflags: usize,
rsp: usize,
ss: usize,
}
extern "C" fn exception_handler(registers: u64) {
crate::println!("{:X?}", registers);
let registers = unsafe { *(registers as *const Registers) };
crate::println!("{:X?}", registers);
let int = registers.int;
match int {
0x00 => {
log_error!("DIVISION ERROR!");
@@ -20,9 +58,6 @@ pub extern "C" fn exception_handler(int: u64, eip: u64, cs: u64, eflags: u64) ->
0x0E => {
log_error!("PAGE FAULT!");
}
0x0F => {
log_error!("IDE");
}
0xFF => {
log_error!("EXCEPTION!");
}
@@ -32,100 +67,52 @@ pub extern "C" fn exception_handler(int: u64, eip: u64, cs: u64, eflags: u64) ->
}
log_info!(
"INT: {:x} EIP: {:X}, CS: {:X}, EFLAGS: {:b}",
"INT: {:x} RIP: {:X}, CS: {:X}, EFLAGS: {:b}",
int,
eip,
cs,
eflags
registers.rip,
registers.cs,
registers.rflags
);
// unsafe {
// core::arch::asm!("cli");
// };
crate::arch::stack_trace::print_stack_trace(6, registers.rbp as u64);
}
crate::arch::stack_trace::print_stack_trace(6);
// *macro intensifies*
macro_rules! exception_function {
($code:expr, $handler:ident, $recoverable:literal) => {
#[inline(always)]
extern "C" fn $handler() {
crate::arch::push_gprs();
unsafe {
core::arch::asm!(
"push {0:r}",
"mov rdi, rsp",
"call {1}",
"pop {0:r}",
"mov rsp, rdi",
in(reg) $code,
sym exception_handler,
);
};
if $recoverable {
crate::println!("TODO: Recover gracefully ;~;");
hcf();
} else {
hcf();
}
#[naked]
pub extern "C" fn div_error() {
unsafe {
core::arch::asm!(
// WHY DOESN'T PUSH DO THIS CORRECTLY
"mov rdi, 0x00",
"call exception_handler",
"add esp, 4",
"iretq",
options(noreturn)
);
}
};
}
#[naked]
pub extern "C" fn invalid_opcode() {
unsafe {
core::arch::asm!(
"mov rdi, 0x06",
"call exception_handler",
"add esp, 4",
"iretq",
options(noreturn)
);
}
}
#[naked]
pub extern "C" fn double_fault() {
unsafe {
core::arch::asm!(
"mov rdi, 0x08",
"call exception_handler",
"add esp, 4",
"iretq",
options(noreturn)
);
}
}
#[naked]
pub extern "C" fn general_protection_fault() {
unsafe {
core::arch::asm!(
"mov rdi, 0x0D",
"call exception_handler",
"add esp, 4",
"iretq",
options(noreturn)
);
}
}
#[naked]
pub extern "C" fn page_fault() {
unsafe {
core::arch::asm!(
"mov rdi, 0x0E",
"call exception_handler",
"add esp, 4",
"iretq",
options(noreturn)
);
}
}
#[naked]
pub extern "C" fn generic_handler() {
unsafe {
core::arch::asm!(
"mov rdi, 0xFF",
"call exception_handler",
"add esp, 4",
"iretq",
options(noreturn)
);
}
}
exception_function!(0x00, div_error, true);
exception_function!(0x06, invalid_opcode, true);
exception_function!(0x08, double_fault, false);
exception_function!(0x0D, general_protection_fault, true);
// TODO: fix the page fault then gracefully return.
exception_function!(0x0E, page_fault, false);
exception_function!(0xFF, generic_handler, true);
pub fn set_exceptions() {
for i in 0..32 {

View File

@@ -114,7 +114,7 @@ fn idt_init() {
}
#[naked]
pub extern "C" fn syscall() {
pub extern "C" fn syscall(func: extern "C" fn()) {
unsafe {
core::arch::asm!(
"push rdi",

View File

@@ -1,4 +1,24 @@
pub mod interrupts;
#[path = "../x86_common/mod.rs"]
pub mod common;
// This inline is detremental to having readable stack traces
#[inline(always)]
pub fn push_gprs() {
unsafe {
core::arch::asm!(
"push rax", "push rbx", "push rcx", "push rdx", "push rsi", "push rdi", "push rbp",
"push r8", "push r9", "push r10", "push r11", "push r12", "push r13", "push r14",
"push r15"
);
}
}
// This inline is detremental to having readable stack traces
#[inline(always)]
pub fn pop_gprs() {
unsafe {
core::arch::asm!(
"pop rax", "pop rbx", "pop rcx", "pop rdx", "pop rsi", "pop rdi", "pop rbp", "pop r8",
"pop r9", "pop r10", "pop r11", "pop r12", "pop r13", "pop r14", "pop r15",
);
}
}

View File

@@ -7,12 +7,8 @@ struct StackFrame {
rip: u64,
}
pub fn print_stack_trace(max_frames: usize) {
let mut stackframe: *const StackFrame;
unsafe {
core::arch::asm!("mov {0:r}, rbp", out(reg) stackframe);
};
pub fn print_stack_trace(max_frames: usize, rbp: u64) {
let mut stackframe = rbp as *const StackFrame;
crate::println!("Stack Trace:");
for _frame in 0..max_frames {

View File

@@ -36,8 +36,6 @@ pub extern "x86-interrupt" fn keyboard_interrupt_handler() {
#[derive(Debug)]
pub enum KBDError {
TimeoutError,
ParityError,
TestFailed,
}
@@ -51,25 +49,7 @@ pub fn init() -> Result<(), KBDError> {
outb(KBD_COMMAND_AND_STATUS_PORT, 0xA7);
outb(KBD_COMMAND_AND_STATUS_PORT, 0xAD);
outb(KBD_COMMAND_AND_STATUS_PORT, 0xFF);
let status = inb(KBD_COMMAND_AND_STATUS_PORT);
if status & (1 << 6) != 0 {
return Err(KBDError::TimeoutError);
}
if status & (1 << 7) != 0 {
return Err(KBDError::ParityError);
}
// Test the controller
outb(KBD_COMMAND_AND_STATUS_PORT, 0xAA);
let result = inb(KBD_DATA_PORT);
if result != 0x55 {
crate::println!("Got result: {result}");
return Err(KBDError::TestFailed);
}
// TODO: Test the controller correctly
idt_set_gate(
InterruptIndex::Keyboard.as_u8(),

View File

@@ -295,12 +295,10 @@ impl<'a> ATABus {
self.wait_for_drive_ready()
.map_err(|_| crate::log_error!("Error before issuing Identify command."))?;
for i in 0..(ATA_SECTOR_SIZE / size_of::<u16>()) {
for chunk in buffer.chunks_exact_mut(core::mem::size_of::<u16>()) {
let word = inw(self.io_bar + ATADriveDataRegister::Data as u16);
unsafe {
*(buffer.as_mut_ptr() as *mut u16).add(i) = word;
};
chunk.copy_from_slice(&word.to_le_bytes());
}
return Ok(Arc::from(buffer));

View File

@@ -46,6 +46,11 @@ pub extern "C" fn _start() -> ! {
.label_bytes()
);
let asd: u32 = 0xdeadbeef;
unsafe {
*(asd as *mut u64) = 12;
};
usr::shell::init_shell();
hcf();

View File

@@ -1,2 +1,3 @@
pub mod shell;
#[macro_use]
pub mod tty;

View File

@@ -133,10 +133,6 @@ pub fn handle_key(mut key: Key) {
}
pub fn prompt() {
unsafe {
core::arch::asm!("div rax, {0:r}", in(reg) 0x00);
};
super::tty::CONSOLE.puts("> ");
}