Debugging Overview
Aeolos provides multiple debugging mechanisms to help you diagnose issues and understand kernel behavior:- Serial output - Real-time kernel logs via COM1
- Kernel logging system - Structured logging with color-coded levels
- Symbol table - Function names in stack traces
- QEMU debugging - GDB integration for low-level debugging
Serial Output
How It Works
Aeolos initializes COM1 (serial port 0x3F8) at 9600 baud and sends all kernel log output to it. This is implemented inkernel/dev/serial/serial.c:4-15:
klog() automatically sends output to the serial port via serial_send() in kernel/lib/klog.c:23.
Capturing Serial Output in QEMU
- To File
- To Terminal
- To TCP Socket
Redirect serial output to a file:Monitor in real-time:
Kernel Logging System
Log Levels
Aeolos uses color-coded log levels defined inkernel/lib/klog.c:180-195:
LOG_INFO
General information messages (blue)
LOG_SUCCESS
Successful operations (green)
LOG_WARN
Warning messages (yellow)
LOG_ERROR
Error conditions (red)
Using the Logger
Theklog() function supports printf-style formatting:
Supported Format Specifiers
Fromkernel/lib/klog.c:106-140:
%d- Signed decimal integer%x- Hexadecimal with0xprefix%s- String%b- Boolean (“true” or “false”)%%- Literal percent sign
Ring Buffer
All log output is stored in a ring buffer (kernel/lib/klog.c:11-13):
Kernel Panics and Stack Traces
Panic Behavior
When a critical error occurs,kernel_panic() is called from kernel/sys/panic.c:58-82:
- Disables interrupts
- Halts all other CPU cores
- Prints the panic message in red
- Generates a stack trace
- Displays the log buffer
- Halts the system
The
-no-reboot -no-shutdown QEMU flags keep the VM running after a panic so you can examine the output.Stack Traces
Stack traces use the kernel symbol table to resolve addresses to function names (kernel/sys/panic.c:32-56):
Symbol Table Generation
The kernel build process generates symbols twice (fromkernel/Makefile:46-60):
- Link kernel without symbols
- Extract symbols using
gensymscript - Compile symbols as C code
- Link symbols into final kernel
GDB Debugging with QEMU
Starting a Debug Session
Launch QEMU with GDB server:-s: Start GDB server on TCP port 1234-S: Pause execution at start
Common GDB Commands
Debugging Tips
Debug early boot code
Debug early boot code
The kernel is loaded at virtual address
0xffffffff80000000 (higher half). Set breakpoints relative to this:Inspect page tables
Inspect page tables
Debug SMP initialization
Debug SMP initialization
QEMU’s
-smp 4 flag enables 4 CPUs. Use GDB’s thread commands:View kernel structures
View kernel structures
QEMU Monitor
Access QEMU’s monitor console withCtrl+Alt+2 (return with Ctrl+Alt+1).
Useful monitor commands:
Debugging Techniques
Adding Debug Output
Add temporary debug logging:Asserting Conditions
Use kernel panic for assertions:Tracing Execution Flow
Add entry/exit logging:Memory Debugging
Log memory operations:Common Issues
Triple Fault
Triple Fault
QEMU exits immediately with “Triple fault” - usually indicates:
- Invalid page tables
- Bad IDT/GDT setup
- Stack overflow
Page Fault Loop
Page Fault Loop
Repeating page faults indicate recursive page fault handling. Check:
- IDT exception handlers are mapped correctly
- Kernel stack is valid
- Exception handler doesn’t trigger another fault
No Serial Output
No Serial Output
If you don’t see serial output:
- Ensure serial port is initialized before first log
- Check QEMU serial flag:
-serial stdio - Verify
serial_init()is called in kernel initialization
Deadlock
Deadlock
System hangs with no output:
- Add debug logs before suspected deadlock
- Use QEMU monitor:
info registersshows if CPUs are halted - Check lock ordering in kernel code
Next Steps
Setup
Set up your development environment
Contributing
Learn how to contribute to Aeolos