How to Effectively Debug Exceptions in an Operating System
Posted: Sun Jan 31, 2021 12:54 pm
Debugging can be incredibly hard, and when developing an operating system, this is only amplified by the fact that you don't have the same suite of tools at your disposal as in userland programs.
This post will cover how to effectively debug exceptions in an operating system, without using GDB.
The reasoning behind is that you must turn off optimizations and hardware acceleration, which can be tedious switching between, so no external debugger will be used here.
1. The tools
You might need the c++filt program if your kernel is in C++.
You can use Bochs, which can be very helpful in debugging, but in this post I'll be using QEMU.
Some useful parameters:
2. The code
For debugging, two functions are extremely important.
You will need an itoa function, or similar, and you will need a way to send strings to serial output.
3. The process
When you encounter an exception, take note of the instruction pointer register. This is extremely useful.
When you have an instruction pointer, use objdump -d on your kernel binary to disassemble your kernel.
Look for the instruction at the given instruction pointer. Take note of it.
Now, what function are you in? The objump output has labels at the beginning of the function.
If your kernel is written in C++, the label will look like garbage. To find out it's proper demangled name, copy the label,
and run:
and it will output the proper name of the function.
If you can read assembly fluently, then you can know which line of your code the instruction belongs to.
If not, just remember the function's name.
Now, you will start moving breakpoints.
Find the suspicious line of code in your source file, and notify serial output when you have reached it.
If you never get the notification, move it up.
If you do, move it down.
If the line of code is a function call, move into the new function and move the breakpoints there.
The goal is to find the single line of code that raises the exception.
If you have found the issue: congrats! You found the bug!
If not, check the parameters.
Check every value that affects the code.
Use your serial monitor and your itoa function.
If you find an invalid value, check where it came from.
If it came from a return value in a function, well then, you have found the root cause.
Congrats, you found the bug.
-=-=-=-=-=-
Thanks for reading this post. I hope it was informational. I am trying to repay the debt I owe this community for all the help I have asked of you all, by hopefully helping others.
This post will cover how to effectively debug exceptions in an operating system, without using GDB.
The reasoning behind is that you must turn off optimizations and hardware acceleration, which can be tedious switching between, so no external debugger will be used here.
1. The tools
You might need the c++filt program if your kernel is in C++.
You can use Bochs, which can be very helpful in debugging, but in this post I'll be using QEMU.
Some useful parameters:
Code: Select all
-serial stdio // always use this!!!
-d int // you might want to use this if your exception handlers are broken
-no-shutdown //////
-no-reboot // use these two in conjunction so you can read out register dumps, but not always essential
For debugging, two functions are extremely important.
You will need an itoa function, or similar, and you will need a way to send strings to serial output.
3. The process
When you encounter an exception, take note of the instruction pointer register. This is extremely useful.
When you have an instruction pointer, use objdump -d on your kernel binary to disassemble your kernel.
Look for the instruction at the given instruction pointer. Take note of it.
Now, what function are you in? The objump output has labels at the beginning of the function.
If your kernel is written in C++, the label will look like garbage. To find out it's proper demangled name, copy the label,
and run:
Code: Select all
c++filt <function-label>
If you can read assembly fluently, then you can know which line of your code the instruction belongs to.
If not, just remember the function's name.
Now, you will start moving breakpoints.
Find the suspicious line of code in your source file, and notify serial output when you have reached it.
If you never get the notification, move it up.
If you do, move it down.
If the line of code is a function call, move into the new function and move the breakpoints there.
The goal is to find the single line of code that raises the exception.
If you have found the issue: congrats! You found the bug!
If not, check the parameters.
Check every value that affects the code.
Use your serial monitor and your itoa function.
If you find an invalid value, check where it came from.
If it came from a return value in a function, well then, you have found the root cause.
Congrats, you found the bug.
-=-=-=-=-=-
Thanks for reading this post. I hope it was informational. I am trying to repay the debt I owe this community for all the help I have asked of you all, by hopefully helping others.