Troubleshooting: Difference between revisions

Jump to navigation Jump to search
m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Bot: Replace deprecated source tag with syntaxhighlight)
Line 9:
 
<!-- The following code example should be more generalized (e.g. exc_0d_handler, gpfExcHandler renamed to more meaningful names).-->
<sourcesyntaxhighlight lang="asm">
exc_0d_handler:
push gs
Line 37:
pop gs
iret
</syntaxhighlight>
</source>
 
Once you have implemented such a technique, it may be wise to test it, deliberately issuing 'faulty' instructions to see if the correct code is displayed. Having the 'double fault' exception (08) displayed somewhere else on the screen may also be a smart move.
Line 54:
In order to avoid recursive exceptions to occur endlessly, you can easily maintain a 'nested exceptions counter' that will be incremented every time you enter an exception handler and decremented just before you leave that handler. If the counter is above a certain threshold of a few units (3 should give interesting enough results), the kernel will abort trying to solve the exception and enter a 'panic' mode (red background, flashing LED, whatever).
 
<sourcesyntaxhighlight lang="c">
int nestexc = 0;
 
Line 68:
return;
}
</syntaxhighlight>
</source>
 
You need to know, of course, that some exceptions are not 'resumable'. If your kernel issued a division by zero, trying to return to the 'div' instruction will only trigger the exception one more time (yeah! altogether, now :). Such loops cannot be solved by the 'nestexc' counter
Line 77:
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:
 
<sourcesyntaxhighlight lang="asm">
stack_dump:
push ebp
Line 84:
pop ebp
ret ; note that this is not going to work, but it should be here for completion.
</syntaxhighlight>
</source>
 
and use <tt>void dump_hex(char *stack)</tt>.
Line 144:
Each time a function is called it gets the following head/tail: ([[GCC]] 3.3.2)
 
<sourcesyntaxhighlight lang="asm">
push ebp
mov ebp, esp
Line 150:
leave
ret
</syntaxhighlight>
</source>
 
On the place of the ... the rest of the code is filled in. Now, if you analyze the stack output, it looks something like:
Line 182:
If your function <tt>x()</tt> wreaks havoc only after 1000 calls it may not suffice to put a <tt>panic()</tt> statement inside the functions to see where the functions breaks. You may want to know which call is malignant. To do this, one might use a global or static var to count calls and panic() after an amount to see if it managed to crash. If not, you try twice that amount; if it does crash, you try bisection to find the amount.
 
<sourcesyntaxhighlight lang="c">
void scheduler_choose_task() {
static uint32_t Z=0;
Line 191:
...
}
</syntaxhighlight>
</source>
...and then check how far does it go:
<sourcesyntaxhighlight lang="c">
Z++;
uint32_t N = 1000;
Line 199:
if (in_critical_section()) return;
if (Z > N) panic(); //do we get here to panic() before a crash?
</syntaxhighlight>
</source>
However as complexity rises or multithreading is involved, it is less probable that a crash would be consistently occurring at the same point, after the same amount of calls every time. Then it would not be possible to find the number of the call to <tt>scheduler_choose_talk()</tt> that crashes it (because that number changes). Debugging needs some imagination; what if you knew, by tracing the program flow with <tt>print(__LINE__)</tt> that <tt>scheduler_choose_task()</tt> crashes only when a call to <tt>fun1()</tt> is in progress? You might use a global var <tt>uint32_t dbg</tt> or an array (<tt>uint32_t dbg[20]</tt>) of various <tt>dbg</tt> vars (which are used only in debugging code which is cleaned after the programmer ceases to debug) in a manner such as:
<sourcesyntaxhighlight lang="c">
void fun1() {
dbg[3] = 1;
Line 209:
dbg[3] = 0;
}
</syntaxhighlight>
</source>
...and:
<sourcesyntaxhighlight lang="c">
void scheduler_choose_task() {
// if (dbg[3]==1) panic(); //check here.. a panic saves the day from crashing!
Line 217:
if (dbg[3]==1) panic(); //check here.. it crashes
}
</syntaxhighlight>
</source>
(Or mix it with a call count, <tt>Z++; if (Z>5 && dbg[3] == 1) panic()</tt>.)
 
Using the <tt>__LINE__</tt> aids tracing the program flow:
<sourcesyntaxhighlight lang="c">
print(__LINE__);
</syntaxhighlight>
</source>
See [[C preprocessor#Uses for debugging|Uses for debugging]] for more info.
 
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu