00001
00002
00003
00004
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
00085
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
00174 if(pr)
00175 {
00176 result+= "Occured at ";
00177 result+= AddressToString(hModule,pr->ExceptionAddress);
00178 result+="\n";
00179 }
00180
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(),
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