21 #ifdef USE_WINDOWS_SEH
31 const ULONG maxnamelength = 512;
32 struct IMAGEHLP_SYMBOL64_EXT :
public IMAGEHLP_SYMBOL64 {
33 TCHAR nameExt[maxnamelength];
35 typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
36 fpStackWalk64 pStackWalk64;
37 typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64);
38 fpSymGetModuleBase64 pSymGetModuleBase64;
39 typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64);
40 fpSymGetSymFromAddr64 pSymGetSymFromAddr64;
41 typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD, PIMAGEHLP_LINE64);
42 fpSymGetLineFromAddr64 pSymGetLineFromAddr64;
43 typedef DWORD (WINAPI *fpUnDecorateSymbolName)(
const TCHAR*, PTSTR, DWORD, DWORD);
44 fpUnDecorateSymbolName pUnDecorateSymbolName;
45 typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
46 fpSymFunctionTableAccess64 pSymFunctionTableAccess64;
47 typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL);
48 fpSymInitialize pSymInitialize;
54 hLibDbgHelp = ::LoadLibraryW(L
"Dbghelp.dll");
57 pStackWalk64 = (fpStackWalk64) ::GetProcAddress(hLibDbgHelp,
"StackWalk64");
58 pSymGetModuleBase64 = (fpSymGetModuleBase64) ::GetProcAddress(hLibDbgHelp,
"SymGetModuleBase64");
59 pSymGetSymFromAddr64 = (fpSymGetSymFromAddr64) ::GetProcAddress(hLibDbgHelp,
"SymGetSymFromAddr64");
60 pSymGetLineFromAddr64 = (fpSymGetLineFromAddr64)::GetProcAddress(hLibDbgHelp,
"SymGetLineFromAddr64");
61 pSymFunctionTableAccess64 = (fpSymFunctionTableAccess64)::GetProcAddress(hLibDbgHelp,
"SymFunctionTableAccess64");
62 pSymInitialize = (fpSymInitialize) ::GetProcAddress(hLibDbgHelp,
"SymInitialize");
63 pUnDecorateSymbolName = (fpUnDecorateSymbolName)::GetProcAddress(hLibDbgHelp,
"UnDecorateSymbolName");
68 void printCallstack(FILE* outputFile, PEXCEPTION_POINTERS ex)
72 const HANDLE hProcess = GetCurrentProcess();
73 const HANDLE hThread = GetCurrentThread();
79 CONTEXT context = *(ex->ContextRecord);
80 STACKFRAME64 stack= {0};
82 stack.AddrPC.Offset = context.Eip;
83 stack.AddrPC.Mode = AddrModeFlat;
84 stack.AddrStack.Offset = context.Esp;
85 stack.AddrStack.Mode = AddrModeFlat;
86 stack.AddrFrame.Offset = context.Ebp;
87 stack.AddrFrame.Mode = AddrModeFlat;
89 stack.AddrPC.Offset = context.Rip;
90 stack.AddrPC.Mode = AddrModeFlat;
91 stack.AddrStack.Offset = context.Rsp;
92 stack.AddrStack.Mode = AddrModeFlat;
93 stack.AddrFrame.Offset = context.Rsp;
94 stack.AddrFrame.Mode = AddrModeFlat;
96 IMAGEHLP_SYMBOL64_EXT symbol;
97 symbol.SizeOfStruct =
sizeof(IMAGEHLP_SYMBOL64);
98 symbol.MaxNameLength = maxnamelength;
99 DWORD64 displacement = 0;
101 for (ULONG frame = 0; ; frame++) {
102 BOOL result = pStackWalk64
105 IMAGE_FILE_MACHINE_I386,
107 IMAGE_FILE_MACHINE_AMD64,
114 pSymFunctionTableAccess64,
120 pSymGetSymFromAddr64(hProcess, (ULONG64)stack.AddrPC.Offset, &displacement, &symbol);
121 TCHAR undname[maxnamelength]= {0};
122 pUnDecorateSymbolName((
const TCHAR*)symbol.Name, (PTSTR)undname, (DWORD)
getArrayLength(undname), UNDNAME_COMPLETE);
125 if (_tcscmp(undname, _T(
"main"))==0)
128 "%lu. 0x%08I64X in ",
129 frame, (ULONG64)stack.AddrPC.Offset);
130 fputs((
const char *)undname, outputFile);
131 fputc(
'\n', outputFile);
132 if (0==stack.AddrReturn.Offset || beyond_main>2)
136 FreeLibrary(hLibDbgHelp);
140 void writeMemoryErrorDetails(FILE* outputFile, PEXCEPTION_POINTERS ex,
const char* description)
142 fputs(description, outputFile);
143 fprintf(outputFile,
" (instruction: 0x%p) ", ex->ExceptionRecord->ExceptionAddress);
146 C_ASSERT(
sizeof(
void*) ==
sizeof(ex->ExceptionRecord->ExceptionInformation[1]));
147 switch (ex->ExceptionRecord->ExceptionInformation[0]) {
149 fprintf(outputFile,
"reading from 0x%p",
150 reinterpret_cast<void*
>(ex->ExceptionRecord->ExceptionInformation[1]));
153 fprintf(outputFile,
"writing to 0x%p",
154 reinterpret_cast<void*
>(ex->ExceptionRecord->ExceptionInformation[1]));
157 fprintf(outputFile,
"data execution prevention at 0x%p",
158 reinterpret_cast<void*
>(ex->ExceptionRecord->ExceptionInformation[1]));
168 int filterException(FILE *outputFile,
int code, PEXCEPTION_POINTERS ex)
170 fputs(
"Internal error: ", outputFile);
171 switch (ex->ExceptionRecord->ExceptionCode) {
172 case EXCEPTION_ACCESS_VIOLATION:
173 writeMemoryErrorDetails(outputFile, ex,
"Access violation");
175 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
176 fputs(
"Out of array bounds", outputFile);
178 case EXCEPTION_BREAKPOINT:
179 fputs(
"Breakpoint", outputFile);
181 case EXCEPTION_DATATYPE_MISALIGNMENT:
182 fputs(
"Misaligned data", outputFile);
184 case EXCEPTION_FLT_DENORMAL_OPERAND:
185 fputs(
"Denormalized floating-point value", outputFile);
187 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
188 fputs(
"Floating-point divide-by-zero", outputFile);
190 case EXCEPTION_FLT_INEXACT_RESULT:
191 fputs(
"Inexact floating-point value", outputFile);
193 case EXCEPTION_FLT_INVALID_OPERATION:
194 fputs(
"Invalid floating-point operation", outputFile);
196 case EXCEPTION_FLT_OVERFLOW:
197 fputs(
"Floating-point overflow", outputFile);
199 case EXCEPTION_FLT_STACK_CHECK:
200 fputs(
"Floating-point stack overflow", outputFile);
202 case EXCEPTION_FLT_UNDERFLOW:
203 fputs(
"Floating-point underflow", outputFile);
205 case EXCEPTION_GUARD_PAGE:
206 fputs(
"Page-guard access", outputFile);
208 case EXCEPTION_ILLEGAL_INSTRUCTION:
209 fputs(
"Illegal instruction", outputFile);
211 case EXCEPTION_IN_PAGE_ERROR:
212 writeMemoryErrorDetails(outputFile, ex,
"Invalid page access");
214 case EXCEPTION_INT_DIVIDE_BY_ZERO:
215 fputs(
"Integer divide-by-zero", outputFile);
217 case EXCEPTION_INT_OVERFLOW:
218 fputs(
"Integer overflow", outputFile);
220 case EXCEPTION_INVALID_DISPOSITION:
221 fputs(
"Invalid exception dispatcher", outputFile);
223 case EXCEPTION_INVALID_HANDLE:
224 fputs(
"Invalid handle", outputFile);
226 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
227 fputs(
"Non-continuable exception", outputFile);
229 case EXCEPTION_PRIV_INSTRUCTION:
230 fputs(
"Invalid instruction", outputFile);
232 case EXCEPTION_SINGLE_STEP:
233 fputs(
"Single instruction step", outputFile);
235 case EXCEPTION_STACK_OVERFLOW:
236 fputs(
"Stack overflow", outputFile);
239 fprintf(outputFile,
"Unknown exception (%d)\n",
243 fputc(
'\n', outputFile);
244 printCallstack(outputFile, ex);
246 return EXCEPTION_EXECUTE_HANDLER;
260 return (&executor->*f)(settings);
261 } __except (filterException(outputFile, GetExceptionCode(), GetExceptionInformation())) {
262 fputs(
"Please report this to the cppcheck developers!\n", outputFile);
This class works as an example of how CppCheck can be used in external programs without very little k...
static FILE * getExceptionOutput()
This is just a container for general settings so that we don't need to pass individual values to func...
std::size_t getArrayLength(const T(&)[size])
Simple helper function: