compute-runtime/shared/offline_compiler/source/utilities/windows/seh_exception.cpp

165 lines
4.8 KiB
C++

/*
* Copyright (C) 2018-2020 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 (code) {
case EXCEPTION_ACCESS_VIOLATION:
return "Access violation";
case EXCEPTION_DATATYPE_MISALIGNMENT:
return "Datatype misalignement";
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 (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();
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::load("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, ep->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";
}