I really hope that this isn't a stupid question. I've been unable to find any answer to this as of yet.

When an executable causes an error and Windows kills it, you get some information along the lines of "TEST caused a general protection fault in...."

If the error occurred within the executable itself, then the address that Windows provides easily allows you to find the problem code.

However, most of the errors occur within a system dll. "TEST caused a general protection fault in module KERNEL32.dll at 0....." and so on. The location that you're given points to where it was at in the system dll, and not where it was last at in the executable itself.

What I'm trying to understand is how to translate a standard GPF such as this, into something meaningful. I want to find out where in my own code Windows was at before my code did something horrible in a system DLL.

GPF's and other errors usually list all the registers and so on. Are there any ways of finding out where we were at in *my* code from a standard windows GPF?

If there isn't, is there any way of being able to add something to my executables so that I can get relevant information in case of an undiscovered bug in my code?

Using a debugger may seem like the most straightforward solution, but I want to also track down bugs that I can't reproduce and that a user mails to me for example.

Any information about this sort of stuff will be very gratefully received.
Posted on 2004-04-01 10:59:50 by turtle
Errors in system DLLs usually means you have passed invalid data to an API function, or that you've forgotten about register preservation. Look at the stack dump (or even better, stack trace in a debugger like ollydbg), and you should be able to find the address in your app that called the dll function.

Also, there really isn't any replacement for running your application in a debugger, even though you might want to look at vkim's debug package. I haven't used it myself (since I swear to debuggers), but it might be worth a look.

As for giving helpful info (or even correcting the error and continuing) in case of an undiscovered bug, you'll most definitely want to look at exception handling ("that stuff playing around with FS:0"). There's a number of articles on how to deal with this in assembly, google is your friend. I think donkey recently posted some code here, too.
Posted on 2004-04-01 11:25:42 by f0dder
I have some GoAsm code posted on my site, the MASM version is available in the FlipCase Addin for RadASM. I never really figured out how to trace it back to the caller as I needed the address in the DLL more than the application that called it. After all, it had to find the exception in an AddIn DLL both in RadASM and in the app it was written for. Without single step debugging it would be difficult to automatically find the address that made the erroneous call. I cannot think of a way to reliably find the ultimate return address through the stack in any automated way, a DLL function may make several nested calls each of which modifies EBP and adds any number of parameters and local variables to the stack. There may be information about this in the context or exception record but I have not found it and would have difficulty imagining how they determined where to start the trace. For example how would Windows know that you wanted the main application's calling address and not the address USER32.DLL that called the function in NTDLL.DLL or the function in NTDLL.DLL that called lstrlen ?
Posted on 2004-04-01 11:40:57 by donkey
As long as EBP is used for stack frame, it should be possible to do a complete stalk walk. It's not a trivial matter, especially when EBP is used as a GP register, but it should be doable. There should be a bunch of articles around on the net, "stack unwind" or "stack walk" and similar should return stuff in google. Sorry I don't have any ready URLs, but didn't have much use for it yet. I'm pretty sure I saw some good articles from Microsoft, btw...
Posted on 2004-04-01 12:24:42 by f0dder
I imagine you could use RtlUnwind if you're on 2K/XP
Posted on 2004-04-01 12:40:46 by donkey

From your description, you're not yet using WinXP. Its a good thing that I had my newest box installed with two partitions on the hard disk, one with the current default WinXP and the other one with Win98.

WinXP gives absolutely no usefull information whatsoever if the program crashes. It only asks if you want to send some data to MS for them to analyze. At least I still have Win98 to tell me where the fault is taking place. I also have the habit of testing programs in development as often as I can. When I get a GPF outside my program, I thus have a limited amount of code to review.

Posted on 2004-04-01 20:12:09 by Raymond
hi Raymond,

I think that the information is dumped to Dr Watson, which is the default final exception handler in WinXP. You can use my (rather incomplete) Dr Watson log viewer to see if the file exists. The infomation in a Dr Watson log is much more comprehensive than the old dumps from Win98. It is an abandonned project as I decided to make a dedicated exception handler for my use and RadASM but it works OK.


The default debugger is in the key :

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger
Posted on 2004-04-01 20:44:58 by donkey
opening a ~40/50 mb drwatson.log is another problem or for that matter .dmp files it creates both minidump and what ever .dmp

anyway as fodder said using olly dbg with the app and viewing its call stack shows all the previous calls that were made prior to gpf
in w98 its some what sketchy coz the included calls arent properly listed but in w2k etc the call stack shows the included calls too
or using olly as the default jit (just in time debugger)instead of original DrWatson catches the gpf and attaches to it in real time so you can single step through it
or analyze it

or better use the runtrace and when it has gpffed and view runtrace and global profile it will show you each and every call that was executed before crash
Posted on 2004-04-01 23:13:48 by bluffer
Hi donkey,

> I imagine you could use RtlUnwind if you're on 2K/XP

RtlUnwind exists on all windows systems, but it "unwinds" exception frames (the linked list which starts at fs:[0]) and has not too much to do with stack frames . IIRC, it is still not "officially" documented.
Posted on 2004-04-01 23:16:25 by japheth
There's a registry key to disable the "report to MS" and enable register contents information on XP crashes. I can't remember where it is, but it's probably tweakable from PowertoysXP, if not google will surely help.
Posted on 2004-04-01 23:19:27 by f0dder

Thanks so much for all the advice that was given to me in this thread. I didn't know the correct terminologies before my post here, and so my searches weren't coming up with much information to help me.

Now, I've found lots of snippets of code and writings about Exception handling and stack walking. I implemented a simple test exception handler that walks up the stack to see if it works, and it actually does! Even when the exception is caused in a system DLL, I now get told where in my own code it was eventually going to return to.

I'm really happy that this works! :) :alright: :grin: This is going to really help me squash bugs that manage to slip through into release code, as I'll now know the exact code location where it happened.

There's a StackWalk function in imagehlp.dll that seems to work quite nicely, but I prefer to use some code that I found on the Microsoft Journal that do it manually. I didn't want to rely on a dll that might not be present on all systems.

The only thing I'm concerned about now is if it will work on XP? There was a post in this thread that said XP has it's own exception handler that reports to Microsoft. Will this override my custom exception handler when my application(s) are run on XP, or does my exception handler override XP's one?
Posted on 2004-04-04 23:44:28 by turtle
Your (per-thread) FS:0 handler will always be called first, before the "unhandled exception filter" (SetUnhandledExceptionFilter). Iirc, it's the default unhandled exception filter that's responsible for shoving the "program performed an illegal action" or "report to microsoft" dialog - so if you install your own UEF, that dialog will never pop up. The UEF is per-process.

The default on XP is to show the "report to MS" dialog, which is good for end-users (who don't get confused with register dumps), but bad for developers. But well, flip a registry setting, and you get the win2k-style dialog.

Oh, there's also something called Vectored Exception Handling on XP, but I don't think it's something you'll have to worry much about unless you're using it yourself :). VEH is also per-process, iirc.

So... no need to worry too much, I guess.
Posted on 2004-04-05 09:49:17 by f0dder