Kernel Debugging: Difference between revisions

Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content deleted Content added
mNo edit summary
Line 9: Line 9:
useless when it's the OS itself that you want to debug.
useless when it's the OS itself that you want to debug.


Debugging is essentialy being able to probe the contents of a variable at a specific breakpoint.
Debugging is essentially being able to probe the contents of a variable at a specific breakpoint.
When your program hits the breakpoint, you can probe the variable.
When your program hits the breakpoint, you can probe the variable.


Line 37: Line 37:
VM might not even behave exactly like the "real" hardware.
VM might not even behave exactly like the "real" hardware.


That being said, there are also alot of other advantages to using a VM.
That being said, there are also a lot of other advantages to using a VM.
For example, you don't have to reboot to test your new OS, you just start the VM.
For example, you don't have to reboot to test your new OS, you just start the VM.


Line 64: Line 64:
(Replace localhost with remote IP / URL if necessary.) Then start execution:
(Replace localhost with remote IP / URL if necessary.) Then start execution:


But thats not all, you can compile your source code under gcc with debuging symbols using "-g". This will add all the debuging symbols in the kernel image itself (Thus making it bigger ). There is also a way to put all of the debugging information in a separate file using the "objcopy" tool, which is part of the GNU binutils package.
But that's not all, you can compile your source code under gcc with debugging symbols using "-g". This will add all the debugging symbols in the kernel image itself (Thus making it bigger ). There is also a way to put all of the debugging information in a separate file using the "objcopy" tool, which is part of the GNU binutils package.


objcopy --only-keep-debug kernel.elf kernel.sym
objcopy --only-keep-debug kernel.elf kernel.sym
Line 109: Line 109:
(gdb) info registers
(gdb) info registers


I won't start explaining all the nice things about gdb, but as you can see, it is a very powerfull tool for debuging OSes.
I won't start explaining all the nice things about gdb, but as you can see, it is a very powerfull tool for debugging OSes.


== Develop in hosted environment ==
== Develop in hosted environment ==
Another possibility, which is also a great architectural exercise, is to code every software module in a hosted environment like Linux, and then port it to your OS. You can do this for kernel code too, not just usermode programs.
Another possibility, which is also a great architectural exercise, is to code every software module in a hosted environment like Linux, and then port it to your OS. You can do this for kernel code too, not just usermode programs.


Suppose you want to develop your VFS interface implementation. Your already created the interface for block devices (doesn't matter if you already implemented it in your kernel). In this case, you can implement your block device interface as a set of wrappers that [http://en.wikipedia.org/wiki/Adapter_pattern adapts] your interface to POSIX calls. You will then implement your VFS interface (i.e., the code that will manage the filesystem drivers in your kernel) on top of those wrappers. You will then test&debug your implementation all in the hosted environment, and when it is mature, you link it into your real kernel instead of into your hosted implementations. You will finally test your newly introduced code, now in the freestanding environmentm to ensure it works there as well.
Suppose you want to develop your VFS interface implementation. Your already created the interface for block devices (doesn't matter if you already implemented it in your kernel). In this case, you can implement your block device interface as a set of wrappers that [http://en.wikipedia.org/wiki/Adapter_pattern adapts] your interface to POSIX calls. You will then implement your VFS interface (i.e., the code that will manage the filesystem drivers in your kernel) on top of those wrappers. You will then test&debug your implementation all in the hosted environment, and when it is mature, you link it into your real kernel instead of into your hosted implementations. You will finally test your newly introduced code, now in the freestanding environment to ensure it works there as well.


Now, the Pros. First of all, you can use your favourite debugger. You can also use unit testing, for example, which is far better than testing software by hand, if you use the right method.
Now, the Pros. First of all, you can use your favourite debugger. You can also use unit testing, for example, which is far better than testing software by hand, if you use the right method.


There are some Cons on this approach. For example, you are far from your target environment when you code like this. This is further agravated by the fact that so-called ''freestanding'' environments are dramatically more sensible to undefined behaviour, specially unitilialized variables. You can workarround this limitation by asking the compiler to perform aggressive optimization while testing hosted, which make software more sensible to undefined behaviour, too. However, as the best debug environment is the final target environment, you will still want to test your code when you introduce in into your real kernel.
There are some Cons on this approach. For example, you are far from your target environment when you code like this. This is further aggravated by the fact that so-called ''freestanding'' environments are dramatically more sensible to undefined behaviour, specially uninitialized variables. You can work around this limitation by asking the compiler to perform aggressive optimization while testing hosted, which make software more sensible to undefined behaviour, too. However, as the best debug environment is the final target environment, you will still want to test your code when you introduce in into your real kernel.


Another Con that will probabilly scare most people is that this approach requires you to consistently plan your interfaces beforehand. Depending on your specific requirements, you may still be able to avoid a too long planning phase. For example, if you want to throw away the hosted implementations once you get the modules working properly, then you don't have to bother maintaining the same interfaces forever.
Another Con that will probably scare most people is that this approach requires you to consistently plan your interfaces beforehand. Depending on your specific requirements, you may still be able to avoid a too long planning phase. For example, if you want to throw away the hosted implementations once you get the modules working properly, then you don't have to bother maintaining the same interfaces forever.


== Related Threads ==
== Related Threads ==