1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
/*
* Copyright (C) 2018-2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "seh_exception.h"
#include "shared/source/os_interface/os_library.h"
#include <memory>
#include <string>
#pragma warning(push)
#pragma warning(disable : 4091)
#include <dbghelp.h>
#pragma warning(pop)
#include <windows.h>
#include <excpt.h>
#include <psapi.h>
std::string SehException::getExceptionDescription(unsigned int code) {
switch (static_cast<long>(code)) {
case EXCEPTION_ACCESS_VIOLATION:
return "Access violation";
case EXCEPTION_DATATYPE_MISALIGNMENT:
return "Datatype misalignment";
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
return "Divide by zero";
case EXCEPTION_STACK_OVERFLOW:
return "Stack overflow";
default:
break;
}
return "Unknown";
}
int SehException::filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
printf("EXCEPTION: %s\n", SehException::getExceptionDescription(code).c_str());
if (static_cast<long>(code) != EXCEPTION_STACK_OVERFLOW) {
std::string callstack;
SehException::getCallStack(code, ep, callstack);
printf("Callstack:\n\n%s", callstack.c_str());
}
return EXCEPTION_EXECUTE_HANDLER;
}
void SehException::getCallStack(unsigned int code, struct _EXCEPTION_POINTERS *ep, std::string &stack) {
DWORD machine = 0;
HANDLE hProcess = GetCurrentProcess();
HANDLE hThread = GetCurrentThread();
auto contextRecord = *ep->ContextRecord;
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
machine = IMAGE_FILE_MACHINE_I386;
} else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
machine = IMAGE_FILE_MACHINE_AMD64;
} else {
stack = "invalid processor arch";
return;
}
stack.clear();
BOOL result = SymInitialize(hProcess, NULL, TRUE);
if (result == FALSE) {
return;
}
STACKFRAME64 stackFrame;
memset(&stackFrame, 0, sizeof(STACKFRAME64));
const int nameSize = 255;
char buffer[sizeof(IMAGEHLP_SYMBOL64) + (nameSize + 1) * sizeof(char)];
IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
symbol->MaxNameLength = nameSize;
DWORD displacement = 0;
DWORD64 displacement64 = 0;
std::unique_ptr<NEO::OsLibrary> psApiLib(NEO::OsLibrary::loadFunc({"psapi.dll"}));
auto getMappedFileName = reinterpret_cast<getMappedFileNameFunction>(psApiLib->getProcAddress("GetMappedFileNameA"));
size_t callstackCounter = 0;
const size_t maxCallstackDepth = 1000;
#ifdef _WIN64
stackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
stackFrame.AddrStack.Mode = AddrModeFlat;
stackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
stackFrame.AddrFrame.Mode = AddrModeFlat;
#else
stackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
stackFrame.AddrStack.Mode = AddrModeFlat;
stackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp;
stackFrame.AddrFrame.Mode = AddrModeFlat;
#endif
while (callstackCounter < maxCallstackDepth) {
symbol->Name[255] = '\0';
if (!StackWalk64(machine, hProcess, hThread, &stackFrame, &contextRecord, nullptr, SymFunctionTableAccess64, SymGetModuleBase64, 0)) {
break;
}
if (stackFrame.AddrFrame.Offset == 0) {
break;
}
std::string lineInCode;
std::string module;
std::string symbolName;
DWORD64 address = stackFrame.AddrPC.Offset;
IMAGEHLP_LINE64 imageLine;
imageLine.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
if (SymGetLineFromAddr64(hProcess, address, &displacement, &imageLine)) {
lineInCode = imageLine.FileName;
char filename[MAX_PATH + 1];
filename[MAX_PATH] = '\0';
if (getMappedFileName(hProcess, reinterpret_cast<LPVOID>(imageLine.Address), filename, MAX_PATH)) {
module = filename;
}
}
if (SymGetSymFromAddr64(hProcess, address, &displacement64, symbol)) {
symbolName = symbol->Name;
}
addLineToCallstack(stack, callstackCounter, module, lineInCode, symbolName);
callstackCounter++;
}
}
void SehException::addLineToCallstack(std::string &callstack, size_t counter, std::string &module, std::string &line, std::string &symbol) {
callstack += "[";
callstack += std::to_string(counter);
callstack += "]: ";
if (module.size()) {
callstack += "Module:";
callstack += module + "\n\t";
}
if (line.size()) {
callstack += line + ":";
}
callstack += symbol + "\n";
}
|