Skip to content

Instantly share code, notes, and snippets.

@mlugg
Created September 4, 2025 22:43
Show Gist options
  • Select an option

  • Save mlugg/2841dd3c47a69c768cbdc3c156411b5f to your computer and use it in GitHub Desktop.

Select an option

Save mlugg/2841dd3c47a69c768cbdc3c156411b5f to your computer and use it in GitHub Desktop.
ClashOS 0.15.1-ish port
pub fn wfe_hang() noreturn {
while (true) {
asm volatile ("wfe");
}
}
const source_files: []const []const u8 = &.{
"debug.zig",
"video_core_mailboxes.zig",
"bootloader.zig",
"serial.zig",
"video_core_metrics.zig",
"video_core_properties.zig",
"video_core_frame_buffer.zig",
"time.zig",
"main.zig",
"mmio.zig",
"slice_iterator.zig",
};
pub fn printLineFromFile(w: *std.Io.Writer, sl: std.debug.SourceLocation) !void {
const file_contents = inline for (source_files) |path| {
if (std.mem.endsWith(u8, sl.file_name, "src/" ++ path)) {
break @embedFile(path);
}
} else return error.FileNotFound;
var it = std.mem.splitScalar(u8, file_contents, '\n');
for (1..sl.line) |_| {
_ = it.next() orelse return error.EndOfFile;
}
try w.writeAll(it.next() orelse return error.EndOfFile);
try w.writeByte('\n');
}
/// Looks for the symbols `__name` and `__name_len`, which the linker script has
/// populated with the address and length of the section '.name'. Returns `null`
/// if the section is empty or missing.
fn section(comptime name: []const u8) ?[]const u8 {
const start = @extern([*]u8, .{ .name = "__" ++ name });
const len = @intFromPtr(@extern(*anyopaque, .{ .name = "__" ++ name ++ "_len" }));
if (len == 0) return null;
return start[0..len];
}
pub const DebugInfoModule = struct {
comptime name: []const u8 = "clashos",
pub const LookupCache = void;
pub fn lookup(_: *LookupCache, _: Allocator, _: usize) !DebugInfoModule {
return .{};
}
pub fn key(_: *const DebugInfoModule) usize {
return 0;
}
pub const DebugInfo = struct {
pub const init: DebugInfo = .{};
};
pub fn getSymbolAtAddress(_: *const DebugInfoModule, gpa: Allocator, _: *DebugInfo, address: usize) !std.debug.Symbol {
const dwarf = try getDwarf(gpa);
return dwarf.getSymbol(gpa, builtin.target.cpu.arch.endian(), address) catch |err| switch (err) {
error.InvalidDebugInfo, error.MissingDebugInfo, error.OutOfMemory => |e| return e,
error.ReadFailed,
error.EndOfStream,
error.Overflow,
error.StreamTooLong,
=> return error.InvalidDebugInfo,
};
}
};
fn getDwarf(gpa: Allocator) !*Dwarf {
const S = struct {
var dwarf: ?Dwarf = null;
};
if (S.dwarf) |*dwarf| return dwarf;
var dwarf: Dwarf = .{ .sections = s: {
var s: Dwarf.SectionArray = undefined;
inline for (@typeInfo(Dwarf.Section.Id).@"enum".fields) |f| {
s[f.value] = if (section(f.name)) |bytes| .{
.data = bytes,
.owned = false,
} else null;
}
break :s s;
} };
dwarf.open(gpa, builtin.cpu.arch.endian()) catch |err| switch (err) {
error.InvalidDebugInfo, error.MissingDebugInfo, error.OutOfMemory => |e| return e,
else => return error.InvalidDebugInfo,
};
S.dwarf = dwarf;
return &S.dwarf.?;
}
const std = @import("std");
const Allocator = std.mem.Allocator;
const Dwarf = std.debug.Dwarf;
const builtin = @import("builtin");
// ...
pub const DebugInfoModule = debug.DebugInfoModule;
pub const debugPrintLineFromFile = debug.printLineFromFile;
pub const panic = std.debug.FullPanic(panicImpl);
fn panicImpl(msg: []const u8, ra: ?usize) noreturn {
@branchHint(.cold);
const S = struct {
var already_panicking: bool = false;
};
if (S.already_panicking) {
serial.log("\npanicked during kernel panic: {s}", .{msg});
debug.wfe_hang();
}
S.already_panicking = true;
serial.log("KERNEL PANIC: {s}", .{msg});
std.debug.dumpCurrentStackTraceToWriter(ra orelse @returnAddress(), &serial.out, .escape_codes) catch {};
debug.wfe_hang();
}
// ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment