src/SEHExceptionWatcher.cpp

Go to the documentation of this file.
00001 /*
00002 * Copyright (c) 2006 by Kirill Kolodyazhniy.
00003 * See the file "license.terms" for information on usage and redistribution
00004 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00005 */
00006 
00007 #include "stdinc.h"
00008 #include "SEHExceptionWatcher.h"
00009 
00010 #ifndef _MT
00012 extern struct EHExceptionRecord * _pCurrentException;
00013 extern struct _CONTEXT*  _pCurrentExContext;
00014 #endif
00015 
00016 /****************************************************************************/
00017 SEHExceptionWatcher::SEHExceptionWatcher()
00018 {
00019 };
00020 
00021 #ifdef _MSC_VER
00022 /****************************************************************************/
00023 const EXCEPTION_RECORD * SEHExceptionWatcher::GetCurrentExceptionRecord()
00024 {
00025 #if defined(_MT) && !defined(_DLL)
00026         _ptiddata p = _getptd();
00027         return (EXCEPTION_RECORD *)p->_curexception;
00028 #elif !defined(_MT)
00029         return (EXCEPTION_RECORD *)_pCurrentException;
00030 #endif //_MT
00031 };
00032 /****************************************************************************/
00033 const _CONTEXT * SEHExceptionWatcher::GetCurrentExceptionContext()
00034 {
00035 #if defined(_MT) && !defined(_DLL)
00036         _ptiddata p = _getptd();
00037         return p->_curcontext;
00038 #elif !defined(_MT)
00039         return _pCurrentExContext;
00040 #endif //_MT
00041 }
00042 /****************************************************************************/
00043 std::string SEHExceptionWatcher::AddressToString(HANDLE hModule, PVOID address )
00044 {
00045         char buf[100];
00046         std::string result;
00047         DWORD displacement;
00048         IMAGEHLP_LINE64  line;
00049         ZeroMemory(&line,sizeof(IMAGEHLP_LINE64));
00050         line.SizeOfStruct=sizeof(IMAGEHLP_LINE64);
00051         itoa((int)(DWORD64)address,buf,16);
00052         result+= buf;
00053         if(SymGetLineFromAddr64)
00054         {
00055                 if(SymGetLineFromAddr64(hModule,(DWORD64)address,&displacement,&line))
00056                 {
00057                         result="";
00058                         result+= line.FileName;
00059                         result+= "(";
00060                         itoa(line.LineNumber,buf,10);
00061                         result+= buf;
00062                         result+= ")";
00063                 }
00064         }
00065         return result;
00066 };
00067 #endif
00068 /****************************************************************************/
00069 std::string SEHExceptionWatcher::Read()
00070 {
00071         std::string result;
00072 #ifdef _MSC_VER
00073         char filename[MAX_PATH];
00074         char path[MAX_PATH];
00075         char *shortfilename;
00076         char libpath[MAX_PATH];
00077         memset(path,0,sizeof(char)*MAX_PATH);
00078         memset(filename,0,sizeof(char)*MAX_PATH);
00079         HANDLE hModule=GetCurrentProcess();
00080         GetModuleFileName(NULL,filename,MAX_PATH);
00081         GetFullPathName(filename,MAX_PATH,path,&shortfilename);
00082         path[shortfilename-path]='\0';
00083         strcpy(libpath,"dbghelp.dll");
00084         //strcpy(libpath,path);
00085         //strcat(libpath,"dbghelp.dll");
00086         const EXCEPTION_RECORD * pr = GetCurrentExceptionRecord();
00087         if (pr )
00088         {
00089                 result+= "SEH Exception : \n";
00090                 switch(pr->ExceptionCode)
00091                 {
00092                         case EXCEPTION_ACCESS_VIOLATION :
00093                                 result+= "The thread tried to read from or write to a virtual address that it does not have appropriate access to.\n";
00094                                 break;
00095                         case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
00096                                 result+= " The thread tried to access an array element that is out of bounds and the underlying hardware supports bounds checking. \n";
00097                                 break;
00098                         case EXCEPTION_BREAKPOINT:
00099                                 result+= " A breakpoint was encountered. ";
00100                                 break;
00101                         case EXCEPTION_DATATYPE_MISALIGNMENT:
00102                                 result+= " The thread tried to read or write data that is misaligned on hardware that does not provide alignment. For example, 16-bit values must be aligned on 2-byte boundaries; 32-bit values on 4-byte boundaries, and so on.\n";
00103                                 break;
00104                         case EXCEPTION_FLT_DENORMAL_OPERAND:
00105                                 result+= " An operand in a floating-point operation is denormal. A denormal value is one that is too small to represent as a standard floating-point value.\n";
00106                                 break;
00107                         case EXCEPTION_FLT_DIVIDE_BY_ZERO:
00108                                 result+= " The thread tried to divide a floating-point value by a floating-point divisor of zero. \n";
00109                                 break;
00110                         case EXCEPTION_FLT_INEXACT_RESULT:
00111                                 result+= " The result of a floating-point operation cannot be represented exactly as a decimal fraction.\n ";
00112                                 break;
00113                         case EXCEPTION_FLT_INVALID_OPERATION:
00114                                 result+= " This exception represents a floating-point exception not included in this list. \n";
00115                                 break;
00116                         case EXCEPTION_FLT_OVERFLOW:
00117                                 result+= " The exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type. \n";
00118                                 break;
00119                         case EXCEPTION_FLT_STACK_CHECK:
00120                                 result+= " The stack overflowed or underflowed as the result of a floating-point operation.\n ";
00121                                 break;
00122                         case EXCEPTION_FLT_UNDERFLOW:
00123                                 result+= " The exponent of a floating-point operation is less than the magnitude allowed by the corresponding type.\n ";
00124                                 break;
00125                         case EXCEPTION_ILLEGAL_INSTRUCTION:
00126                                 result+= " The thread tried to execute an invalid instruction. \n";
00127                                 break;
00128                         case EXCEPTION_IN_PAGE_ERROR:
00129                                 result+= " The thread tried to access a page that was not present and the system could not load the page. For example, this exception might occur if a network connection is lost while running a program over the network.\n";
00130                                 break;
00131                         case EXCEPTION_INT_DIVIDE_BY_ZERO:
00132                                 result+= " The thread tried to divide an integer value by an integer divisor of zero. \n";
00133                                 break;
00134                         case EXCEPTION_INT_OVERFLOW:
00135                                 result+= " The result of an integer operation caused a carry out of the most significant bit of the result. \n";
00136                                 break;
00137                         case EXCEPTION_INVALID_DISPOSITION:
00138                                 result+= " An exception handler returned an invalid disposition to the exception dispatcher. Programmers using a high-level language, such as C, should never encounter this exception.\n";
00139                                 break;
00140                         case EXCEPTION_NONCONTINUABLE_EXCEPTION:
00141                                 result+= " The thread tried to continue execution after a noncontinuable exception occurred. \n";
00142                                 break;
00143                         case EXCEPTION_PRIV_INSTRUCTION:
00144                                 result+= " The thread tried to execute an instruction whose operation is not allowed in the current machine mode.\n ";
00145                                 break;
00146                         case EXCEPTION_SINGLE_STEP:
00147                                 result+= " A trace trap or other single-instruction mechanism signaled that one instruction has been executed. \n";
00148                                 break;
00149                         case EXCEPTION_STACK_OVERFLOW:
00150                                 result+= " The thread used up its stack. \n";
00151                                 break;
00152                 }
00153         }
00154         else
00155                 result+="Can't get exception information.\n";
00156 
00157 
00158         HMODULE hDbgHelp = LoadLibrary(libpath);
00159         if(hDbgHelp)
00160         {
00161                 SymSetOptions=(SSO)GetProcAddress(hDbgHelp,"SymSetOptions");
00162                 SymInitialize=(SI)GetProcAddress(hDbgHelp,"SymInitialize");
00163                 SymCleanup=(SC)GetProcAddress(hDbgHelp,"SymCleanup");
00164                 SymGetLineFromAddr64=(SGLFA64)GetProcAddress(hDbgHelp,"SymGetLineFromAddr64");
00165                 StackWalk64=(SW64)GetProcAddress(hDbgHelp,"StackWalk64");
00166                 SymFunctionTableAccess64=(SFTA64)GetProcAddress(hDbgHelp,"SymFunctionTableAccess64");
00167                 SymGetModuleBase64=(SGMB64)GetProcAddress(hDbgHelp,"SymGetModuleBase64");
00168                 if(SymSetOptions&&SymInitialize&&SymGetLineFromAddr64&&SymCleanup&&StackWalk64&&SymFunctionTableAccess64&&SymGetModuleBase64)
00169                 {
00170                         SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES);
00171                         if(SymInitialize(hModule,path,TRUE))
00172                         {
00173                                 //get exception source
00174                                 if(pr)
00175                                 {
00176                                         result+= "Occured at ";
00177                                         result+= AddressToString(hModule,pr->ExceptionAddress);
00178                                         result+="\n";
00179                                 }
00180                                 //get stack info
00181                                 result+= "Stack trace: \n";
00182                                 CONTEXT context = {CONTEXT_FULL};
00183                                 memcpy(&context, GetCurrentExceptionContext() , sizeof(CONTEXT));
00184 
00185                                 STACKFRAME64 stackFrame = {0};
00186 
00187                                 stackFrame.AddrPC.Offset = context.Eip;
00188                                 stackFrame.AddrPC.Mode = AddrModeFlat;
00189 
00190                                 stackFrame.AddrFrame.Offset = context.Ebp;
00191                                 stackFrame.AddrFrame.Mode = AddrModeFlat;
00192 
00193                                 stackFrame.AddrStack.Offset = context.Esp;
00194                                 stackFrame.AddrStack.Mode = AddrModeFlat;
00195 
00196                                 while (StackWalk64(
00197                                 IMAGE_FILE_MACHINE_I386,
00198                                 hModule,
00199                                 GetCurrentThread(), // this value doesn't matter much if previous one is a real handle
00200                                 &stackFrame,
00201                                 &context,
00202                                 NULL,
00203                                 SymFunctionTableAccess64,
00204                                 SymGetModuleBase64,
00205                                 NULL ) )
00206                                 {
00207                                         result+=AddressToString(hModule,(PVOID)(DWORD64)stackFrame.AddrPC.Offset );
00208                                         result+="\n";
00209                                 }
00210 
00211                                 SymCleanup(hModule);
00212                         }
00213                         else
00214                                 result+="Can't load symbol information.\n";
00215                 }
00216                 else
00217                         result="Can't load dbghelp.dll\n";
00218 
00219                 FreeLibrary(hDbgHelp);
00220         }
00221         else
00222                 result+="Can't load dbghelp.dll\n";
00223 #else
00224         result+="Unknown error!";
00225 #endif
00226         return result;
00227 };
00228 
00229 /****************************************************************************/

Generated on Thu Oct 26 13:47:45 2006 for MWidgets by  doxygen 1.4.7