FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
os_windows.cpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6
7#ifndef _WIN32
8#error This file can only be compiled under Windows.
9#endif
10
11#pragma comment(lib, "DbgHelp.lib")
12
13// Warning:
14// This source file MUST NOT include any other FEAT header file!
15#include <Windows.h>
16#include <DbgHelp.h>
17#include <Psapi.h>
18#include <cstdio>
19#include <cstdlib>
20
21namespace FEAT
22{
23 namespace Windows
24 {
26 {
27 LARGE_INTEGER li;
28 if(QueryPerformanceCounter(&li) == FALSE)
29 return 0ll;
30 return li.QuadPart;
31 }
32
34 {
35 LARGE_INTEGER li;
36 if(QueryPerformanceFrequency(&li) == FALSE)
37 return 0ll;
38 return li.QuadPart;
39 }
40
42 unsigned long long& work_set_size,
43 unsigned long long& work_set_size_peak,
44 unsigned long long& page_file_usage,
45 unsigned long long& page_file_usage_peak)
46 {
47 work_set_size = work_set_size_peak = page_file_usage = page_file_usage_peak = 0ull;
48
49 // initialize memory counters structure
50 PROCESS_MEMORY_COUNTERS pmc;
51 memset(&pmc, 0, sizeof(PROCESS_MEMORY_COUNTERS));
52
53 // get memory info
54 if(GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(PROCESS_MEMORY_COUNTERS)) != FALSE)
55 {
56 work_set_size = pmc.WorkingSetSize;
57 work_set_size_peak = pmc.PeakWorkingSetSize;
58 page_file_usage = pmc.PagefileUsage;
59 page_file_usage_peak = pmc.PeakPagefileUsage;
60 }
61 }
62
63 void dump_call_stack(CONTEXT& ctx, FILE* stream)
64 {
65 DWORD line_dsp;
66 DWORD64 addr;
67 struct
68 {
69 SYMBOL_INFO si;
70 char name[512];
71 } sim;
72
73 // retrieve our process and thread id
74 HANDLE prc = GetCurrentProcess();
75 HANDLE thr = GetCurrentThread();
76
77 // initialize line info
78 IMAGEHLP_LINE64 img_line;
79 img_line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
80
81 // create a symbol information structure
82 memset(&sim, 0, sizeof(SYMBOL_INFO) + 512);
83 sim.si.MaxNameLen = 512;
84 sim.si.SizeOfStruct = sizeof(SYMBOL_INFO);
85
86 // initialize symbol table
87 SymInitialize(prc, nullptr, TRUE);
88
89 // initialize the stack frame stuff
90 STACKFRAME64 stack_frame;
91 memset(&stack_frame, 0, sizeof(stack_frame));
92
93#if defined(_WIN64)
94 int machine_type = IMAGE_FILE_MACHINE_AMD64;
95 stack_frame.AddrPC.Offset = ctx.Rip;
96 stack_frame.AddrFrame.Offset = ctx.Rbp;
97 stack_frame.AddrStack.Offset = ctx.Rsp;
98#else
99 int machine_type = IMAGE_FILE_MACHINE_I386;
100 stack_frame.AddrPC.Offset = ctx.Eip;
101 stack_frame.AddrFrame.Offset = ctx.Ebp;
102 stack_frame.AddrStack.Offset = ctx.Esp;
103#endif
104 stack_frame.AddrPC.Mode = AddrModeFlat;
105 stack_frame.AddrFrame.Mode = AddrModeFlat;
106 stack_frame.AddrStack.Mode = AddrModeFlat;
107
108 // flush the output stream
109 fflush(stream);
110
111 // dump call stack
112 fprintf(stream, "\nCall-Stack Back-Trace:\n");
113 fprintf(stream, "----------------------\n");
114
115 // walk the stack
116 while (StackWalk64(machine_type, prc, thr, &stack_frame, &ctx, nullptr,
117 &SymFunctionTableAccess64, &SymGetModuleBase64, nullptr) != FALSE)
118 {
119 // get stack address
120 addr = stack_frame.AddrPC.Offset;
121
122 // print stack address
123 fprintf(stream, "0x%0*I64X", 2*int(sizeof(void*)), addr);
124
125 // get symbol info to obtain function name
126 if(SymFromAddr(prc, addr, 0, &sim.si) != FALSE)
127 {
128 // print function name
129 fprintf(stream, ": '%s'", sim.si.Name);
130 }
131 else
132 {
133 // cannot query function name
134 fprintf(stream, ": ???");
135 }
136
137 // get source file line info
138 if(SymGetLineFromAddr64(prc, addr, &line_dsp, &img_line) != FALSE)
139 {
140 // print source file and line
141 fprintf(stream, " ['%s' @ %i]", img_line.FileName, img_line.LineNumber);
142 }
143
144 // next stack entry
145 fprintf(stream, "\n");
146 }
147
148 // flush stream
149 fflush(stream);
150 }
151
153 {
154 // query context
155 CONTEXT ctx;
156 RtlCaptureContext(&ctx);
157 // make a copy
158 CONTEXT ctx2(ctx);
159 dump_call_stack(ctx2, stderr);
160 }
161
162 LONG WINAPI FeatWinExceptionFilter(LPEXCEPTION_POINTERS p)
163 {
164 // print an error header
165 fprintf(stderr, "\n>>>>> FATAL ERROR <<<<<\n\n");
166 fprintf(stderr, "Exception at 0x%0*I64X: ", 2*int(sizeof(void*)), (DWORD64)p->ExceptionRecord->ExceptionAddress);
167
168 // print exception info
169 switch(p->ExceptionRecord->ExceptionCode)
170 {
171 // note: There are more than 20 exceptions, but we do not handle all of them here explicitly.
172 case EXCEPTION_ACCESS_VIOLATION:
173 // This one is also known as 'segmentation fault'...
174 fprintf(stderr, "Access Violation when ");
175 if(p->ExceptionRecord->ExceptionInformation[0] == 0)
176 fprintf(stderr, "reading from");
177 else
178 fprintf(stderr, "writing to");
179 fprintf(stderr, " 0x%0*I64X\n", 2*int(sizeof(void*)), (DWORD64)p->ExceptionRecord->ExceptionInformation[1]);
180 break;
181 case EXCEPTION_ILLEGAL_INSTRUCTION:
182 fprintf(stderr, "Illegal Instruction\n");
183 break;
184 case EXCEPTION_IN_PAGE_ERROR:
185 fprintf(stderr, "Page Error\n");
186 break;
187 case EXCEPTION_STACK_OVERFLOW:
188 fprintf(stderr, "Stack Overflow\n");
189 break;
190 default:
191 // We do not handle all error types, so just dump the error code here...
192 fprintf(stderr, "Error 0x%08X\n", p->ExceptionRecord->ExceptionCode);
193 break;
194 }
195
196 // dump call stack
197 CONTEXT ctx = *p->ContextRecord;
198 dump_call_stack(ctx, stderr);
199
200 // flush
201 fprintf(stderr, "\n>>>>> TERMINATING <<<<<\n");
202 fflush(stderr);
203
204 // return
205 return EXCEPTION_EXECUTE_HANDLER;
206 }
207
209 {
210 // set our custom exception filter
211 SetUnhandledExceptionFilter(FeatWinExceptionFilter);
212 }
213
215 {
216 // disable error prompts
217 SetErrorMode(GetErrorMode() | SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
218 // disable handling of abort function
219 _set_abort_behavior(0, _WRITE_ABORT_MSG);
220 }
221
223 {
224 return GetCurrentProcessId();
225 }
226 } // namespace Windows
227} // namespace FEAT
void install_seh_filter()
Installs custom Windows Structured-Exception-Handler filter.
Definition: os_windows.cpp:208
void dump_call_stack_to_stderr()
Dumps the call-stack to stderr.
Definition: os_windows.cpp:152
void query_memory_usage(unsigned long long &work_set_size, unsigned long long &work_set_size_peak, unsigned long long &page_file_usage, unsigned long long &page_file_usage_peak)
Queries memory usage information.
Definition: os_windows.cpp:41
long long query_performance_frequency()
Wraps around the QueryPerformanceCounter function.
Definition: os_windows.cpp:33
void disable_error_prompts()
Disables Windows error dialog boxes.
Definition: os_windows.cpp:214
unsigned long get_current_process_id()
Returns the Windows process ID for the current process.
Definition: os_windows.cpp:222
long long query_performance_counter()
Wraps around the QueryPerformanceCounter function.
Definition: os_windows.cpp:25
FEAT namespace.
Definition: adjactor.hpp:12