ovr_sdk

annotate LibOVR/Src/Kernel/OVR_DebugHelp.h @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
rev   line source
nuclear@0 1 /************************************************************************************
nuclear@0 2
nuclear@0 3 Filename : OVR_DebugHelp.h
nuclear@0 4 Content : Platform-independent exception handling interface
nuclear@0 5 Created : October 6, 2014
nuclear@0 6
nuclear@0 7 Copyright : Copyright 2014 Oculus VR, LLC. All Rights reserved.
nuclear@0 8
nuclear@0 9 Licensed under the Apache License, Version 2.0 (the "License");
nuclear@0 10 you may not use this file except in compliance with the License.
nuclear@0 11 You may obtain a copy of the License at
nuclear@0 12
nuclear@0 13 http://www.apache.org/licenses/LICENSE-2.0
nuclear@0 14
nuclear@0 15 Unless required by applicable law or agreed to in writing, software
nuclear@0 16 distributed under the License is distributed on an "AS IS" BASIS,
nuclear@0 17 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nuclear@0 18 See the License for the specific language governing permissions and
nuclear@0 19 limitations under the License.
nuclear@0 20
nuclear@0 21 ************************************************************************************/
nuclear@0 22
nuclear@0 23 #ifndef OVR_ExceptionHandler_h
nuclear@0 24 #define OVR_ExceptionHandler_h
nuclear@0 25
nuclear@0 26
nuclear@0 27 #include "OVR_Types.h"
nuclear@0 28 #include "OVR_String.h"
nuclear@0 29 #include "OVR_Threads.h"
nuclear@0 30 #include "OVR_Atomic.h"
nuclear@0 31 #include "OVR_Nullptr.h"
nuclear@0 32 #include <stdio.h>
nuclear@0 33 #include <time.h>
nuclear@0 34
nuclear@0 35 #if defined(OVR_OS_WIN32) || defined(OVR_OS_WIN64)
nuclear@0 36 #include <Windows.h>
nuclear@0 37
nuclear@0 38 #elif defined(OVR_OS_APPLE)
nuclear@0 39 #include <pthread.h>
nuclear@0 40 #include <mach/thread_status.h>
nuclear@0 41 #include <mach/mach_types.h>
nuclear@0 42
nuclear@0 43 extern "C" void* MachHandlerThreadFunctionStatic(void*);
nuclear@0 44 extern "C" int catch_mach_exception_raise_state_identity_OVR(mach_port_t, mach_port_t, mach_port_t, exception_type_t, mach_exception_data_type_t*,
nuclear@0 45 mach_msg_type_number_t, int*, thread_state_t, mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t*);
nuclear@0 46 #elif defined(OVR_OS_LINUX)
nuclear@0 47 #include <pthread.h>
nuclear@0 48 #endif
nuclear@0 49
nuclear@0 50
nuclear@0 51 OVR_DISABLE_MSVC_WARNING(4351) // new behavior: elements of array will be default initialized
nuclear@0 52
nuclear@0 53
nuclear@0 54 namespace OVR {
nuclear@0 55
nuclear@0 56 // Thread identifiers
nuclear@0 57 //typedef void* ThreadHandle; // Already defined by OVR Threads. Same as Windows thread handle, Unix pthread_t.
nuclear@0 58 //typedef void* ThreadId; // Already defined by OVR Threads. Used by Windows as DWORD thread id, by Unix as pthread_t.
nuclear@0 59 typedef uintptr_t ThreadSysId; // System thread identifier. Used by Windows the same as ThreadId (DWORD), thread_act_t on Mac/BSD, lwp id on Linux.
nuclear@0 60
nuclear@0 61 // Thread constants
nuclear@0 62 // To do: Move to OVR Threads
nuclear@0 63 #define OVR_THREADHANDLE_INVALID ((ThreadHandle*)nullptr)
nuclear@0 64 #define OVR_THREADID_INVALID ((ThreadId*)nullptr)
nuclear@0 65 #define OVR_THREADSYSID_INVALID ((uintptr_t)0)
nuclear@0 66
nuclear@0 67 OVR::ThreadSysId ConvertThreadHandleToThreadSysId(OVR::ThreadHandle threadHandle);
nuclear@0 68 OVR::ThreadHandle ConvertThreadSysIdToThreadHandle(OVR::ThreadSysId threadSysId); // The returned handle must be freed with FreeThreadHandle.
nuclear@0 69 void FreeThreadHandle(OVR::ThreadHandle threadHandle); // Frees the handle returned by ConvertThreadSysIdToThreadHandle.
nuclear@0 70 OVR::ThreadSysId GetCurrentThreadSysId();
nuclear@0 71
nuclear@0 72 // CPUContext
nuclear@0 73 #if defined(OVR_OS_MS)
nuclear@0 74 typedef CONTEXT CPUContext;
nuclear@0 75 #elif defined(OVR_OS_MAC)
nuclear@0 76 struct CPUContext
nuclear@0 77 {
nuclear@0 78 x86_thread_state_t threadState; // This works for both x86 and x64.
nuclear@0 79 x86_float_state_t floatState;
nuclear@0 80 x86_debug_state_t debugState;
nuclear@0 81 x86_avx_state_t avxState;
nuclear@0 82 x86_exception_state exceptionState;
nuclear@0 83
nuclear@0 84 CPUContext() { memset(this, 0, sizeof(CPUContext)); }
nuclear@0 85 };
nuclear@0 86 #elif defined(OVR_OS_LINUX)
nuclear@0 87 typedef int CPUContext; // To do.
nuclear@0 88 #endif
nuclear@0 89
nuclear@0 90
nuclear@0 91 // Tells if the current process appears to be running under a debugger. Does not attempt to
nuclear@0 92 // detect the case of sleath debuggers (malware-related for example).
nuclear@0 93 bool OVRIsDebuggerPresent();
nuclear@0 94
nuclear@0 95 // Exits the process with the given exit code.
nuclear@0 96 #if !defined(OVR_NORETURN)
nuclear@0 97 #if defined(OVR_CC_MSVC)
nuclear@0 98 #define OVR_NORETURN __declspec(noreturn)
nuclear@0 99 #else
nuclear@0 100 #define OVR_NORETURN __attribute__((noreturn))
nuclear@0 101 #endif
nuclear@0 102 #endif
nuclear@0 103 OVR_NORETURN void ExitProcess(intptr_t processReturnValue);
nuclear@0 104
nuclear@0 105 // Returns the instruction pointer of the caller for the position right after the call.
nuclear@0 106 OVR_NO_INLINE void GetInstructionPointer(void*& pInstruction);
nuclear@0 107
nuclear@0 108 // Returns the stack base and limit addresses for the given thread, or for the current thread if the threadHandle is default.
nuclear@0 109 // The stack limit is a value less than the stack base on most platforms, as stacks usually grow downward.
nuclear@0 110 // Some platforms (e.g. Microsoft) have dynamically resizing stacks, in which case the stack limit reflects the current limit.
nuclear@0 111 void GetThreadStackBounds(void*& pStackBase, void*& pStackLimit, ThreadHandle threadHandle = OVR_THREADHANDLE_INVALID);
nuclear@0 112
nuclear@0 113
nuclear@0 114 // Equates to VirtualAlloc/VirtualFree on Windows, mmap/munmap on Unix.
nuclear@0 115 // These are useful for when you need system-supplied memory pages.
nuclear@0 116 // These are also useful for when you need to allocate memory in a way
nuclear@0 117 // that doesn't affect the application heap.
nuclear@0 118 void* SafeMMapAlloc(size_t size);
nuclear@0 119 void SafeMMapFree(const void* memory, size_t size);
nuclear@0 120
nuclear@0 121
nuclear@0 122 // OVR_MAX_PATH
nuclear@0 123 // Max file path length (for most uses).
nuclear@0 124 // To do: move this to OVR_File.
nuclear@0 125 #if defined(OVR_OS_MS) // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
nuclear@0 126 #define OVR_MAX_PATH 260 // Windows can use paths longer than this in some cases (network paths, UNC paths).
nuclear@0 127 #else
nuclear@0 128 #define OVR_MAX_PATH 1024 // This isn't a strict limit on all Unix-based platforms.
nuclear@0 129 #endif
nuclear@0 130
nuclear@0 131
nuclear@0 132 // ModuleHandle
nuclear@0 133 #if defined(OVR_OS_MS)
nuclear@0 134 typedef void* ModuleHandle; // from LoadLibrary()
nuclear@0 135 #elif defined(OVR_OS_APPLE) || defined(OVR_OS_UNIX)
nuclear@0 136 typedef void* ModuleHandle; // from dlopen()
nuclear@0 137 #endif
nuclear@0 138
nuclear@0 139 #define OVR_MODULEHANDLE_INVALID ((ModuleHandle*)nullptr)
nuclear@0 140
nuclear@0 141
nuclear@0 142
nuclear@0 143 // Module info constants
nuclear@0 144 static const ModuleHandle kMIHandleInvalid = OVR_MODULEHANDLE_INVALID;
nuclear@0 145 static const uint64_t kMIAddressInvalid = 0xffffffffffffffffull;
nuclear@0 146 static const uint64_t kMISizeInvalid = 0xffffffffffffffffull;
nuclear@0 147 static const int32_t kMILineNumberInvalid = -1;
nuclear@0 148 static const int32_t kMIFunctionOffsetInvalid = -1;
nuclear@0 149 static const uint64_t kMIBaseAddressInvalid = 0xffffffffffffffffull;
nuclear@0 150 static const uint64_t kMIBaseAddressUnspecified = 0xffffffffffffffffull;
nuclear@0 151
nuclear@0 152 struct ModuleInfo
nuclear@0 153 {
nuclear@0 154 ModuleHandle handle;
nuclear@0 155 uint64_t baseAddress; // The actual runtime base address of the module. May be different from the base address specified in the debug symbol file.
nuclear@0 156 uint64_t size;
nuclear@0 157 char filePath[OVR_MAX_PATH];
nuclear@0 158 char name[32];
nuclear@0 159 char type[8]; // Unix-specific. e.g. __TEXT
nuclear@0 160 char permissions[8]; // Unix specific. e.g. "drwxr-xr-x"
nuclear@0 161
nuclear@0 162 ModuleInfo() : handle(kMIHandleInvalid), baseAddress(kMIBaseAddressInvalid), size(0), filePath(), name(){}
nuclear@0 163 };
nuclear@0 164
nuclear@0 165
nuclear@0 166 // Refers to symbol info for an instruction address.
nuclear@0 167 // Info includes function name, source code file/line, and source code itself.
nuclear@0 168 struct SymbolInfo
nuclear@0 169 {
nuclear@0 170 uint64_t address;
nuclear@0 171 uint64_t size;
nuclear@0 172 const ModuleInfo* pModuleInfo;
nuclear@0 173 char filePath[OVR_MAX_PATH];
nuclear@0 174 int32_t fileLineNumber;
nuclear@0 175 char function[128]; // This is a fixed size because we need to use it during application exceptions.
nuclear@0 176 int32_t functionOffset;
nuclear@0 177 char sourceCode[1024]; // This is a string representing the code itself and not a file path to the code.
nuclear@0 178
nuclear@0 179 SymbolInfo() : address(kMIAddressInvalid), size(kMISizeInvalid), pModuleInfo(nullptr), filePath(),
nuclear@0 180 fileLineNumber(kMILineNumberInvalid), function(), functionOffset(kMIFunctionOffsetInvalid), sourceCode() {}
nuclear@0 181 };
nuclear@0 182
nuclear@0 183
nuclear@0 184 // Implements support for reading thread lists, module lists, backtraces, and backtrace symbols.
nuclear@0 185 class SymbolLookup
nuclear@0 186 {
nuclear@0 187 public:
nuclear@0 188 SymbolLookup();
nuclear@0 189 ~SymbolLookup();
nuclear@0 190
nuclear@0 191 void AddSourceCodeDirectory(const char* pDirectory);
nuclear@0 192
nuclear@0 193 bool Initialize();
nuclear@0 194 void Shutdown();
nuclear@0 195
nuclear@0 196 // Should be disabled when within an exception handler.
nuclear@0 197 void EnableMemoryAllocation(bool enabled);
nuclear@0 198
nuclear@0 199 // Retrieves the backtrace (call stack) of the given thread. There may be some per-platform restrictions on this.
nuclear@0 200 // Returns the number written, which will be <= addressArrayCapacity.
nuclear@0 201 // This may not work on some platforms unless stack frames are enabled.
nuclear@0 202 // For Microsoft platforms the platformThreadContext is CONTEXT*.
nuclear@0 203 // For Apple platforms the platformThreadContext is x86_thread_state_t* or arm_thread_state_t*.
nuclear@0 204 // If threadSysIdHelp is non-zero, it may be used by the implementation to help produce a better backtrace.
nuclear@0 205 size_t GetBacktrace(void* addressArray[], size_t addressArrayCapacity, size_t skipCount = 0, void* platformThreadContext = nullptr, OVR::ThreadSysId threadSysIdHelp = OVR_THREADSYSID_INVALID);
nuclear@0 206
nuclear@0 207 // Retrieves the backtrace for the given ThreadHandle.
nuclear@0 208 // Returns the number written, which will be <= addressArrayCapacity.
nuclear@0 209 size_t GetBacktraceFromThreadHandle(void* addressArray[], size_t addressArrayCapacity, size_t skipCount = 0, OVR::ThreadHandle threadHandle = OVR_THREADHANDLE_INVALID);
nuclear@0 210
nuclear@0 211 // Retrieves the backtrace for the given ThreadSysId.
nuclear@0 212 // Returns the number written, which will be <= addressArrayCapacity.
nuclear@0 213 size_t GetBacktraceFromThreadSysId(void* addressArray[], size_t addressArrayCapacity, size_t skipCount = 0, OVR::ThreadSysId threadSysId = OVR_THREADSYSID_INVALID);
nuclear@0 214
nuclear@0 215 // Gets a list of the modules (e.g. DLLs) present in the current process.
nuclear@0 216 // Writes as many ModuleInfos as possible to pModuleInfoArray.
nuclear@0 217 // Returns the required count of ModuleInfos, which will be > moduleInfoArrayCapacity if the capacity needs to be larger.
nuclear@0 218 size_t GetModuleInfoArray(ModuleInfo* pModuleInfoArray, size_t moduleInfoArrayCapacity);
nuclear@0 219
nuclear@0 220 // Retrieves a list of the current threads. Unless the process is paused the list is volatile.
nuclear@0 221 // Returns the required capacity, which may be larger than threadArrayCapacity.
nuclear@0 222 // Either array can be NULL to specify that it's not written to.
nuclear@0 223 // For Windows the caller needs to CloseHandle the returned ThreadHandles. This can be done by calling DoneThreadList.
nuclear@0 224 size_t GetThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCapacity);
nuclear@0 225
nuclear@0 226 // Frees any references to thread handles or ids returned by GetThreadList;
nuclear@0 227 void DoneThreadList(ThreadHandle* threadHandleArray, ThreadSysId* threadSysIdArray, size_t threadArrayCount);
nuclear@0 228
nuclear@0 229 // Writes a given thread's callstack with symbols to the given output.
nuclear@0 230 // It may not be safe to call this from an exception handler, as sOutput allocates memory.
nuclear@0 231 bool ReportThreadCallstack(OVR::String& sOutput, size_t skipCount = 0, ThreadSysId threadSysId = OVR_THREADSYSID_INVALID);
nuclear@0 232
nuclear@0 233 // Writes all thread's callstacks with symbols to the given output.
nuclear@0 234 // It may not be safe to call this from an exception handler, as sOutput allocates memory.
nuclear@0 235 bool ReportThreadCallstacks(OVR::String& sOutput, size_t skipCount = 0);
nuclear@0 236
nuclear@0 237 // Retrieves symbol info for the given address.
nuclear@0 238 bool LookupSymbol(uint64_t address, SymbolInfo& symbolInfo);
nuclear@0 239 bool LookupSymbols(uint64_t* addressArray, SymbolInfo* pSymbolInfoArray, size_t arraySize);
nuclear@0 240
nuclear@0 241 const ModuleInfo* GetModuleInfoForAddress(uint64_t address); // The returned ModuleInfo points to an internal structure.
nuclear@0 242
nuclear@0 243 protected:
nuclear@0 244 bool RefreshModuleList();
nuclear@0 245
nuclear@0 246 protected:
nuclear@0 247 bool initialized;
nuclear@0 248 bool allowMemoryAllocation; // True by default. If true then we allow allocating memory (and as a result provide less information). This is useful for when in an exception handler.
nuclear@0 249 bool moduleListUpdated;
nuclear@0 250 ModuleInfo moduleInfoArray[96]; // Cached list of modules we use. This is a fixed size because we need to use it during application exceptions.
nuclear@0 251 size_t moduleInfoArraySize;
nuclear@0 252 };
nuclear@0 253
nuclear@0 254
nuclear@0 255
nuclear@0 256 // ExceptionInfo
nuclear@0 257 // We need to be careful to avoid data types that can allocate memory while we are
nuclear@0 258 // handling an exception, as the memory system may be corrupted at that point in time.
nuclear@0 259 struct ExceptionInfo
nuclear@0 260 {
nuclear@0 261 tm time; // GM time.
nuclear@0 262 time_t timeVal; // GM time_t (seconds since 1970).
nuclear@0 263 void* backtrace[64];
nuclear@0 264 size_t backtraceCount;
nuclear@0 265 ThreadHandle threadHandle; //
nuclear@0 266 ThreadSysId threadSysId; //
nuclear@0 267 char threadName[32]; // Cannot be an allocating String object.
nuclear@0 268 void* pExceptionInstructionAddress;
nuclear@0 269 void* pExceptionMemoryAddress;
nuclear@0 270 CPUContext cpuContext;
nuclear@0 271 char exceptionDescription[1024]; // Cannot be an allocating String object.
nuclear@0 272 SymbolInfo symbolInfo; // SymbolInfo for the exception location.
nuclear@0 273
nuclear@0 274 #if defined(OVR_OS_MS)
nuclear@0 275 EXCEPTION_RECORD exceptionRecord; // This is a Windows SDK struct.
nuclear@0 276 #elif defined(OVR_OS_APPLE)
nuclear@0 277 uint64_t exceptionType; // e.g. EXC_BAD_INSTRUCTION, EXC_BAD_ACCESS, etc.
nuclear@0 278 uint32_t cpuExceptionId; // The x86/x64 CPU trap id.
nuclear@0 279 uint32_t cpuExceptionIdError; // The x86/x64 CPU trap id extra info.
nuclear@0 280 int64_t machExceptionDetail[4]; // Kernel exception code info.
nuclear@0 281 int machExceptionDetailCount; // Count of valid entries.
nuclear@0 282 #endif
nuclear@0 283
nuclear@0 284 ExceptionInfo();
nuclear@0 285 };
nuclear@0 286
nuclear@0 287
nuclear@0 288 // Implments support for asynchronous exception handling and basic exception report generation.
nuclear@0 289 // If you are implementing exception handling for a commercial application and want auto-uploading
nuclear@0 290 // functionality you may want to consider using something like Google Breakpad. This exception handler
nuclear@0 291 // is for in-application debug/diagnostic services, though it can write a report that has similar
nuclear@0 292 // information to Breakpad or OS-provided reports such as Apple .crash files.
nuclear@0 293 //
nuclear@0 294 // Example usage:
nuclear@0 295 // ExceptionHandler exceptionHandler;
nuclear@0 296 //
nuclear@0 297 // int main(int, char**)
nuclear@0 298 // {
nuclear@0 299 // exceptionHandler.Enable(true);
nuclear@0 300 // exceptionHandler.SetExceptionListener(pSomeListener, 0); // Optional listener hook.
nuclear@0 301 // }
nuclear@0 302 //
nuclear@0 303 class ExceptionHandler
nuclear@0 304 {
nuclear@0 305 public:
nuclear@0 306 ExceptionHandler();
nuclear@0 307 ~ExceptionHandler();
nuclear@0 308
nuclear@0 309 bool Enable(bool enable);
nuclear@0 310
nuclear@0 311 // Some report info can be considered private information of the user, such as the current process list,
nuclear@0 312 // computer name, IP address or other identifying info, etc. We should not report this information for
nuclear@0 313 // external users unless they agree to this.
nuclear@0 314 void EnableReportPrivacy(bool enable);
nuclear@0 315
nuclear@0 316 struct ExceptionListener
nuclear@0 317 {
nuclear@0 318 virtual ~ExceptionListener(){}
nuclear@0 319 virtual int HandleException(uintptr_t userValue, ExceptionHandler* pExceptionHandler, ExceptionInfo* pExceptionInfo, const char* reportFilePath) = 0;
nuclear@0 320 };
nuclear@0 321
nuclear@0 322 void SetExceptionListener(ExceptionListener* pExceptionListener, uintptr_t userValue);
nuclear@0 323
nuclear@0 324 // What we do after handling the exception.
nuclear@0 325 enum ExceptionResponse
nuclear@0 326 {
nuclear@0 327 kERContinue, // Continue execution. Will result in the exception being re-generated unless the application has fixed the cause. Similar to Windows EXCEPTION_CONTINUE_EXECUTION.
nuclear@0 328 kERHandle, // Causes the OS to handle the exception as it normally would. Similar to Windows EXCEPTION_EXECUTE_HANDLER.
nuclear@0 329 kERTerminate, // Exit the application.
nuclear@0 330 kERThrow, // Re-throw the exception. Other handlers may catch it. Similar to Windows EXCEPTION_CONTINUE_SEARCH.
nuclear@0 331 kERDefault // Usually set to kERTerminate.
nuclear@0 332 };
nuclear@0 333
nuclear@0 334 void SetExceptionResponse(ExceptionResponse er)
nuclear@0 335 { exceptionResponse = er; }
nuclear@0 336
nuclear@0 337 // Allws you to add an arbitrary description of the current application, which will be added to exception reports.
nuclear@0 338 void SetAppDescription(const char* appDescription);
nuclear@0 339
nuclear@0 340 // If the report path has a "%s" in its name, then assume the path is a sprintf format and write it
nuclear@0 341 // with the %s specified as a date/time string.
nuclear@0 342 // The report path can be "default" to signify that you want to use the default user location.
nuclear@0 343 // Example usage:
nuclear@0 344 // handler.SetExceptionPaths("/Users/Current/Exceptions/Exception %s.txt");
nuclear@0 345 void SetExceptionPaths(const char* exceptionReportPath, const char* exceptionMinidumpPath = nullptr);
nuclear@0 346
nuclear@0 347 // Allows you to specify base directories for code paths, which can be used to associate exception addresses to lines
nuclear@0 348 // of code as opposed to just file names and line numbers, or function names plus binary offsets.
nuclear@0 349 void SetCodeBaseDirectoryPaths(const char* codeBaseDirectoryPathArray[], size_t codeBaseDirectoryPathCount);
nuclear@0 350
nuclear@0 351 // Given an exception report at a given file path, returns a string suitable for displaying in a message
nuclear@0 352 // box or similar user interface during the handling of an exception. The returned string must be passed
nuclear@0 353 // to FreeMessageBoxText when complete.
nuclear@0 354 static const char* GetExceptionUIText(const char* exceptionReportPath);
nuclear@0 355 static void FreeExceptionUIText(const char* messageBoxText);
nuclear@0 356
nuclear@0 357 protected:
nuclear@0 358 void WriteExceptionDescription();
nuclear@0 359 void WriteReport();
nuclear@0 360 void WriteReportLine(const char* pLine);
nuclear@0 361 void WriteReportLineF(const char* format, ...);
nuclear@0 362 void WriteThreadCallstack(ThreadHandle threadHandle, ThreadSysId threadSysId, const char* additionalInfo);
nuclear@0 363 void WriteMiniDump();
nuclear@0 364
nuclear@0 365 // Runtime constants
nuclear@0 366 bool enabled;
nuclear@0 367 bool reportPrivacyEnabled; // Defaults to true.
nuclear@0 368 ExceptionResponse exceptionResponse; // Defaults to kERHandle
nuclear@0 369 ExceptionListener* exceptionListener;
nuclear@0 370 uintptr_t exceptionListenerUserValue;
nuclear@0 371 String appDescription;
nuclear@0 372 String codeBasePathArray[6]; // 6 is arbitrary.
nuclear@0 373 char reportFilePath[OVR_MAX_PATH];// May be an encoded path, in that it has "%s" in it or is named "default". See reporFiletPathActual for the runtime actual report path.
nuclear@0 374 int miniDumpFlags;
nuclear@0 375 char miniDumpFilePath[OVR_MAX_PATH];
nuclear@0 376 FILE* file; // Can/should we use OVR Files for this?
nuclear@0 377 char scratchBuffer[4096];
nuclear@0 378 SymbolLookup symbolLookup;
nuclear@0 379
nuclear@0 380 // Runtime variables
nuclear@0 381 bool exceptionOccurred;
nuclear@0 382 OVR::AtomicInt<uint32_t> handlingBusy;
nuclear@0 383 char reportFilePathActual[OVR_MAX_PATH];
nuclear@0 384 char minidumpFilePathActual[OVR_MAX_PATH];
nuclear@0 385 int terminateReturnValue;
nuclear@0 386 ExceptionInfo exceptionInfo;
nuclear@0 387
nuclear@0 388 #if defined(OVR_OS_MS)
nuclear@0 389 void* vectoredHandle;
nuclear@0 390 LPTOP_LEVEL_EXCEPTION_FILTER previousFilter;
nuclear@0 391 LPEXCEPTION_POINTERS pExceptionPointers;
nuclear@0 392
nuclear@0 393 friend LONG WINAPI Win32ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers);
nuclear@0 394 LONG ExceptionFilter(LPEXCEPTION_POINTERS pExceptionPointers);
nuclear@0 395
nuclear@0 396 #elif defined(OVR_OS_APPLE)
nuclear@0 397 struct SavedExceptionPorts
nuclear@0 398 {
nuclear@0 399 SavedExceptionPorts() : count(0) { memset(this, 0, sizeof(SavedExceptionPorts)); }
nuclear@0 400
nuclear@0 401 mach_msg_type_number_t count;
nuclear@0 402 exception_mask_t masks[6];
nuclear@0 403 exception_handler_t ports[6];
nuclear@0 404 exception_behavior_t behaviors[6];
nuclear@0 405 thread_state_flavor_t flavors[6];
nuclear@0 406 };
nuclear@0 407
nuclear@0 408 friend void* ::MachHandlerThreadFunctionStatic(void*);
nuclear@0 409 friend int ::catch_mach_exception_raise_state_identity_OVR(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
nuclear@0 410 mach_exception_data_type_t*, mach_msg_type_number_t, int*, thread_state_t,
nuclear@0 411 mach_msg_type_number_t, thread_state_t, mach_msg_type_number_t*);
nuclear@0 412
nuclear@0 413 bool InitMachExceptionHandler();
nuclear@0 414 void ShutdownMachExceptionHandler();
nuclear@0 415 void* MachHandlerThreadFunction();
nuclear@0 416 kern_return_t HandleMachException(mach_port_t port, mach_port_t thread, mach_port_t task, exception_type_t exceptionType,
nuclear@0 417 mach_exception_data_type_t* pExceptionDetail, mach_msg_type_number_t exceptionDetailCount,
nuclear@0 418 int* pFlavor, thread_state_t pOldState, mach_msg_type_number_t oldStateCount, thread_state_t pNewState,
nuclear@0 419 mach_msg_type_number_t* pNewStateCount);
nuclear@0 420 kern_return_t ForwardMachException(mach_port_t thread, mach_port_t task, exception_type_t exceptionType,
nuclear@0 421 mach_exception_data_t pExceptionDetail, mach_msg_type_number_t exceptionDetailCount);
nuclear@0 422
nuclear@0 423 bool machHandlerInitialized;
nuclear@0 424 mach_port_t machExceptionPort;
nuclear@0 425 SavedExceptionPorts machExceptionPortsSaved;
nuclear@0 426 volatile bool machThreadShouldContinue;
nuclear@0 427 volatile bool machThreadExecuting;
nuclear@0 428 pthread_t machThread;
nuclear@0 429
nuclear@0 430 #elif defined(OVR_OS_LINUX)
nuclear@0 431 // To do.
nuclear@0 432 #endif
nuclear@0 433 };
nuclear@0 434
nuclear@0 435
nuclear@0 436 // Identifies basic exception types for the CreateException function.
nuclear@0 437 enum CreateExceptionType
nuclear@0 438 {
nuclear@0 439 kCETAccessViolation, // Read or write to inaccessable memory.
nuclear@0 440 kCETAlignment, // Misaligned read or write.
nuclear@0 441 kCETDivideByZero, // Integer divide by zero.
nuclear@0 442 kCETFPU, // Floating point / VPU exception.
nuclear@0 443 kCETIllegalInstruction, // Illegal opcode.
nuclear@0 444 kCETStackCorruption, // Stack frame was corrupted.
nuclear@0 445 kCETStackOverflow, // Stack ran out of space, often due to infinite recursion.
nuclear@0 446 kCETTrap // System/OS trap (system call).
nuclear@0 447 };
nuclear@0 448
nuclear@0 449
nuclear@0 450 // Creates an exception of the given type, primarily for testing.
nuclear@0 451 void CreateException(CreateExceptionType exceptionType);
nuclear@0 452
nuclear@0 453
nuclear@0 454
nuclear@0 455 } // namespace OVR
nuclear@0 456
nuclear@0 457
nuclear@0 458 OVR_RESTORE_MSVC_WARNING()
nuclear@0 459
nuclear@0 460
nuclear@0 461 #endif // Header include guard