Troubleshooting: Difference between revisions

Jump to navigation Jump to search
m
Fixed grammar error, consistency fixes
[unchecked revision][unchecked revision]
m (Interwiki)
m (Fixed grammar error, consistency fixes)
Line 1:
== Providing a basic debugging environment ==
=== Exception handlers ===
 
The first thing ever to do is to implement a reliable 'exception handler' which will tell you what went wrong. Under an emulator like [[Bochs]], the absence of such a handler will lead to a '3rd Exception without resolution' panic message (a.k.a [[Triple Fault]]), if the emulator is configured to do so... On bare hardware, it will simply reset your computer with a laconic 'bip'.
 
Line 42 ⟶ 41:
 
==== What to do if characters cannot be displayed ====
 
Such things occurs for instance when your GDT or paging tables has been badly configured (e.g. 0xb8000 no longer refers to the video memory). Fortunately enough, the video memory is not your sole communication technique with your kernel:
* you may use the [[PS2 Keyboard|keyboard]] LEDs to report some events (for instance enabling the 'scroll lock' LED when you're a handler and disabling it when you're out).
Line 51 ⟶ 49:
 
==== Avoiding exception loops ====
 
So we know when exceptions occur and which exception occurred. That's better but still not especially useful. Your exception handler is likely to become something complex as your kernel will evolve, and you'll discover that exceptions mainly occur ... in exception handlers.
 
Line 75 ⟶ 72:
 
==== Showing the stack content ====
Much of youyour program's state (function arguments, return address, local variables) is stored on the [[stack]], especially when using C/C++ code. A complete debugger (like GDB) will inspect the debugging info to give names to the stack content, provide a list of calls, etc. This is a bit complex forto do usourselves, but if your kernel can simply ''show'' the content of the stack and if you know ''where'' in the code the process halted, you can already fix quite a lot of bugs by doing the job of the debugger yourself, guessing which stack location holds which variable, where arethe return addresses are, etc.
 
The stack content is still in memory. The [[EBP]] value of the erroring process is still in memory, and points to the start of the stack frame for the current function. Everything from this address and up was the current stack. Now, you can use the value in ebp as the source. Just use the following call:
Line 91 ⟶ 88:
 
==== Locating the Faulty instruction ====
 
In most cases, when your exception handler is called, the address of the faulty instruction is somewhere on the stack. The first step here is to print out the address of this instruction.
 
Line 135 ⟶ 131:
 
=== Enhanced debugging techniques ===
 
==== Stack tracing ====
 
By analyzing the default way to create a stack frame, you can rip off a stack frame at a time, resulting in the call sequence that lead to the fault. For a single bonus point, also extract the arguments and dump them as well. For multiple bonus points, use C++ name mangling, and export the arguments in readable form in the correct type.
 
Line 173 ⟶ 167:
Now, you can traverse along the path of execution. The content of EBP is the old value of EBP, that is, the one of the last stack frame. The value above that is the old instruction pointer (which points inside the current function), and the values above that, up to but not including the value pointed to by the old EBP, are the arguments. Note that the arguments don't have to belong to this function, GCC occasionally saves an add to esp by not popping the values. By then pretending the old EBP is the current EBP, you can unwind another call. Do this until you are fed up by it, you have enough output or the stack ends. If the last one, watch out for not generating a double fault.
 
If you use C++ name mangling, the arguments are encoded in the function name. If you can read that, you can decode what the value on the stack must be, so you can actually present it to the user in the form of a normal function call with legible arguments and everything. This is the creme'crème de la cremecrème' of stack dumping methods, so most aren't expected to do this.
 
While I program my kernel in C, I actually thought of writing a script that would parse the header files for function declarations, extract the debugging symbols from the compiled kernel image using <tt>objdump</tt>, and write a system map which would provide the types. Forgot it after falling in love with BOCHS[[Bochs]]'s debugger though. Similarly, typemaps for structured types could be created, which would allow the same kind of browsing that GDB or [[Visual Studio]] give you. THIS would be the cremecrème de la cremecrème.
 
=== Debugging techniques ===
Line 233 ⟶ 227:
 
=== Debugging interface ===
 
''Now we have plenty of information about what was wrong... can we ask for more ? what do Mobius' debugging shell and Clicker's information panels tell us ...''
 
252

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu