How to Effectively Debug Exceptions in an Operating System

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
austanss
Member
Member
Posts: 377
Joined: Sun Oct 11, 2020 9:46 pm
Location: United States

How to Effectively Debug Exceptions in an Operating System

Post by austanss »

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:

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
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:

Code: Select all

c++filt <function-label>
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.
Skylight: https://github.com/austanss/skylight

I make stupid mistakes and my vision is terrible. Not a good combination.

NOTE: Never respond to my posts with "it's too hard".
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: How to Effectively Debug Exceptions in an Operating Syst

Post by nullplan »

Further useful tips: You can pipe the output of any program (including objdump -d) through c++filt to have it demangle the C++ labels inline. You can also use addr2line to translate a code address into a source file and line number.
Carpe diem!
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: How to Effectively Debug Exceptions in an Operating Syst

Post by nexos »

nullplan wrote:You can also use addr2line to translate a code address into a source file and line number.
addr2line has saved me from disaster more then once. I probably should get a bit more familiar with GDB, most of my debugger knowledge is in VS.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Post Reply