Skip to content

Instantly share code, notes, and snippets.

@rgreenblatt
Created February 6, 2021 02:15
Show Gist options
  • Save rgreenblatt/b6933aba1d979112baade97d683ee3e0 to your computer and use it in GitHub Desktop.
Save rgreenblatt/b6933aba1d979112baade97d683ee3e0 to your computer and use it in GitHub Desktop.
Won't work without some changes.
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