|
31 | 31 | #include <stdio.h> |
32 | 32 | #include <stddef.h> |
33 | 33 | #include <math.h> |
| 34 | +#include <signal.h> |
| 35 | + |
| 36 | +#define MAX_STACK_FRAMES 64 |
| 37 | + |
| 38 | +void diag(const char *fstr, ...); |
34 | 39 |
|
35 | 40 | #ifdef _WIN32 |
36 | 41 | # define _WINSOCKAPI_ |
37 | 42 | # include <windows.h> |
38 | 43 | # include <shlwapi.h> |
| 44 | +# include <dbghelp.h> |
| 45 | +//# pragma comment(lib, "dbghelp.lib") |
| 46 | + |
39 | 47 |
|
40 | 48 | char* strcasestr(const char* HayStack, const char* Needle) |
41 | 49 | { |
42 | 50 | return StrStrIA(HayStack, Needle); |
43 | 51 | } |
| 52 | + |
| 53 | + |
| 54 | +void print_btrace(int sig) |
| 55 | +{ |
| 56 | + void* callstack[MAX_STACK_FRAMES]; |
| 57 | + SYMBOL_INFO* symbol; |
| 58 | + IMAGEHLP_LINE64 line; |
| 59 | + HANDLE process = GetCurrentProcess(); |
| 60 | + |
| 61 | + diag("Caught signal %d", sig); |
| 62 | + diag("Stack Trace:"); |
| 63 | + SymSetOptions(SYMOPT_LOAD_LINES); |
| 64 | + SymInitialize(process, NULL, TRUE); |
| 65 | + |
| 66 | + memset((void*)&line, 0, sizeof(IMAGEHLP_LINE64)); |
| 67 | + line.SizeOfStruct= sizeof(IMAGEHLP_LINE64); |
| 68 | + |
| 69 | + symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256, 1); |
| 70 | + symbol->MaxNameLen = 255; |
| 71 | + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); |
| 72 | + |
| 73 | + WORD frames = CaptureStackBackTrace(0, MAX_STACK_FRAMES, callstack, NULL); |
| 74 | + |
| 75 | + // At 0 index will be btrace itself |
| 76 | + for (int i = 1; i < frames; ++i) |
| 77 | + { |
| 78 | + DWORD64 displacement= 0; |
| 79 | + SymFromAddr(process, (DWORD64)callstack[i], 0, symbol); |
| 80 | + if (!SymGetLineFromAddr64(process, (DWORD64)callstack[i], &displacement, &line)) |
| 81 | + { |
| 82 | + DWORD error= GetLastError(); |
| 83 | + diag("SymGetLineFromAddr64 returned error : %d", error); |
| 84 | + line.FileName= "<no file name>"; |
| 85 | + } |
| 86 | + //stderr? |
| 87 | + printf("%d: %s(%s:%u)\n", i, symbol->Name, line.FileName, line.LineNumber); |
| 88 | + } |
| 89 | + |
| 90 | + free(symbol); |
| 91 | + SymCleanup(process); |
| 92 | + exit(1); |
| 93 | +} |
| 94 | + |
44 | 95 | #else |
45 | 96 |
|
46 | 97 | # include <string.h> |
47 | 98 | # include <errno.h> |
48 | 99 | # include <wchar.h> |
49 | 100 | # include <unistd.h> |
| 101 | +# include <execinfo.h> |
| 102 | + |
50 | 103 | # include "ma_conv_charset.h" |
51 | 104 |
|
52 | 105 | /* Mimicking of VS' _snprintf */ |
@@ -111,6 +164,17 @@ int strcpy_s(char *dest, size_t buffer_size, const char *src) |
111 | 164 | #define _atoi64(str) strtoll((str), NULL, 10) |
112 | 165 | #define _i64toa(a,b,c) longlong2str((a),(b),(c)) |
113 | 166 |
|
| 167 | +void print_btrace(int sig) |
| 168 | +{ |
| 169 | + void* callstack[MAX_STACK_FRAMES]; |
| 170 | + int frames = backtrace(callstack, MAX_STACK_FRAMES); |
| 171 | + |
| 172 | + diag("Caught signal %d\n", sig); |
| 173 | + diag("Stack Trace:\n"); |
| 174 | + backtrace_symbols_fd(callstack, frames, STDERR_FILENO); |
| 175 | + exit(1); |
| 176 | +} |
| 177 | + |
114 | 178 | #endif |
115 | 179 |
|
116 | 180 | #include <sql.h> |
@@ -307,11 +371,16 @@ void get_env_defaults() |
307 | 371 | } |
308 | 372 | } |
309 | 373 |
|
310 | | - |
| 374 | +/* Reads env defaults, command line options, but also it sets functions to process signals(SIGABRT SIGSEGV) |
| 375 | + * as all tests run it and run only once. even though not the right place |
| 376 | + */ |
311 | 377 | void get_options(int argc, char **argv) |
312 | 378 | { |
313 | 379 | int i; |
314 | 380 |
|
| 381 | + signal(SIGABRT, print_btrace); |
| 382 | + signal(SIGSEGV, print_btrace); |
| 383 | + |
315 | 384 | get_env_defaults(); |
316 | 385 |
|
317 | 386 | for (i= 1; i < argc; i+= 2) /* "d:u:p:P:s:S:?" */ |
|
0 commit comments