mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-29 06:28:21 +00:00
feat: better panic handler
This commit is contained in:
+27
-7
@@ -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
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
Reference in New Issue
Block a user