Post-Mortem Debugging
by Stefan Woerthmueller 


Listing One

int FunctionC(int x, int y)
{
    char *p = (char *)0xBADC0DE; // Ummm!!, a dirty bad thing
    // Create a access vioaltion
    char c = *p;
    return 0;
}
int FunctionB(int x)
{
    return FunctionC(x, 16);
}
int FunctionA()
{
    return FunctionB(100);
}
int main(int argc, char *argv[])
{
    InstallWin32FaultHandler();
    FunctionA();
    return 0;
}

Listing Two
LONG Win32FaultHandler(struct _EXCEPTION_POINTERS *  ExInfo)

{   char  *FaultTx = "";
    switch(ExInfo->ExceptionRecord->ExceptionCode)
    {
      case EXCEPTION_ACCESS_VIOLATION      : FaultTx = "ACCESS VIOLATION"         ; break;
      case EXCEPTION_DATATYPE_MISALIGNMENT : FaultTx = "DATATYPE MISALIGNMENT"    ; break;
      case EXCEPTION_FLT_DIVIDE_BY_ZERO    : FaultTx = "FLT DIVIDE BY ZERO"       ; break;
        ...
        default: FaultTx = "(unknown)";           break;
    }
    sgLogFile = fopen("Win32Fault.log", "w");
    int    wsFault    = ExInfo->ExceptionRecord->ExceptionCode;
    PVOID  CodeAdress = ExInfo->ExceptionRecord->ExceptionAddress;
    sgLogFile = fopen("Win32Fault.log", "w");
    if(sgLogFile != NULL)
    {
       fprintf(sgLogFile, "****************************************************\n");
       fprintf(sgLogFile, "*** A Programm Fault occured:\n");
       fprintf(sgLogFile, "*** Error code %08X: %s\n", wsFault, FaultTx);
       fprintf(sgLogFile, "****************************************************\n");
       fprintf(sgLogFile, "***   Address: %08X\n", (int)CodeAdress);
       fprintf(sgLogFile, "***     Flags: %08X\n", ExInfo->ExceptionRecord->ExceptionFlags);
       LogStackFrames(CodeAdress, (char *)ExInfo->ContextRecord->Ebp);
       fclose(sgLogFile);
    }
    /*if(want to continue)
    {
       ExInfo->ContextRecord->Eip++;
       return EXCEPTION_CONTINUE_EXECUTION;
    }
    */ 
    return EXCEPTION_EXECUTE_HANDLER;
}


Listing Three 
void InstallFaultHandler()
{
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) Win32FaultHandler);
}



Listing Four

void   LogStackFrames(PVOID FaultAdress, char *eNextBP)
{      char *p, *pBP;                                     
       unsigned i, x, BpPassed;
       static int  CurrentlyInTheStackDump = 0;
   ...
       BpPassed = (eNextBP != NULL);
       if(! eNextBP)
       {
          _asm mov     eNextBP, eBp   
       }
       else 
           fprintf(sgLogFile, "\n  Fault Occured At $ADDRESS:%08LX\n", (int)FaultAdress);
                             // prevent infinite loops
       for(i = 0; eNextBP && i < 100; i++)
       {      
           pBP = eNextBP;           // keep current BasePointer
           eNextBP = *(char **)pBP; // dereference next BP 
           p = pBP + 8; 
           // Write 20 Bytes of potential arguments
           fprintf(sgLogFile, "         with ");                                                          
           for(x = 0; p < eNextBP && x < 20; p++, x++)
               fprintf(sgLogFile, "%02X ", *(unsigned char *)p);
           fprintf(sgLogFile, "\n\n");                                                          
                  if(i == 1 && ! BpPassed) 
               fprintf(sgLogFile, "****************************************************\n"
                                  "         Fault Occured Here:\n");
        // Write the backjump address
        fprintf(sgLogFile, "*** %2d called from $ADDRESS:%08LX\n", i, *(char **)(pBP + 4));
        if(*(char **)(pBP + 4) == NULL)
            break; 
       }
    ...

}




2


