- // Based on https://gist.github.com/jvranish/4441299 
-   
- #ifdef _WIN32 // Pierre-Marie Baty -- added compile guard 
-   
- // this has to be first 
- #include <windows.h> 
-   
- #include <imagehlp.h> 
-   
- #include "harness/os.h" 
-   
- #include <assert.h> 
- #include <direct.h> 
- #include <errno.h> 
- #include <limits.h> 
- #include <signal.h> 
- #include <stdbool.h> 
- #include <stdint.h> 
- #include <stdio.h> 
- #include <stdlib.h> 
- #include <string.h> 
-   
- #ifdef _WIN64 
- #define Esp Rsp 
- #define Eip Rip 
- #define Ebp Rbp 
- #endif 
-   
- void dr_dprintf(char* fmt_string, ...); 
-   
- static int stack_nbr = 0; 
- static char windows_program_name[1024]; 
-   
- static char dirname_buf[_MAX_DIR]; 
- static char fname_buf[_MAX_FNAME]; 
-   
- static int addr2line(char const* const program_name, void const* const addr) { 
-     char addr2line_cmd[512] = { 0 }; 
-   
-     sprintf(- addr2line_cmd , "addr2line -f -p -e %.256s %p",-  program_name ,-  addr );
 
-   
-     fprintf(- stderr , "%d: ",-  stack_nbr ++);
 
- } 
-   
- static void print_stacktrace(CONTEXT* context) { 
- #if 0 // Pierre-Marie Baty -- looks like this doesn't build right away on Windows 
-     SymInitialize(GetCurrentProcess(), 0, true); 
-   
-     STACKFRAME frame = { 0 }; 
-   
-     /* setup initial stack frame */ 
-     frame.AddrPC.Offset = context->Eip; 
-     frame.AddrPC.Mode = AddrModeFlat; 
-     frame.AddrStack.Offset = context->Esp; 
-     frame.AddrStack.Mode = AddrModeFlat; 
-     frame.AddrFrame.Offset = context->Ebp; 
-     frame.AddrFrame.Mode = AddrModeFlat; 
-   
-     while (StackWalk(IMAGE_FILE_MACHINE_I386, 
-         GetCurrentProcess(), 
-         GetCurrentThread(), 
-         &frame, 
-         context, 
-         0, 
-         SymFunctionTableAccess, 
-         SymGetModuleBase, 
-         0)) { 
-         addr2line(windows_program_name, (void*)frame.AddrPC.Offset); 
-     } 
-   
-     SymCleanup(GetCurrentProcess()); 
- #endif // 0 
- } 
-   
- static LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS* ExceptionInfo) { 
-     switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { 
-     case EXCEPTION_ACCESS_VIOLATION: 
-         fputs("Error: EXCEPTION_ACCESS_VIOLATION\n",-  stderr );
 
-         break; 
-     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: 
-         fputs("Error: EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n",-  stderr );
 
-         break; 
-     case EXCEPTION_BREAKPOINT: 
-         fputs("Error: EXCEPTION_BREAKPOINT\n",-  stderr );
 
-         break; 
-     case EXCEPTION_DATATYPE_MISALIGNMENT: 
-         fputs("Error: EXCEPTION_DATATYPE_MISALIGNMENT\n",-  stderr );
 
-         break; 
-     case EXCEPTION_FLT_DENORMAL_OPERAND: 
-         fputs("Error: EXCEPTION_FLT_DENORMAL_OPERAND\n",-  stderr );
 
-         break; 
-     case EXCEPTION_FLT_DIVIDE_BY_ZERO: 
-         fputs("Error: EXCEPTION_FLT_DIVIDE_BY_ZERO\n",-  stderr );
 
-         break; 
-     case EXCEPTION_FLT_INEXACT_RESULT: 
-         fputs("Error: EXCEPTION_FLT_INEXACT_RESULT\n",-  stderr );
 
-         break; 
-     case EXCEPTION_FLT_INVALID_OPERATION: 
-         fputs("Error: EXCEPTION_FLT_INVALID_OPERATION\n",-  stderr );
 
-         break; 
-     case EXCEPTION_FLT_OVERFLOW: 
-         fputs("Error: EXCEPTION_FLT_OVERFLOW\n",-  stderr );
 
-         break; 
-     case EXCEPTION_FLT_STACK_CHECK: 
-         fputs("Error: EXCEPTION_FLT_STACK_CHECK\n",-  stderr );
 
-         break; 
-     case EXCEPTION_FLT_UNDERFLOW: 
-         fputs("Error: EXCEPTION_FLT_UNDERFLOW\n",-  stderr );
 
-         break; 
-     case EXCEPTION_ILLEGAL_INSTRUCTION: 
-         fputs("Error: EXCEPTION_ILLEGAL_INSTRUCTION\n",-  stderr );
 
-         break; 
-     case EXCEPTION_IN_PAGE_ERROR: 
-         fputs("Error: EXCEPTION_IN_PAGE_ERROR\n",-  stderr );
 
-         break; 
-     case EXCEPTION_INT_DIVIDE_BY_ZERO: 
-         fputs("Error: EXCEPTION_INT_DIVIDE_BY_ZERO\n",-  stderr );
 
-         break; 
-     case EXCEPTION_INT_OVERFLOW: 
-         fputs("Error: EXCEPTION_INT_OVERFLOW\n",-  stderr );
 
-         break; 
-     case EXCEPTION_INVALID_DISPOSITION: 
-         fputs("Error: EXCEPTION_INVALID_DISPOSITION\n",-  stderr );
 
-         break; 
-     case EXCEPTION_NONCONTINUABLE_EXCEPTION: 
-         fputs("Error: EXCEPTION_NONCONTINUABLE_EXCEPTION\n",-  stderr );
 
-         break; 
-     case EXCEPTION_PRIV_INSTRUCTION: 
-         fputs("Error: EXCEPTION_PRIV_INSTRUCTION\n",-  stderr );
 
-         break; 
-     case EXCEPTION_SINGLE_STEP: 
-         fputs("Error: EXCEPTION_SINGLE_STEP\n",-  stderr );
 
-         break; 
-     case EXCEPTION_STACK_OVERFLOW: 
-         fputs("Error: EXCEPTION_STACK_OVERFLOW\n",-  stderr );
 
-         break; 
-     default: 
-         fputs("Error: Unrecognized Exception\n",-  stderr );
 
-         break; 
-     } 
-     /* If this is a stack overflow then we can't walk the stack, so just show 
-       where the error happened */ 
-     if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) { 
-         print_stacktrace(ExceptionInfo->ContextRecord); 
-     } else { 
-         addr2line(windows_program_name, (void*)ExceptionInfo->ContextRecord->Eip); 
-     } 
-   
-     return EXCEPTION_EXECUTE_HANDLER; 
- } 
-   
- void OS_InstallSignalHandler(char* program_name) { 
-     strcpy(- windows_program_name ,-  program_name );
 
-     SetUnhandledExceptionFilter(windows_exception_handler); 
- } 
-   
- FILE* OS_fopen(const char* pathname, const char* mode) { 
-     FILE* f; 
-     errno_t err; 
-   
-     f = NULL; 
-     err = fopen_s(&f, pathname, mode); 
-     if (err != 0) { 
-     } 
-   
-     return f; 
- } 
-   
- size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) { 
-     // FIXME: unsafe implementation (echos the password) 
-     pBuffer[0] = '\0'; 
-     fgets(- pBuffer ,-  pBufferLen ,-  stdin );
 
- } 
-   
- char* OS_Dirname(const char* path) { 
-     _splitpath(path, NULL, dirname_buf, NULL, NULL); 
-     return dirname_buf; 
- } 
-   
- char* OS_Basename(const char* path) { 
-     _splitpath(path, NULL, NULL, fname_buf, NULL); 
-     return fname_buf; 
- } 
-   
- #endif // _WIN32 
-