Created
February 6, 2021 02:15
-
-
Save rgreenblatt/b6933aba1d979112baade97d683ee3e0 to your computer and use it in GitHub Desktop.
Won't work without some changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const builtin = @import("builtin"); | |
const std = @import("std"); | |
const assert = std.debug.assert; | |
const log = std.log.scoped(.debug); | |
const build_options = @import("build_options"); | |
const log_writer = @import("log.zig").Writer{.context = {}}; | |
const c = @import("c.zig"); | |
extern var __debug_info_start: u8; | |
extern var __debug_info_end: u8; | |
extern var __debug_abbrev_start: u8; | |
extern var __debug_abbrev_end: u8; | |
extern var __debug_str_start: u8; | |
extern var __debug_str_end: u8; | |
extern var __debug_line_start: u8; | |
extern var __debug_line_end: u8; | |
extern var __debug_ranges_start: u8; | |
extern var __debug_ranges_end: u8; | |
fn get_slice_start_end(start: *const u8, end: *const u8) []const u8 { | |
return @ptrCast([*]const u8, start)[0 .. @ptrToInt(end) - @ptrToInt(start)]; | |
} | |
var kernel_panic_allocator_bytes: [32 * 1024]u8 = undefined; | |
var kernel_panic_allocator_state = std.heap.FixedBufferAllocator.init(kernel_panic_allocator_bytes[0..]); | |
const kernel_panic_allocator = &kernel_panic_allocator_state.allocator; | |
pub fn getSelfDebugInfo() !*std.dwarf.DwarfInfo { | |
const S = struct { | |
var self_debug_info: ?std.dwarf.DwarfInfo = null; | |
}; | |
if (S.self_debug_info != null) return &S.self_debug_info.?; | |
log.warn("__debug_info_start: {}\n", .{&__debug_info_start}); | |
log.warn("__debug_info_end: {}\n", .{&__debug_info_end}); | |
log.warn("__debug_abbrev_start: {}\n", .{&__debug_abbrev_start}); | |
log.warn("__debug_abbrev_end: {}\n", .{&__debug_abbrev_end}); | |
log.warn("__debug_line_start: {}\n", .{&__debug_line_start}); | |
log.warn("__debug_line_end: {}\n", .{&__debug_line_end}); | |
log.warn("__debug_ranges_start: {}\n", .{&__debug_ranges_start}); | |
log.warn("__debug_ranges_end: {}\n", .{&__debug_ranges_end}); | |
S.self_debug_info = std.dwarf.DwarfInfo{ | |
.endian = builtin.Endian.Little, | |
.debug_info = get_slice_start_end(&__debug_info_start, &__debug_info_end), | |
.debug_abbrev = get_slice_start_end(&__debug_abbrev_start, &__debug_abbrev_end), | |
.debug_str = get_slice_start_end(&__debug_str_start, &__debug_str_end), | |
.debug_line = get_slice_start_end(&__debug_line_start, &__debug_line_end), | |
.debug_ranges = get_slice_start_end(&__debug_ranges_start, &__debug_ranges_end), | |
.abbrev_table_list = undefined, | |
.compile_unit_list = undefined, | |
.func_list = undefined, | |
// .dwarf_seekable_stream = S.seekable_stream, | |
// .dwarf_in_stream = S.in_stream, | |
}; | |
try std.dwarf.openDwarfDebugInfo(&S.self_debug_info.?, kernel_panic_allocator); | |
return &S.self_debug_info.?; | |
} | |
var already_panicking: bool = false; | |
pub fn panic(stack_trace: ?*builtin.StackTrace, comptime fmt: []const u8, args: anytype) noreturn { | |
@setCold(true); | |
if (already_panicking) { | |
log.emerg("\npanicked during kernel panic", .{}); | |
panicHalt(); | |
} | |
already_panicking = true; | |
log.emerg("panic: " ++ fmt, args); | |
const first_trace_addr = @returnAddress(); | |
if (stack_trace) |t| { | |
dumpStackTrace(t); | |
} | |
dumpCurrentStackTrace(first_trace_addr); | |
panicHalt(); | |
} | |
fn panicHalt() noreturn { | |
asm volatile ("cli; hlt"); | |
while (true) {} | |
} | |
fn dwarfSectionFromSymbolAbs(start: *u8, end: *u8) std.dwarf.DwarfInfo.Section { | |
return std.dwarf.DwarfInfo.Section{ | |
.offset = 0, | |
.size = @ptrToInt(end) - @ptrToInt(start), | |
}; | |
} | |
fn dwarfSectionFromSymbol(start: *u8, end: *u8) std.dwarf.DwarfInfo.Section { | |
return std.dwarf.DwarfInfo.Section{ | |
.offset = @ptrToInt(start), | |
.size = @ptrToInt(end) - @ptrToInt(start), | |
}; | |
} | |
pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void { | |
const dwarf_info = getSelfDebugInfo() catch |err| { | |
log.emerg("Unable to dump stack trace: Unable to open debug info: {}", .{@errorName(err)}); | |
return; | |
}; | |
writeStackTrace(stack_trace, dwarf_info) catch |err| { | |
log.emerg("Unable to dump stack trace: {}", .{@errorName(err)}); | |
return; | |
}; | |
} | |
pub fn dumpCurrentStackTrace(start_addr: ?usize) void { | |
const dwarf_info = getSelfDebugInfo() catch |err| { | |
log.emerg("Unable to dump stack trace: Unable to open debug info: {}", .{@errorName(err)}); | |
return; | |
}; | |
writeCurrentStackTrace(dwarf_info, start_addr) catch |err| { | |
log.emerg("Unable to dump stack trace: {}", .{@errorName(err)}); | |
return; | |
}; | |
} | |
fn printLineFromBuffer(writer: anytype, contents: []const u8, line_info: std.debug.LineInfo) anyerror!void { | |
var line: usize = 1; | |
var column: usize = 1; | |
var abs_index: usize = 0; | |
for (contents) |byte| { | |
if (line == line_info.line) { | |
try writer.writeByte(byte); | |
if (byte == '\n') { | |
return; | |
} | |
} | |
if (byte == '\n') { | |
line += 1; | |
column = 1; | |
} else { | |
column += 1; | |
} | |
} | |
return error.EndOfFile; | |
} | |
fn printLineFromFileEmbed(writer: anytype, line_info: std.debug.LineInfo) anyerror!void { | |
inline for (build_options.source_files) |src_path| { | |
if (std.mem.endsWith(u8, line_info.file_name, src_path)) { | |
const contents = @embedFile("../" ++ src_path); | |
try printLineFromBuffer(writer, contents[0..], line_info); | |
return; | |
} | |
} | |
try writer.print("(source file {} not added in std/debug.zig)\n", .{line_info.file_name}); | |
} | |
// sad copy paste from debug.zig | |
const SymbolInfo = struct { | |
symbol_name: []const u8 = "???", | |
compile_unit_name: []const u8 = "???", | |
line_info: ?std.debug.LineInfo = null, | |
}; | |
// sad copy paste from debug.zig | |
pub fn getSymbolAtAddress( | |
dwarf: *std.dwarf.DwarfInfo, | |
in_address: usize, | |
) !SymbolInfo { | |
// TODO: relocation?!?!?! | |
// Translate the VA into an address into this object | |
// const relocated_address = in_address - base_address; | |
const addr = in_address; | |
if (nosuspend dwarf.findCompileUnit(addr)) |compile_unit| { | |
return SymbolInfo{ | |
.symbol_name = nosuspend (dwarf.getSymbolName(addr) orelse "???"), | |
.compile_unit_name = compile_unit.die.getAttrString( | |
dwarf, | |
std.dwarf.AT_name, | |
) catch |err| switch (err) { | |
error.MissingDebugInfo, error.InvalidDebugInfo => "???", | |
else => return err, | |
}, | |
.line_info = nosuspend dwarf.getLineNumberInfo( | |
compile_unit.*, | |
addr, | |
) catch |err| switch (err) { | |
error.MissingDebugInfo, error.InvalidDebugInfo => null, | |
else => return err, | |
}, | |
}; | |
} else |err| switch (err) { | |
error.MissingDebugInfo, error.InvalidDebugInfo => { | |
return SymbolInfo{}; | |
}, | |
else => return err, | |
} | |
unreachable; | |
} | |
fn printSourceAtAddress(dwarf_info: *std.dwarf.DwarfInfo, address: usize) !void { | |
const symbol_info = try getSymbolAtAddress(dwarf_info, address); | |
return std.debug.printLineInfo( | |
log_writer, | |
symbol_info.line_info, | |
address, | |
symbol_info.symbol_name, | |
symbol_info.compile_unit_name, | |
.escape_codes, | |
printLineFromFileEmbed, | |
); | |
} | |
fn writeCurrentStackTrace(dwarf_info: *std.dwarf.DwarfInfo, start_addr: ?usize) !void { | |
var it = std.debug.StackIterator.init(start_addr, null); | |
while (it.next()) |return_address| { | |
try printSourceAtAddress(dwarf_info, return_address); | |
} | |
} | |
fn writeStackTrace(stack_trace: *const builtin.StackTrace, dwarf_info: *std.dwarf.DwarfInfo) !void { | |
var frame_index: usize = undefined; | |
var frames_left: usize = undefined; | |
if (stack_trace.index < stack_trace.instruction_addresses.len) { | |
frame_index = 0; | |
frames_left = stack_trace.index; | |
} else { | |
frame_index = (stack_trace.index + 1) % stack_trace.instruction_addresses.len; | |
frames_left = stack_trace.instruction_addresses.len; | |
} | |
while (frames_left != 0) : ({ | |
frames_left -= 1; | |
frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len; | |
}) { | |
const return_address = stack_trace.instruction_addresses[frame_index]; | |
try printSourceAtAddress(dwarf_info, return_address); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment