Subversion Repositories Games.Carmageddon

Rev

Rev 18 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
// Based on https://gist.github.com/jvranish/4441299
2
 
3
#ifdef _WIN32 // Pierre-Marie Baty -- added compile guard
4
 
5
// this has to be first
6
#include <windows.h>
7
 
8
#include <imagehlp.h>
9
 
10
#include "harness/os.h"
11
 
12
#include <assert.h>
13
#include <direct.h>
14
#include <errno.h>
15
#include <limits.h>
16
#include <signal.h>
17
#include <stdbool.h>
18
#include <stdint.h>
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <string.h>
22
 
23
#ifdef _WIN64
24
#define Esp Rsp
25
#define Eip Rip
26
#define Ebp Rbp
27
#endif
28
 
29
void dr_dprintf(char* fmt_string, ...);
30
 
31
static int stack_nbr = 0;
11 pmbaty 32
static char windows_program_name[1024];
1 pmbaty 33
 
34
static char dirname_buf[_MAX_DIR];
35
static char fname_buf[_MAX_FNAME];
36
 
11 pmbaty 37
static int addr2line(char const* const program_name, void const* const addr) {
1 pmbaty 38
    char addr2line_cmd[512] = { 0 };
39
 
40
    sprintf(addr2line_cmd, "addr2line -f -p -e %.256s %p", program_name, addr);
41
 
42
    fprintf(stderr, "%d: ", stack_nbr++);
43
    return system(addr2line_cmd);
44
}
45
 
11 pmbaty 46
static void print_stacktrace(CONTEXT* context) {
14 pmbaty 47
#if 0 // Pierre-Marie Baty -- looks like this doesn't build right away on Windows
1 pmbaty 48
    SymInitialize(GetCurrentProcess(), 0, true);
49
 
50
    STACKFRAME frame = { 0 };
51
 
52
    /* setup initial stack frame */
53
    frame.AddrPC.Offset = context->Eip;
54
    frame.AddrPC.Mode = AddrModeFlat;
55
    frame.AddrStack.Offset = context->Esp;
56
    frame.AddrStack.Mode = AddrModeFlat;
57
    frame.AddrFrame.Offset = context->Ebp;
58
    frame.AddrFrame.Mode = AddrModeFlat;
59
 
60
    while (StackWalk(IMAGE_FILE_MACHINE_I386,
61
        GetCurrentProcess(),
62
        GetCurrentThread(),
63
        &frame,
64
        context,
65
        0,
66
        SymFunctionTableAccess,
67
        SymGetModuleBase,
68
        0)) {
11 pmbaty 69
        addr2line(windows_program_name, (void*)frame.AddrPC.Offset);
1 pmbaty 70
    }
71
 
72
    SymCleanup(GetCurrentProcess());
14 pmbaty 73
#endif // 0
1 pmbaty 74
}
75
 
11 pmbaty 76
static LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS* ExceptionInfo) {
1 pmbaty 77
    switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
78
    case EXCEPTION_ACCESS_VIOLATION:
79
        fputs("Error: EXCEPTION_ACCESS_VIOLATION\n", stderr);
80
        break;
81
    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
82
        fputs("Error: EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n", stderr);
83
        break;
84
    case EXCEPTION_BREAKPOINT:
85
        fputs("Error: EXCEPTION_BREAKPOINT\n", stderr);
86
        break;
87
    case EXCEPTION_DATATYPE_MISALIGNMENT:
88
        fputs("Error: EXCEPTION_DATATYPE_MISALIGNMENT\n", stderr);
89
        break;
90
    case EXCEPTION_FLT_DENORMAL_OPERAND:
91
        fputs("Error: EXCEPTION_FLT_DENORMAL_OPERAND\n", stderr);
92
        break;
93
    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
94
        fputs("Error: EXCEPTION_FLT_DIVIDE_BY_ZERO\n", stderr);
95
        break;
96
    case EXCEPTION_FLT_INEXACT_RESULT:
97
        fputs("Error: EXCEPTION_FLT_INEXACT_RESULT\n", stderr);
98
        break;
99
    case EXCEPTION_FLT_INVALID_OPERATION:
100
        fputs("Error: EXCEPTION_FLT_INVALID_OPERATION\n", stderr);
101
        break;
102
    case EXCEPTION_FLT_OVERFLOW:
103
        fputs("Error: EXCEPTION_FLT_OVERFLOW\n", stderr);
104
        break;
105
    case EXCEPTION_FLT_STACK_CHECK:
106
        fputs("Error: EXCEPTION_FLT_STACK_CHECK\n", stderr);
107
        break;
108
    case EXCEPTION_FLT_UNDERFLOW:
109
        fputs("Error: EXCEPTION_FLT_UNDERFLOW\n", stderr);
110
        break;
111
    case EXCEPTION_ILLEGAL_INSTRUCTION:
112
        fputs("Error: EXCEPTION_ILLEGAL_INSTRUCTION\n", stderr);
113
        break;
114
    case EXCEPTION_IN_PAGE_ERROR:
115
        fputs("Error: EXCEPTION_IN_PAGE_ERROR\n", stderr);
116
        break;
117
    case EXCEPTION_INT_DIVIDE_BY_ZERO:
118
        fputs("Error: EXCEPTION_INT_DIVIDE_BY_ZERO\n", stderr);
119
        break;
120
    case EXCEPTION_INT_OVERFLOW:
121
        fputs("Error: EXCEPTION_INT_OVERFLOW\n", stderr);
122
        break;
123
    case EXCEPTION_INVALID_DISPOSITION:
124
        fputs("Error: EXCEPTION_INVALID_DISPOSITION\n", stderr);
125
        break;
126
    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
127
        fputs("Error: EXCEPTION_NONCONTINUABLE_EXCEPTION\n", stderr);
128
        break;
129
    case EXCEPTION_PRIV_INSTRUCTION:
130
        fputs("Error: EXCEPTION_PRIV_INSTRUCTION\n", stderr);
131
        break;
132
    case EXCEPTION_SINGLE_STEP:
133
        fputs("Error: EXCEPTION_SINGLE_STEP\n", stderr);
134
        break;
135
    case EXCEPTION_STACK_OVERFLOW:
136
        fputs("Error: EXCEPTION_STACK_OVERFLOW\n", stderr);
137
        break;
138
    default:
139
        fputs("Error: Unrecognized Exception\n", stderr);
140
        break;
141
    }
142
    fflush(stderr);
143
    /* If this is a stack overflow then we can't walk the stack, so just show
144
      where the error happened */
145
    if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) {
146
        print_stacktrace(ExceptionInfo->ContextRecord);
147
    } else {
11 pmbaty 148
        addr2line(windows_program_name, (void*)ExceptionInfo->ContextRecord->Eip);
1 pmbaty 149
    }
150
 
151
    return EXCEPTION_EXECUTE_HANDLER;
152
}
153
 
154
void OS_InstallSignalHandler(char* program_name) {
11 pmbaty 155
    strcpy(windows_program_name, program_name);
1 pmbaty 156
    SetUnhandledExceptionFilter(windows_exception_handler);
157
}
158
 
159
FILE* OS_fopen(const char* pathname, const char* mode) {
160
    FILE* f;
161
    errno_t err;
162
 
163
    f = NULL;
164
    err = fopen_s(&f, pathname, mode);
20 pmbaty 165
    if (err != 0) {
166
        fprintf(stderr, "Failed to open \"%s\" (%s)\n", pathname, strerror(err));
1 pmbaty 167
    }
168
 
169
    return f;
170
}
171
 
172
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) {
173
    // FIXME: unsafe implementation (echos the password)
174
    pBuffer[0] = '\0';
175
    fgets(pBuffer, pBufferLen, stdin);
176
    return strlen(pBuffer);
177
}
178
 
179
char* OS_Dirname(const char* path) {
180
    _splitpath(path, NULL, dirname_buf, NULL, NULL);
181
    return dirname_buf;
182
}
183
 
184
char* OS_Basename(const char* path) {
185
    _splitpath(path, NULL, NULL, fname_buf, NULL);
186
    return fname_buf;
187
}
188
 
189
#endif // _WIN32