SchOS/.gdbinit
Nexoniarz 6c70040f57 build: a gdb target, because the tree had no source-level debugger
QEMU carries a gdb stub and exposing it costs two flags. `make qemu-gdb` holds
the machine before its first instruction and waits on port 26000; attach and
you get breakpoints, single-stepping and symbols in kernel code -- including
the early boot the crash screen cannot reach and the serial console has not
started for.

.gdbinit does the connecting, and documents the one confusing part rather than
leaving it to be rediscovered: at the reset vector a breakpoint on a kernel
symbol fails with "Cannot access memory at 0xffff8000...", because the kernel
links into the high half and nothing is mapped there until it enables paging.
Symbols resolve fine -- gdb knows kmain is main.c:32 -- the address just is not
addressable yet. Continue, let it boot, interrupt, and everything works.

This is for QEMU. On hardware with no serial port the tools are the on-screen
kernel log and PSOGM's QR code, which is what that QR code has always been for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
2026-09-13 15:05:46 +02:00

39 lines
1.4 KiB
Text

# SchOS kernel debugging.
#
# gdb refuses to auto-load this unless the directory is trusted. Once, in
# ~/.gdbinit:
#
# add-auto-load-safe-path /home/nexoniarz/Dokumenty/Projects/SchOS
#
# Then: make qemu-gdb (one terminal)
# gdb build/kernel/kernel (another)
set confirm off
set architecture i386:x86-64
target remote 127.0.0.1:26000
# You are stopped at the reset vector, 0xfff0, with the firmware not yet run.
#
# A breakpoint on a kernel symbol will NOT take here, and the error is
# confusing rather than wrong:
#
# Cannot insert breakpoint 1. Cannot access memory at 0xffff800000104fc2
#
# The kernel links at 0xffff8000_00000000 and nothing is mapped there until it
# turns paging on. Symbols resolve -- gdb knows kmain is main.c:32 -- but the
# address is not addressable yet.
#
# So: `continue`, let the firmware and the loader run, and interrupt with ^C
# once SchOS is up. Every kernel symbol works from then on, because the high
# half is mapped and stays mapped.
#
# (gdb) continue
# ... SchOS boots ...
# ^C
# (gdb) break vt_switch
# (gdb) continue
#
# For the early boot itself -- entry.S, the long-mode switch, the handoff from
# the loader -- break on the *physical* address instead: the kernel is loaded
# at 1 MB, so `break *0x100000` catches the entry point before paging.
echo \n=== SchOS: stopped at reset. `continue`, then ^C once it boots. ===\n\n