[Piglit] [PATCH 05/13] util: Implement signal handler on windows.
Kenney Phillis
kphillisjr at gmail.com
Thu Oct 31 15:48:01 CET 2013
This signal handler is built using dbghelp support. This is found in most
versions of windows, and should work great on Windows XP or newer. I
have tested this against Windows 7 using MSVC and there is no major
problems. Also, as a benefit, this will automatically generate the
backtrace information within the piglit results file.
---
tests/util/CMakeLists.no_api.txt | 4 +
tests/util/CMakeLists.txt | 4 +-
.../piglit-sighandler/piglit-sighandler-win32.cpp | 339 ++++++++++++++++++++
3 files changed, 346 insertions(+), 1 deletion(-)
create mode 100644 tests/util/piglit-sighandler/piglit-sighandler-win32.cpp
diff --git a/tests/util/CMakeLists.no_api.txt b/tests/util/CMakeLists.no_api.txt
index c331368..6f5e9fe 100644
--- a/tests/util/CMakeLists.no_api.txt
+++ b/tests/util/CMakeLists.no_api.txt
@@ -10,4 +10,8 @@ if(UNIX)
target_link_libraries(piglitutil m)
endif(UNIX)
+if(WIN32)
+ target_link_libraries(piglitutil Dbghelp)
+endif(WIN32)
+
# vim: ft=cmake:
diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt
index 5c184ea..5ffef5f 100644
--- a/tests/util/CMakeLists.txt
+++ b/tests/util/CMakeLists.txt
@@ -11,7 +11,9 @@ set(UTIL_SOURCES
# Auto-detect Correct Signal Handler.
-if(UNIX)
+if(WIN32)
+ list(APPEND UTIL_SOURCES piglit-sighandler/piglit-sighandler-win32.cpp)
+elseif(UNIX)
list(APPEND UTIL_SOURCES piglit-sighandler/piglit-sighandler-posix.c)
else()
# No Signal Handler found.
diff --git a/tests/util/piglit-sighandler/piglit-sighandler-win32.cpp b/tests/util/piglit-sighandler/piglit-sighandler-win32.cpp
new file mode 100644
index 0000000..4a995e3
--- /dev/null
+++ b/tests/util/piglit-sighandler/piglit-sighandler-win32.cpp
@@ -0,0 +1,339 @@
+/*
+ * Copyright © 2013 Kenney Phillis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/** @file piglit-sighandler-win32.c
+ *
+ * Helper function for handling Segmentation faults on windows. This handler
+ * is especially important for Windows XP and up that include a built in
+ * vectored exception handling support.
+ * See: http://msdn.microsoft.com/en-us/magazine/cc301714.aspx
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <windows.h>
+#include <eh.h>
+#include <DbgHelp.h>
+#include <signal.h>
+#include "piglit-util.h"
+
+LONG WINAPI piglit_ExceptionHandler( EXCEPTION_POINTERS* pExp );
+void piglit_PrintExceptionRecord(PCONTEXT pRecord);
+void piglit_SignalHandler(int signal);
+void piglit_PrintBacktrace(HANDLE process);
+bool piglit_register_signal_handler()
+{
+ OSVERSIONINFO mSysVer;
+ DWORD dwMode;
+
+ ZeroMemory(&mSysVer, sizeof(OSVERSIONINFO));
+ mSysVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&mSysVer);
+ if( ( mSysVer.dwMajorVersion < 5) ||
+ ( (mSysVer.dwMajorVersion == 5) && (mSysVer.dwMinorVersion < 1) ) ) {
+ /* Do not bother trying to Register a Handler on windows versions
+ Older than XP */
+ return false;
+ }
+ /* Debug Help, Updated Platform help
+ See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681408%28v=vs.85%29.aspx
+ */
+ /* Note: Windows XP or newer is Required For this to work properly */
+ /* XP is when Vectored Exception handlers where introduced */
+ AddVectoredExceptionHandler(0, piglit_ExceptionHandler);
+ //EnableCrashingOnCrashes();
+ signal(SIGABRT, piglit_SignalHandler);
+ /* Disable Windows Crash dialog
+ See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx
+ */
+ /*Get Current Error Mode*/
+ dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
+ /* Set New Error mode without Crash Dialog */
+ SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
+ return true;
+}
+
+LONG WINAPI piglit_ExceptionHandler( EXCEPTION_POINTERS* pExp ) {
+ unsigned int code = pExp->ExceptionRecord->ExceptionCode;
+ // TODO: Integrate other exceptions that can be of use.
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/aa363082%28v=vs.85%29.aspx
+ if( (code == EXCEPTION_FLT_DIVIDE_BY_ZERO ) ||
+ (code == EXCEPTION_INT_DIVIDE_BY_ZERO ) ||
+ (code == EXCEPTION_ACCESS_VIOLATION) ||
+ (code == EXCEPTION_INVALID_DISPOSITION) || // Not normal For c/c++ ( assembly issue )
+ (code == EXCEPTION_ARRAY_BOUNDS_EXCEEDED) || // Array Bounds Checks
+ (code == EXCEPTION_ILLEGAL_INSTRUCTION ) || // Invalid Instruction
+ (code == EXCEPTION_STACK_OVERFLOW) // Stack Overflow
+ )
+ {
+ PEXCEPTION_RECORD pExceptionRec;
+ PCONTEXT pExceptionContext;
+ DWORD lineDisplacement = 0;
+ HANDLE process;
+ IMAGEHLP_LINE64 line; /* For Line and File Information */
+ DWORD symOptions;
+ SYMBOL_INFO * symbol;
+ symbol = ( SYMBOL_INFO * )calloc(1,
+ sizeof( SYMBOL_INFO ) + 256 * sizeof( char ) );
+ symbol->MaxNameLen = 255;
+ symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ process = GetCurrentProcess();
+ /* Configure Symbol Options for print stack */
+ symOptions = SymGetOptions();
+ symOptions |= SYMOPT_LOAD_LINES;
+ symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
+ symOptions &= ~SYMOPT_UNDNAME; /* Automatically Un-Decorate Symbol Name */
+ symOptions &= ~SYMOPT_DEFERRED_LOADS;
+ symOptions = SymSetOptions(symOptions);
+ /* Initialize Dbghelp */
+ SymInitialize( process, NULL, TRUE );
+ pExceptionRec = pExp->ExceptionRecord;
+ pExceptionContext = pExp->ContextRecord;
+ printf( "Exception Caught:\n\tAddress - 0x%0X ( Code: 0x%08lx)\n",
+ pExceptionRec->ExceptionAddress ,
+ pExceptionRec->ExceptionCode );
+ SymFromAddr( process, ( DWORD64 )( pExceptionRec->ExceptionAddress ),
+ 0, symbol );
+ /* get Exception Address Symbol Name */
+ printf( "Exception Location: %s - 0x%0X\n",
+ symbol->Name, symbol->Address );
+ if (SymGetLineFromAddr64(process, ( DWORD64 )
+ (pExceptionRec->ExceptionAddress ) ,
+ &lineDisplacement, &line))
+ {
+ /* Print the FIle Name and line number if Available.
+ SymGetLineFromAddr64 returned success */
+ printf("\tFile name:\t%s\n\tLine Number:\t%d\n",
+ line.FileName, line.LineNumber );
+ }
+ piglit_PrintBacktrace(process);
+ printf("===========================================\n");
+ printf("Register Dump:\n");
+ printf("===========================================\n");
+ piglit_PrintExceptionRecord(pExceptionContext);
+
+ fprintf(stdout,"PIGLIT: {'result': 'crash' }\n");
+ fflush(stdout);
+ /* Report The Crash now... This may need some work on results that are
+ teired.
+ */
+ //ExitProcess(-1);
+ //exit(code);
+ return EXCEPTION_EXECUTE_HANDLER; /* This shouldn't generate an Error. */
+ }
+
+ /*
+ * Ignore C++ exceptions
+ * http://support.microsoft.com/kb/185294
+ * http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
+ *
+ */
+ if (code == 0xe06d7363 ) {
+ // C++ Exceptions
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+
+ /* Didn't Handle Exception, Continue */
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+
+void piglit_PrintBacktrace(HANDLE process)
+{
+ unsigned int i;
+ SYMBOL_INFO *symbol;
+ HANDLE thread;
+ unsigned short frames;
+ void *pCallStack[64];
+ PIMAGEHLP_SYMBOL64 ImageData;
+ IMAGEHLP_LINE64 line; /* For Line and File Information */
+ DWORD lineDisplacement = 0;
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+ printf("===========================================\n");
+ printf("Call Stack:\n");
+ printf("===========================================\n");
+
+ frames = CaptureStackBackTrace( 0, 63, pCallStack, NULL );
+
+
+ thread = GetCurrentThread();
+ ImageData = (IMAGEHLP_SYMBOL64*)calloc(1,sizeof(ImageData)+sizeof(CHAR)*512);
+ ImageData->MaxNameLength = 512;
+ symbol = ( SYMBOL_INFO * )calloc(1,
+ sizeof( SYMBOL_INFO ) + 256 * sizeof( char ) );
+ symbol->MaxNameLen = 255;
+ symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
+
+ for( i = 0; i < frames; i++ )
+ {
+ /* Get Symbol Name */
+ SymFromAddr( process, ( DWORD64 )( pCallStack[ i ] ), 0, symbol );
+ printf( "%i: %s - 0x%0X\n", frames - i - 1, symbol->Name, symbol->Address );
+ if(SymGetLineFromAddr64(process, ( DWORD64 )( pCallStack[ i ] ) ,
+ &lineDisplacement, &line))
+ {
+ // Print Line Number and Source file if Available
+ printf (
+ "\tFile name: %s\n\tLine Number: %d\n\n",
+ line.FileName, line.LineNumber );
+ }
+ }
+ free( symbol );
+
+}
+
+void piglit_PrintExceptionRecord(PCONTEXT pRecord){
+#if defined(_WIN64)
+ // Create a Clean Register Dump of the Current Context.
+ printf("Register Dump x64 ( AMD64 )\n");
+ if(pRecord->ContextFlags & CONTEXT_CONTROL) {
+ printf("Control Registers:\n");
+ //egSs, Rsp, SegCs, Rip, and EFlags.
+ printf("\tRip: 0x%016llX Rsp: 0x%016llX\n"
+ "\tEFLags: 0x%0lX SegCS: 0x%0lX SegSs:0x%0lX\n",
+ pRecord->Rip,pRecord->Rsp, pRecord->EFlags,
+ pRecord->SegCs, pRecord->SegSs);
+ }
+
+ if(pRecord->ContextFlags & CONTEXT_SEGMENTS) {
+ printf("Segment Registers:\n");
+ printf("\tSegDS: 0x%0X SegEs:0x%0X SegFs:0x%0X SegGs:0x%0X\n",
+ pRecord->SegDs, pRecord->SegEs, pRecord->SegFs, pRecord->SegGs);
+ }
+ if(pRecord->ContextFlags & CONTEXT_INTEGER) {
+ printf("Integer Registers:\n");
+ printf("\tRAX: 0x%016llX RBX: 0x%016llX\n\tRCX: 0x%016llX RDX: 0x%016llX\n",
+ pRecord->Rax, pRecord->Rbx, pRecord->Rcx, pRecord->Rdx);
+ printf("\t R8: 0x%016llX R9: 0x%016llX \n\tR10: 0x%016llX R11: 0x%016llX\n",
+ pRecord->R8, pRecord->R9, pRecord->R10, pRecord->R11);
+ printf("\tR12: 0x%016llX R13: 0x%016llx\n\tR14: 0x%016llx R15: 0x%016llX\n",
+ pRecord->R12, pRecord->R13, pRecord->R14, pRecord->R15);
+ }
+ if(pRecord->ContextFlags & CONTEXT_FLOATING_POINT) {
+ int i;
+ printf("Floating Point Registers:\n");
+ printf("\tMxCsr: 0x%0lX MxCsr_Mask 0x%0lX\n", pRecord->FltSave.MxCsr, pRecord->FltSave.MxCsr_Mask);
+ for( i = 0; i < 8; i++) {
+ printf("\tFloat Register%-2d: 0x%016llX%016llX \n",
+ i ,
+ pRecord->FltSave.FloatRegisters[i].High,
+ pRecord->FltSave.FloatRegisters[i].Low);
+ }
+
+ /* XMM 1 to 7 - Available on 32-bit and 64 bit chips.*/
+ /* XMM 8 to 15- Available on 64-bit mode.*/
+ for( i = 0; i < 16; i++) {
+ printf("\tXmm%-2d: 0x%016llX%016llX \n",
+ i ,
+ pRecord->FltSave.XmmRegisters[i].High,
+ pRecord->FltSave.XmmRegisters[i].Low);
+ }
+ }
+ if(pRecord->ContextFlags & CONTEXT_DEBUG_REGISTERS) {
+ printf("Debug Registers:\n");
+ printf("\tDr0: %016llX Dr1: %016llX\n\tDr2: %016llX Dr3: %016llX\n"
+ "\tDr6: %016llX Dr7: %016llX\n",
+ pRecord->Dr0, pRecord->Dr1, pRecord->Dr2, pRecord->Dr3,
+ pRecord->Dr6, pRecord->Dr7);
+ }
+
+#else
+ printf("Register Dump x86\n");
+ if(pRecord->ContextFlags & CONTEXT_CONTROL) {
+ printf("\tEip: 0x%08lX Esp: 0x%08lX EFLags: 0x%08lX\n"
+ "\tSegCS: 0x%08lX SegSs:0x%08lX\n",
+ pRecord->Eip,pRecord->Esp, pRecord->EFlags,
+ pRecord->SegCs, pRecord->SegSs);
+ }
+ if(pRecord->ContextFlags & CONTEXT_INTEGER) {
+ printf("Integer Registers:\n");
+ printf("\tEax: 0x%08lX Ebx: 0x%08lX Ecx: 0x%08lX Edx: 0x%08lX\n",
+ pRecord->Eax, pRecord->Ebx, pRecord->Ecx, pRecord->Edx);
+ printf("\tEdi: 0x%08lX Esi: 0x%08lX\n",pRecord->Edi, pRecord->Esi);
+ }
+ if(pRecord->ContextFlags & CONTEXT_SEGMENTS) {
+ printf("Segment Registers:\n");
+ printf("\tSegDSl: 0x%08lX SegEs:0x%08lX SegFs:0x%08lX SegGs:0x%08lX\n",
+ pRecord->SegDs, pRecord->SegEs, pRecord->SegFs, pRecord->SegGs);
+ }
+ if(pRecord->ContextFlags & CONTEXT_EXTENDED_REGISTERS) {
+ int i;
+ PXSAVE_FORMAT fltRegs = (PXSAVE_FORMAT)pRecord->ExtendedRegisters;
+ printf("Floating Point Registers:\n");
+ printf("\tMxCsr: 0x%0lX MxCsr_Mask 0x%0lX\n", fltRegs->MxCsr, fltRegs->MxCsr_Mask);
+ for( i = 0; i < 8; i++) {
+ printf("\tFloat Register%-2d: 0x%016llX%016llX \n",
+ i ,
+ fltRegs->FloatRegisters[i].High,
+ fltRegs->FloatRegisters[i].Low);
+ }
+
+ /* XMM 1 to 7 - Available on 32-bit and 64 bit chips.*/
+ /* XMM 8 to 15- Available on 64-bit mode.*/
+ for( i = 0; i < 8; i++) {
+ printf("\tXmm%-2d: 0x%016llX%016llX \n",
+ i ,
+ fltRegs->XmmRegisters[i].High,
+ fltRegs->XmmRegisters[i].Low);
+ }
+ }
+ if(pRecord->ContextFlags & CONTEXT_DEBUG_REGISTERS) {
+ printf("Debug Registers:\n");
+ printf("\tDr0: 0x%08lX Dr1: 0x%08lX Dr2: 0x%08lX Dr3: 0x%08lX\n"
+ "\tDr6: 0x%08lX Dr7: 0x%08lX\n",
+ pRecord->Dr0, pRecord->Dr1, pRecord->Dr2, pRecord->Dr3,
+ pRecord->Dr6, pRecord->Dr7);
+ }
+#endif
+}
+void piglit_SignalHandler(int signal)
+{
+ printf("Application aborting...\n");
+ HANDLE process;
+ DWORD symOptions;
+ process = GetCurrentProcess();
+ /* Configure Symbol Options for print stack */
+ symOptions = SymGetOptions();
+ symOptions |= SYMOPT_LOAD_LINES;
+ symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS;
+ symOptions &= ~SYMOPT_UNDNAME; /* Automatically Un-Decorate Symbol Name */
+ symOptions &= ~SYMOPT_DEFERRED_LOADS;
+ symOptions = SymSetOptions(symOptions);
+ /* Initialize Dbghelp */
+ SymInitialize( process, NULL, TRUE );
+
+ /* Print backtrace */
+ piglit_PrintBacktrace(process);
+
+ fprintf(stdout,"PIGLIT: {'result': 'crash' }\n");
+ fflush(stdout);
+ ExitProcess(signal);
+}
--
1.7.9.5
More information about the Piglit
mailing list