feat: better panic handler

This commit is contained in:
Loïc Grégoire
2026-04-17 20:35:44 -04:00
parent 927ea2e1b8
commit c68a93b302
6 changed files with 217 additions and 67 deletions
+27 -7
View File
@@ -1,6 +1,8 @@
const amd64 = @import("arch");
const std = @import("std");
const b = @import("base");
const ke = b.ke;
const ki = ke.private;
extern const __interrupt_vectors: [256]usize;
@@ -43,17 +45,35 @@ const exception_msg = [32][]const u8{
export fn isr_handler_main(frame: *const amd64.IrqFrame) callconv(.{ .x86_64_sysv = .{} }) void {
if (frame.intno < 32) {
std.log.info("Unhandled exception: 0x{x} ({s}), err=0x{x}, pc=0x{x}", .{ frame.intno, exception_msg[frame.intno], frame.errcode, frame.rip });
std.log.info("RAX=0x{x:0>16} RBX=0x{x:0>16} RCX=0x{x:0>16} RDX=0x{x:0>16}", .{ frame.rax, frame.rbx, frame.rcx, frame.rdx });
std.log.info("RSI=0x{x:0>16} RDI=0x{x:0>16} RBP=0x{x:0>16} RSP=0x{x:0>16}", .{ frame.rsi, frame.rdi, frame.rbp, frame.rsp });
std.log.info("R8= 0x{x:0>16} R9=0x{x:0>16} R10=0x{x:0>16} R11=0x{x:0>16}", .{ frame.r8, frame.r9, frame.r10, frame.r11 });
std.log.info("R12=0x{x:0>16} R13=0x{x:0>16} R14=0x{x:0>16} R15=0x{x:0>16}", .{ frame.r12, frame.r13, frame.r14, frame.r15 });
std.log.err("Unhandled exception: 0x{x} ({s}), err=0x{x}, pc=0x{x}", .{ frame.intno, exception_msg[frame.intno], frame.errcode, frame.rip });
std.log.err("RAX=0x{x:0>16} RBX=0x{x:0>16} RCX=0x{x:0>16} RDX=0x{x:0>16}", .{ frame.rax, frame.rbx, frame.rcx, frame.rdx });
std.log.err("RSI=0x{x:0>16} RDI=0x{x:0>16} RBP=0x{x:0>16} RSP=0x{x:0>16}", .{ frame.rsi, frame.rdi, frame.rbp, frame.rsp });
std.log.err("R8= 0x{x:0>16} R9=0x{x:0>16} R10=0x{x:0>16} R11=0x{x:0>16}", .{ frame.r8, frame.r9, frame.r10, frame.r11 });
std.log.err("R12=0x{x:0>16} R13=0x{x:0>16} R14=0x{x:0>16} R15=0x{x:0>16}", .{ frame.r12, frame.r13, frame.r14, frame.r15 });
const cr2 = amd64.read_cr(2);
const cr3 = amd64.read_cr(3);
const rflags = amd64.rflags();
std.log.info("CR2=0x{x:0>16} CR3=0x{x:0>16} RFLAGS={x}", .{ cr2, cr3, @as(u64, @bitCast(rflags)) });
@panic("Unhandled exception");
var buf: [128]u8 = undefined;
var writer = std.Io.Writer.fixed(&buf);
writer.print("0x{x:0>8} [", .{@as(u64, @bitCast(rflags))}) catch {};
if (rflags.carry) writer.writeAll(" CF") catch {};
if (rflags.parity) writer.writeAll(" PF") catch {};
if (rflags.auxiliary) writer.writeAll(" AF") catch {};
if (rflags.zero) writer.writeAll(" ZF") catch {};
if (rflags.sign) writer.writeAll(" SF") catch {};
if (rflags.trap) writer.writeAll(" TF") catch {};
if (rflags.interrupt_enable) writer.writeAll(" IF") catch {};
if (rflags.direction) writer.writeAll(" DF") catch {};
if (rflags.overflow) writer.writeAll(" OF") catch {};
if (rflags.resume_) writer.writeAll(" RF") catch {};
if (rflags.virtual_8086_mode) writer.writeAll(" VM") catch {};
writer.print(" IOPL={d}]", .{rflags.iopl}) catch {};
std.log.err("CR2=0x{x:0>16} CR3=0x{x:0>16} RFLAGS={s}", .{ cr2, cr3, buf[0..writer.end] });
ki.panic.panic_with_frame("Unhandled exception", frame.rbp);
}
}
+82 -5
View File
@@ -1,15 +1,92 @@
const std = @import("std");
const config = @import("config");
const b = @import("base");
const ksyms = @import("ksyms");
const ke = b.ke;
const ki = ke.private;
extern var text_start_addr: u8;
extern var text_end_addr: u8;
const StackFrame = struct {
prev: ?*StackFrame,
return_addr: usize,
};
const Symbol = struct {
name: []const u8,
offset: usize,
};
fn get_symbol_name(addr: usize) ?Symbol {
const symbols = ksyms.get_symbols();
// Do a binary search on the ksyms array.
// The address may not be exact, so we look for the closest
// symbol that is less than or equal to the address.
var left: usize = 0;
var right: usize = symbols.len;
while (left < right) {
const mid = left + (right - left) / 2;
const sym = symbols[mid];
if (sym.addr == addr) {
return .{ .name = sym.name_ptr[0..sym.name_len], .offset = 0 };
} else if (sym.addr < addr) {
left = mid + 1;
} else {
right = mid;
}
}
if (left > 0) {
const sym = symbols[left - 1];
if (sym.addr <= addr) {
return .{ .name = sym.name_ptr[0..sym.name_len], .offset = addr - sym.addr };
}
}
return null;
}
fn is_kernel_text(addr: usize) bool {
const s = @intFromPtr(&text_start_addr);
const e = @intFromPtr(&text_end_addr);
return addr >= s and addr < e;
}
fn walk_stack_frame(base: usize) void {
var frame: ?*StackFrame = @ptrFromInt(base);
var depth: usize = 0;
while (frame) |f| : (depth += 1) {
if (depth > 64) break;
const ret_addr = f.return_addr;
if (!is_kernel_text(ret_addr)) {
break;
}
const sym = get_symbol_name(ret_addr) orelse Symbol{ .name = "???", .offset = 0 };
std.log.err(" #{d} {s}+0x{x} - 0x{x}", .{ depth, sym.name, sym.offset, ret_addr });
frame = f.prev;
}
}
pub fn panic_with_frame(
msg: []const u8,
frame: usize,
) noreturn {
std.log.err("KERNEL PANIC: {s}", .{msg});
std.log.err("Stack trace:", .{});
walk_stack_frame(frame);
while (true) {}
}
pub fn panic(
msg: []const u8,
first_trace_addr: ?usize,
) noreturn {
_ = first_trace_addr;
std.log.err("KERNEL PANIC: {s}", .{msg});
while (true) {}
if (@hasDecl(config, "CONFIG_ARCH_UM")) {
std.debug.defaultPanic(msg, first_trace_addr);
}
panic_with_frame(msg, @frameAddress());
}
+13
View File
@@ -0,0 +1,13 @@
pub const KSym = extern struct {
addr: u64,
name_ptr: [*]const u8,
name_len: usize,
};
extern const ksyms_array: [0]KSym;
extern const ksyms_count: usize;
pub fn get_symbols() []const KSym {
const ptr = @as([*]const KSym, @ptrCast(&ksyms_array));
return ptr[0..ksyms_count];
}