Debugging the Ubuntu 6.8 x86_64 Kernel with GDB & QEMU — Without Rebuilding
Field notes from attaching GDB to a running Ubuntu 6.8 x86_64 kernel inside QEMU, disabling KASLR without rebuilding, and finding the bug that wasn't in source — it was in address space reality.
Status: Companion blog draft for the existing video. Long-form transcript + bridge framing TBD.
Companion assets
- Original video:
Debugging Ubuntu 6.8 x86_64 Kernel with GDB & QEMU | Disable KASLR Without Rebuild
- GitHub: harrison001/CoreTracer
TL;DR
You can attach GDB to a stock Ubuntu 6.8 kernel running inside QEMU and walk through it with full symbols — without rebuilding the kernel. The trick is disabling KASLR at boot time so GDB’s symbol map matches the kernel’s runtime addresses. Once aligned, you can debug anything from page-fault handling to syscall entry points. The lesson generalizes: many “kernel-level bugs” aren’t source bugs — they’re address-space-reality bugs.
The setup
- Ubuntu 6.8 kernel image (stock, debug-symbol package installed)
- QEMU/KVM hosting it
- GDB on the host, attaching over the QEMU gdb stub
- Boot param:
nokaslrto align addresses
Debug command transcript
# TODO: paste actual command sequence from the video
# qemu-system-x86_64 -kernel vmlinuz-6.8 -initrd initrd.img -append "console=ttyS0 nokaslr" -s -S
# gdb vmlinux-6.8
# (gdb) target remote :1234
# (gdb) break do_page_fault
# (gdb) c
What broke
GDB connected fine, but every breakpoint silently missed. The kernel was running, but GDB believed every function lived at a different address than it actually did.
Root cause: KASLR moved the kernel, but GDB still believed the old map. Standard symbol files describe load-time addresses; KASLR randomizes them at boot. GDB’s view of vmlinux and the running kernel’s reality had drifted apart by a random offset.
What fixed it
Boot the kernel with nokaslr so symbol addresses match the static vmlinux file. No kernel rebuild needed — the debug symbols package already has what’s required; the alignment was the missing piece.
For investigations where disabling KASLR isn’t acceptable, the alternative is to compute the runtime offset (kaslr_offset) by inspecting a known symbol and rewriting GDB’s add-symbol-file with the offset applied.
What this teaches backend / AI infra engineers
This is the canonical example of a bug class that has nothing to do with the code and everything to do with the address space your tools assume vs. the address space that exists at runtime. Production analogues:
- Coredump symbolication in Go: if your binary was built with PIE on one machine and the symbols you’re loading were generated against a slightly different build, your stack traces will be wrong addresses with the right shape — and lead you to chase a phantom bug
- eBPF programs that hook kernel addresses: if the running kernel has different layout than your symbol source, the program either fails to attach or attaches to the wrong function
- AI inference profiles: GPU traces that point to “kernel X” are using symbols from a CUDA toolchain version that may not match what’s actually running
The pattern: when a debugger says nothing is happening, often it’s because the debugger is looking in the wrong place.
Related work
- Video: Custom ARM64 Linux Kernel Debug — same workflow, different arch
- Companion blog (TBD): “Symbol mismatch in production: when your tracer lies to you”
🎧 More Ways to Consume This Content
I occasionally advise small teams on backend reliability, Go performance, and production AI systems. Learn more: /services
Comments
This space is waiting for your voice.
Comments will be supported shortly. Stay connected for updates!
This section will display user comments from various platforms like X, Reddit, YouTube, and more. Comments will be curated for quality and relevance.
Have questions? Reach out through:
Want to see your comment featured? Mention us on X or tag us on Reddit.
Leave a Comment