mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Added ability to catch llvm errs(), shared crashcatcher object
This commit is contained in:
parent
76e29d385b
commit
f1eafa8d81
4 changed files with 274 additions and 113 deletions
|
@ -1,5 +1,4 @@
|
||||||
#include "CrashCatcher.h"
|
#include "CrashCatcher.h"
|
||||||
#include "../util/CritSect.h"
|
|
||||||
#include "../util/Dictionary.h"
|
#include "../util/Dictionary.h"
|
||||||
#include <commdlg.h>
|
#include <commdlg.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -51,15 +50,7 @@ static SYMFUNCTIONTABLEACCESSPROC gSymFunctionTableAccess = NULL;
|
||||||
static SYMGETMODULEBASEPROC gSymGetModuleBase = NULL;
|
static SYMGETMODULEBASEPROC gSymGetModuleBase = NULL;
|
||||||
static SYMGETSYMFROMADDRPROC gSymGetSymFromAddr = NULL;
|
static SYMGETSYMFROMADDRPROC gSymGetSymFromAddr = NULL;
|
||||||
static SYMGETLINEFROMADDR gSymGetLineFromAddr = NULL;
|
static SYMGETLINEFROMADDR gSymGetLineFromAddr = NULL;
|
||||||
static Array<CrashInfoFunc> gCrashInfoFuncs;
|
|
||||||
static StringT<0> gCrashInfo;
|
|
||||||
static bool gCrashed = false;
|
|
||||||
extern CritSect gBfpCritSect;
|
|
||||||
|
|
||||||
static EXCEPTION_POINTERS* gExceptionPointers = NULL;
|
|
||||||
static LPTOP_LEVEL_EXCEPTION_FILTER gPreviousFilter = NULL;
|
|
||||||
|
|
||||||
static bool gDebugError = false;
|
|
||||||
|
|
||||||
static bool CreateMiniDump(EXCEPTION_POINTERS* pep, const StringImpl& filePath);
|
static bool CreateMiniDump(EXCEPTION_POINTERS* pep, const StringImpl& filePath);
|
||||||
|
|
||||||
|
@ -162,7 +153,6 @@ struct
|
||||||
{ 0xFFFFFFFF, "" }
|
{ 0xFFFFFFFF, "" }
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool gUseDefaultFonts;
|
|
||||||
static HFONT gDialogFont;
|
static HFONT gDialogFont;
|
||||||
static HFONT gBoldFont;
|
static HFONT gBoldFont;
|
||||||
static String gErrorTitle;
|
static String gErrorTitle;
|
||||||
|
@ -171,7 +161,6 @@ static HWND gDebugButtonWindow = NULL;
|
||||||
static HWND gYesButtonWindow = NULL;
|
static HWND gYesButtonWindow = NULL;
|
||||||
static HWND gNoButtonWindow = NULL;
|
static HWND gNoButtonWindow = NULL;
|
||||||
static bool gExiting = false;
|
static bool gExiting = false;
|
||||||
static BfpCrashReportKind gCrashReportKind = BfpCrashReportKind_Default;
|
|
||||||
|
|
||||||
static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
@ -198,7 +187,7 @@ static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
||||||
|
|
||||||
if (::GetSaveFileNameW(&openFileName))
|
if (::GetSaveFileNameW(&openFileName))
|
||||||
{
|
{
|
||||||
CreateMiniDump(gExceptionPointers, UTF8Encode(fileName));
|
CreateMiniDump(CrashCatcher::Get()->mExceptionPointers, UTF8Encode(fileName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (hwndCtl == gNoButtonWindow)
|
else if (hwndCtl == gNoButtonWindow)
|
||||||
|
@ -207,7 +196,7 @@ static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
||||||
}
|
}
|
||||||
else if (hwndCtl == gDebugButtonWindow)
|
else if (hwndCtl == gDebugButtonWindow)
|
||||||
{
|
{
|
||||||
gDebugError = true;
|
CrashCatcher::Get()->mDebugError = true;
|
||||||
gExiting = true;
|
gExiting = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,6 +211,8 @@ static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
||||||
|
|
||||||
static void ShowErrorDialog(const StringImpl& errorTitle, const StringImpl& errorText)
|
static void ShowErrorDialog(const StringImpl& errorTitle, const StringImpl& errorText)
|
||||||
{
|
{
|
||||||
|
bool gUseDefaultFonts;
|
||||||
|
|
||||||
HINSTANCE gHInstance = ::GetModuleHandle(NULL);
|
HINSTANCE gHInstance = ::GetModuleHandle(NULL);
|
||||||
|
|
||||||
OSVERSIONINFO aVersionInfo;
|
OSVERSIONINFO aVersionInfo;
|
||||||
|
@ -247,7 +238,6 @@ static void ShowErrorDialog(const StringImpl& errorTitle, const StringImpl& erro
|
||||||
gErrorTitle = errorTitle;
|
gErrorTitle = errorTitle;
|
||||||
gErrorText = errorText;
|
gErrorText = errorText;
|
||||||
|
|
||||||
|
|
||||||
WNDCLASSW wc;
|
WNDCLASSW wc;
|
||||||
wc.style = 0;
|
wc.style = 0;
|
||||||
wc.cbClsExtra = 0;
|
wc.cbClsExtra = 0;
|
||||||
|
@ -810,18 +800,18 @@ static String GetVersion(const StringImpl& fileName)
|
||||||
|
|
||||||
static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
|
static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
|
||||||
{
|
{
|
||||||
if (gCrashed)
|
if (CrashCatcher::Get()->mCrashed)
|
||||||
return;
|
return;
|
||||||
gCrashed = true;
|
CrashCatcher::Get()->mCrashed = true;
|
||||||
|
|
||||||
HMODULE hMod = GetModuleHandleA(NULL);
|
HMODULE hMod = GetModuleHandleA(NULL);
|
||||||
|
|
||||||
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
|
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
|
||||||
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((uint8*)hMod + pDosHdr->e_lfanew);
|
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((uint8*)hMod + pDosHdr->e_lfanew);
|
||||||
bool isCLI = pNtHdr->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
bool isCLI = pNtHdr->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||||
if (gCrashReportKind == BfpCrashReportKind_GUI)
|
if (CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_GUI)
|
||||||
isCLI = false;
|
isCLI = false;
|
||||||
else if ((gCrashReportKind == BfpCrashReportKind_Console) || (gCrashReportKind == BfpCrashReportKind_PrintOnly))
|
else if ((CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_Console) || (CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_PrintOnly))
|
||||||
isCLI = true;
|
isCLI = true;
|
||||||
|
|
||||||
bool hasImageHelp = LoadImageHelp();
|
bool hasImageHelp = LoadImageHelp();
|
||||||
|
@ -859,10 +849,10 @@ static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto func : gCrashInfoFuncs)
|
for (auto func : CrashCatcher::Get()->mCrashInfoFuncs)
|
||||||
func();
|
func();
|
||||||
|
|
||||||
aDebugDump.Append(gCrashInfo);
|
aDebugDump.Append(CrashCatcher::Get()->mCrashInfo);
|
||||||
|
|
||||||
for (int i = 0; i < (int)aDebugDump.length(); i++)
|
for (int i = 0; i < (int)aDebugDump.length(); i++)
|
||||||
{
|
{
|
||||||
|
@ -994,26 +984,31 @@ static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
|
||||||
|
|
||||||
CrashCatcher::CrashCatcher()
|
CrashCatcher::CrashCatcher()
|
||||||
{
|
{
|
||||||
|
mCrashed = false;
|
||||||
|
mInitialized = false;
|
||||||
|
mExceptionPointers = NULL;
|
||||||
|
mPreviousFilter = NULL;
|
||||||
|
mDebugError = false;
|
||||||
|
mCrashReportKind = BfpCrashReportKind_Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long __stdcall SEHFilter(LPEXCEPTION_POINTERS lpExceptPtr)
|
static long __stdcall SEHFilter(LPEXCEPTION_POINTERS lpExceptPtr)
|
||||||
{
|
{
|
||||||
OutputDebugStrF("SEH Filter! CraskReportKind:%d\n", gCrashReportKind);
|
OutputDebugStrF("SEH Filter! CraskReportKind:%d\n", CrashCatcher::Get()->mCrashReportKind);
|
||||||
|
|
||||||
if (gCrashReportKind == BfpCrashReportKind_None)
|
if (CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_None)
|
||||||
{
|
{
|
||||||
OutputDebugStrF("Silent Exiting\n");
|
OutputDebugStrF("Silent Exiting\n");
|
||||||
::TerminateProcess(GetCurrentProcess(), lpExceptPtr->ExceptionRecord->ExceptionCode);
|
::TerminateProcess(GetCurrentProcess(), lpExceptPtr->ExceptionRecord->ExceptionCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoCrit autoCrit(gBfpCritSect);
|
AutoCrit autoCrit(CrashCatcher::Get()->mBfpCritSect);
|
||||||
//::ExitProcess();
|
//::ExitProcess();
|
||||||
//quick_exit(1);
|
//quick_exit(1);
|
||||||
|
|
||||||
if (!gCrashed)
|
if (!CrashCatcher::Get()->mCrashed)
|
||||||
{
|
{
|
||||||
gExceptionPointers = lpExceptPtr;
|
CrashCatcher::Get()->mExceptionPointers = lpExceptPtr;
|
||||||
//CreateMiniDump(lpExceptPtr);
|
//CreateMiniDump(lpExceptPtr);
|
||||||
DoHandleDebugEvent(lpExceptPtr);
|
DoHandleDebugEvent(lpExceptPtr);
|
||||||
}
|
}
|
||||||
|
@ -1021,7 +1016,7 @@ static long __stdcall SEHFilter(LPEXCEPTION_POINTERS lpExceptPtr)
|
||||||
//if (!gDebugError)
|
//if (!gDebugError)
|
||||||
//SetErrorMode(SEM_NOGPFAULTERRORBOX);
|
//SetErrorMode(SEM_NOGPFAULTERRORBOX);
|
||||||
|
|
||||||
if (gCrashReportKind == BfpCrashReportKind_PrintOnly)
|
if (CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_PrintOnly)
|
||||||
{
|
{
|
||||||
::TerminateProcess(GetCurrentProcess(), lpExceptPtr->ExceptionRecord->ExceptionCode);
|
::TerminateProcess(GetCurrentProcess(), lpExceptPtr->ExceptionRecord->ExceptionCode);
|
||||||
}
|
}
|
||||||
|
@ -1040,8 +1035,12 @@ static long __stdcall VectorExceptionHandler(LPEXCEPTION_POINTERS lpExceptPtr)
|
||||||
|
|
||||||
void CrashCatcher::Init()
|
void CrashCatcher::Init()
|
||||||
{
|
{
|
||||||
gPreviousFilter = SetUnhandledExceptionFilter(SEHFilter);
|
if (mInitialized)
|
||||||
OutputDebugStrF("Setting SEH filter %p\n", gPreviousFilter);
|
return;
|
||||||
|
|
||||||
|
mPreviousFilter = SetUnhandledExceptionFilter(SEHFilter);
|
||||||
|
OutputDebugStrF("Setting SEH filter %p\n", mPreviousFilter);
|
||||||
|
mInitialized = true;
|
||||||
|
|
||||||
// OutputDebugStrF("AddVectoredExceptionHandler 2\n");
|
// OutputDebugStrF("AddVectoredExceptionHandler 2\n");
|
||||||
// AddVectoredExceptionHandler(0, VectorExceptionHandler);
|
// AddVectoredExceptionHandler(0, VectorExceptionHandler);
|
||||||
|
@ -1065,30 +1064,33 @@ void CrashCatcher::Test()
|
||||||
|
|
||||||
void CrashCatcher::AddCrashInfoFunc(CrashInfoFunc crashInfoFunc)
|
void CrashCatcher::AddCrashInfoFunc(CrashInfoFunc crashInfoFunc)
|
||||||
{
|
{
|
||||||
AutoCrit autoCrit(gBfpCritSect);
|
AutoCrit autoCrit(mBfpCritSect);
|
||||||
gCrashInfoFuncs.Add(crashInfoFunc);
|
mCrashInfoFuncs.Add(crashInfoFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashCatcher::AddInfo(const StringImpl& str)
|
void CrashCatcher::AddInfo(const StringImpl& str)
|
||||||
{
|
{
|
||||||
AutoCrit autoCrit(gBfpCritSect);
|
AutoCrit autoCrit(mBfpCritSect);
|
||||||
gCrashInfo.Append(str);
|
mCrashInfo.Append(str);
|
||||||
|
if (!str.EndsWith('\n'))
|
||||||
|
mCrashInfo.Append('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashCatcher::Crash(const StringImpl& str)
|
void CrashCatcher::Crash(const StringImpl& str)
|
||||||
{
|
{
|
||||||
OutputDebugStrF("CrashCatcher::Crash\n");
|
OutputDebugStrF("CrashCatcher::Crash\n");
|
||||||
|
|
||||||
gBfpCritSect.Lock();
|
mBfpCritSect.Lock();
|
||||||
gCrashInfo.Append(str);
|
mCrashInfo.Append(str);
|
||||||
|
mCrashInfo.Append("\n");
|
||||||
|
|
||||||
if (gPreviousFilter == NULL)
|
if (mPreviousFilter == NULL)
|
||||||
{
|
{
|
||||||
// A little late, but install handler now so we can catch this crash
|
// A little late, but install handler now so we can catch this crash
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
gBfpCritSect.Unlock();
|
mBfpCritSect.Unlock();
|
||||||
|
|
||||||
|
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
|
@ -1110,5 +1112,68 @@ void CrashCatcher::Crash(const StringImpl& str)
|
||||||
|
|
||||||
void CrashCatcher::SetCrashReportKind(BfpCrashReportKind crashReportKind)
|
void CrashCatcher::SetCrashReportKind(BfpCrashReportKind crashReportKind)
|
||||||
{
|
{
|
||||||
gCrashReportKind = crashReportKind;
|
mCrashReportKind = crashReportKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CrashCatchMemory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CrashCatcher* mBpManager;
|
||||||
|
int mABIVersion;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CRASHCATCH_ABI_VERSION 1
|
||||||
|
|
||||||
|
static CrashCatcher* sCrashCatcher = NULL;
|
||||||
|
CrashCatcher* CrashCatcher::Get()
|
||||||
|
{
|
||||||
|
if (sCrashCatcher != NULL)
|
||||||
|
return sCrashCatcher;
|
||||||
|
|
||||||
|
char mutexName[128];
|
||||||
|
sprintf(mutexName, "BfCrashCatch_mutex_%d", GetCurrentProcessId());
|
||||||
|
char memName[128];
|
||||||
|
sprintf(memName, "BfCrashCatch_mem_%d", GetCurrentProcessId());
|
||||||
|
|
||||||
|
auto mutex = ::CreateMutexA(NULL, TRUE, mutexName);
|
||||||
|
if (mutex != NULL)
|
||||||
|
{
|
||||||
|
HANDLE fileMapping = ::OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, memName);
|
||||||
|
if (fileMapping != NULL)
|
||||||
|
{
|
||||||
|
CrashCatchMemory* sharedMem = (CrashCatchMemory*)MapViewOfFile(fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CrashCatchMemory));
|
||||||
|
if (sharedMem != NULL)
|
||||||
|
{
|
||||||
|
if (sharedMem->mABIVersion == CRASHCATCH_ABI_VERSION)
|
||||||
|
sCrashCatcher = sharedMem->mBpManager;
|
||||||
|
::UnmapViewOfFile(sharedMem);
|
||||||
|
}
|
||||||
|
::CloseHandle(fileMapping);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileMapping = ::CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(CrashCatchMemory), memName);
|
||||||
|
if (fileMapping != NULL)
|
||||||
|
{
|
||||||
|
CrashCatchMemory* sharedMem = (CrashCatchMemory*)MapViewOfFile(fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CrashCatchMemory));
|
||||||
|
if (sharedMem != NULL)
|
||||||
|
{
|
||||||
|
sCrashCatcher = new CrashCatcher();
|
||||||
|
sharedMem->mBpManager = sCrashCatcher;
|
||||||
|
sharedMem->mABIVersion = CRASHCATCH_ABI_VERSION;
|
||||||
|
::UnmapViewOfFile(sharedMem);
|
||||||
|
::ReleaseMutex(mutex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
::CloseHandle(fileMapping);
|
||||||
|
::CloseHandle(mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sCrashCatcher == NULL)
|
||||||
|
sCrashCatcher = new CrashCatcher();
|
||||||
|
return sCrashCatcher;
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../BeefySysLib/Common.h"
|
#include "../../BeefySysLib/Common.h"
|
||||||
|
#include "../util/CritSect.h"
|
||||||
|
|
||||||
NS_BF_BEGIN
|
NS_BF_BEGIN
|
||||||
|
|
||||||
|
@ -8,6 +9,17 @@ typedef void(*CrashInfoFunc)();
|
||||||
|
|
||||||
class CrashCatcher
|
class CrashCatcher
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
Array<CrashInfoFunc> mCrashInfoFuncs;
|
||||||
|
StringT<0> mCrashInfo;
|
||||||
|
bool mCrashed;
|
||||||
|
bool mInitialized;
|
||||||
|
CritSect mBfpCritSect;
|
||||||
|
EXCEPTION_POINTERS* mExceptionPointers;
|
||||||
|
LPTOP_LEVEL_EXCEPTION_FILTER mPreviousFilter;
|
||||||
|
bool mDebugError;
|
||||||
|
BfpCrashReportKind mCrashReportKind;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CrashCatcher();
|
CrashCatcher();
|
||||||
|
|
||||||
|
@ -18,6 +30,8 @@ public:
|
||||||
void Test();
|
void Test();
|
||||||
void Crash(const StringImpl& str);
|
void Crash(const StringImpl& str);
|
||||||
void SetCrashReportKind(BfpCrashReportKind crashReportKind);
|
void SetCrashReportKind(BfpCrashReportKind crashReportKind);
|
||||||
|
|
||||||
|
static CrashCatcher* Get();
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_BF_END
|
NS_BF_END
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
|
|
||||||
#include "util/AllocDebug.h"
|
#include "util/AllocDebug.h"
|
||||||
|
|
||||||
//kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
|
|
||||||
|
|
||||||
#pragma comment(lib, "ole32.lib")
|
#pragma comment(lib, "ole32.lib")
|
||||||
#pragma comment(lib, "shell32.lib")
|
#pragma comment(lib, "shell32.lib")
|
||||||
#pragma comment(lib, "user32.lib")
|
#pragma comment(lib, "user32.lib")
|
||||||
|
@ -47,10 +45,6 @@ struct WindowsSharedInfo
|
||||||
|
|
||||||
static WindowsSharedInfo* gGlobalPlatformInfo = NULL;
|
static WindowsSharedInfo* gGlobalPlatformInfo = NULL;
|
||||||
static HANDLE gGlobalMutex = 0;
|
static HANDLE gGlobalMutex = 0;
|
||||||
static CrashCatcher gCrashCatcher;
|
|
||||||
|
|
||||||
//#define HANDLE_TO_BFPFILE(val) ((BfpFile*)(val))
|
|
||||||
//#define BFPFILE_TO_HANDLE(val) ((HANDLE)(val))
|
|
||||||
|
|
||||||
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
|
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
|
||||||
typedef LONG KPRIORITY;
|
typedef LONG KPRIORITY;
|
||||||
|
@ -950,10 +944,9 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flag
|
||||||
// Then we install our abort handler.
|
// Then we install our abort handler.
|
||||||
signal(SIGABRT, &AbortHandler);
|
signal(SIGABRT, &AbortHandler);
|
||||||
|
|
||||||
gCrashCatcher.Init();
|
CrashCatcher::Get()->Init();
|
||||||
|
|
||||||
if ((flags & BfpSystemInitFlag_SilentCrash) != 0)
|
if ((flags & BfpSystemInitFlag_SilentCrash) != 0)
|
||||||
gCrashCatcher.SetCrashReportKind(BfpCrashReportKind_None);
|
CrashCatcher::Get()->SetCrashReportKind(BfpCrashReportKind_None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -964,17 +957,17 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCommandLine(int argc, char** argv)
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashReportKind(BfpCrashReportKind crashReportKind)
|
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashReportKind(BfpCrashReportKind crashReportKind)
|
||||||
{
|
{
|
||||||
gCrashCatcher.SetCrashReportKind(crashReportKind);
|
CrashCatcher::Get()->SetCrashReportKind(crashReportKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfoFunc(BfpCrashInfoFunc crashInfoFunc)
|
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfoFunc(BfpCrashInfoFunc crashInfoFunc)
|
||||||
{
|
{
|
||||||
gCrashCatcher.AddCrashInfoFunc(crashInfoFunc);
|
CrashCatcher::Get()->AddCrashInfoFunc(crashInfoFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfo(const char* str)
|
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfo(const char* str)
|
||||||
{
|
{
|
||||||
gCrashCatcher.AddInfo(str);
|
CrashCatcher::Get()->AddInfo(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown()
|
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown()
|
||||||
|
@ -1077,9 +1070,9 @@ BFP_EXPORT uint64 BFP_CALLTYPE BfpSystem_InterlockedCompareExchange64(uint64* pt
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_FatalError(const char* error, const char* title)
|
BFP_EXPORT void BFP_CALLTYPE BfpSystem_FatalError(const char* error, const char* title)
|
||||||
{
|
{
|
||||||
if (title != NULL)
|
if (title != NULL)
|
||||||
gCrashCatcher.Crash(String(title) + "\n" + String(error));
|
CrashCatcher::Get()->Crash(String(title) + "\n" + String(error));
|
||||||
else
|
else
|
||||||
gCrashCatcher.Crash(error);
|
CrashCatcher::Get()->Crash(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_GetCommandLine(char* outStr, int* inOutStrSize, BfpSystemResult* outResult)
|
BFP_EXPORT void BFP_CALLTYPE BfpSystem_GetCommandLine(char* outStr, int* inOutStrSize, BfpSystemResult* outResult)
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "BfModule.h"
|
#include "BfModule.h"
|
||||||
#include "BeefySysLib/util/BeefPerf.h"
|
#include "BeefySysLib/util/BeefPerf.h"
|
||||||
#include "BeefySysLib/util/Hash.h"
|
#include "BeefySysLib/util/Hash.h"
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable:4141)
|
#pragma warning(disable:4141)
|
||||||
|
@ -215,6 +217,147 @@ static llvm::Attribute::AttrKind LLVMMapAttribute(BfIRAttribute attr)
|
||||||
return llvm::Attribute::None;
|
return llvm::Attribute::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BF_PLATFORM_WINDOWS
|
||||||
|
struct BfTempFile
|
||||||
|
{
|
||||||
|
String mContents;
|
||||||
|
String mFilePath;
|
||||||
|
CritSect mCritSect;
|
||||||
|
FILE* mFP;
|
||||||
|
|
||||||
|
BfTempFile()
|
||||||
|
{
|
||||||
|
mFP = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
~BfTempFile()
|
||||||
|
{
|
||||||
|
if (mFP != NULL)
|
||||||
|
fclose(mFP);
|
||||||
|
if (!mFilePath.IsEmpty())
|
||||||
|
::DeleteFileW(UTF8Decode(mFilePath).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Create()
|
||||||
|
{
|
||||||
|
AutoCrit autoCrit(mCritSect);
|
||||||
|
if (mFP != NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WCHAR wPath[4096];
|
||||||
|
wPath[0] = 0;
|
||||||
|
::GetTempPathW(4096, wPath);
|
||||||
|
|
||||||
|
WCHAR wFilePath[4096];
|
||||||
|
wFilePath[0] = 0;
|
||||||
|
GetTempFileNameW(wPath, L"bftmp", 0, wFilePath);
|
||||||
|
|
||||||
|
mFilePath = UTF8Encode(wFilePath);
|
||||||
|
mFP = _wfopen(wFilePath, L"w+D");
|
||||||
|
return mFP != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
String GetContents()
|
||||||
|
{
|
||||||
|
AutoCrit autoCrit(mCritSect);
|
||||||
|
|
||||||
|
if (mFP != NULL)
|
||||||
|
{
|
||||||
|
fseek(mFP, 0, SEEK_END);
|
||||||
|
int size = (int)ftell(mFP);
|
||||||
|
fseek(mFP, 0, SEEK_SET);
|
||||||
|
|
||||||
|
char* str = new char[size];
|
||||||
|
int readSize = (int)fread(str, 1, size, mFP);
|
||||||
|
mContents.Append(str, readSize);
|
||||||
|
delete [] str;
|
||||||
|
fclose(mFP);
|
||||||
|
mFP = NULL;
|
||||||
|
|
||||||
|
::DeleteFileW(UTF8Decode(mFilePath).c_str());
|
||||||
|
}
|
||||||
|
return mContents;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static BfTempFile gTempFile;
|
||||||
|
|
||||||
|
static void AddStdErrCrashInfo()
|
||||||
|
{
|
||||||
|
String tempContents = gTempFile.GetContents();
|
||||||
|
if (!tempContents.IsEmpty())
|
||||||
|
BfpSystem_AddCrashInfo(tempContents.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
BfIRCodeGen::BfIRCodeGen()
|
||||||
|
{
|
||||||
|
mStream = NULL;
|
||||||
|
mBfIRBuilder = NULL;
|
||||||
|
|
||||||
|
mNopInlineAsm = NULL;
|
||||||
|
mAsmObjectCheckAsm = NULL;
|
||||||
|
mHasDebugLoc = false;
|
||||||
|
mAttrSet = NULL;
|
||||||
|
mIRBuilder = NULL;
|
||||||
|
mDIBuilder = NULL;
|
||||||
|
mDICompileUnit = NULL;
|
||||||
|
mActiveFunction = NULL;
|
||||||
|
|
||||||
|
mLLVMContext = new llvm::LLVMContext();
|
||||||
|
mLLVMModule = NULL;
|
||||||
|
mIsCodeView = false;
|
||||||
|
mCmdCount = 0;
|
||||||
|
|
||||||
|
#ifdef BF_PLATFORM_WINDOWS
|
||||||
|
if (::GetStdHandle(STD_ERROR_HANDLE) == 0)
|
||||||
|
{
|
||||||
|
if (gTempFile.Create())
|
||||||
|
{
|
||||||
|
_dup2(fileno(gTempFile.mFP), 2);
|
||||||
|
BfpSystem_AddCrashInfoFunc(AddStdErrCrashInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
BfIRCodeGen::~BfIRCodeGen()
|
||||||
|
{
|
||||||
|
mDebugLoc = llvm::DebugLoc();
|
||||||
|
mSavedDebugLocs.Clear();
|
||||||
|
|
||||||
|
delete mStream;
|
||||||
|
delete mIRBuilder;
|
||||||
|
delete mDIBuilder;
|
||||||
|
delete mLLVMModule;
|
||||||
|
delete mLLVMContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfIRCodeGen::Fail(const StringImpl& error)
|
||||||
|
{
|
||||||
|
if (mFailed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mHasDebugLoc)
|
||||||
|
{
|
||||||
|
auto dbgLoc = mIRBuilder->getCurrentDebugLocation();
|
||||||
|
if (dbgLoc)
|
||||||
|
{
|
||||||
|
llvm::DIFile* file = NULL;
|
||||||
|
if (llvm::DIScope* scope = llvm::dyn_cast<llvm::DIScope>(dbgLoc.getScope()))
|
||||||
|
{
|
||||||
|
BfIRCodeGenBase::Fail(StrFormat("%s at line %d:%d in %s/%s", error.c_str(), dbgLoc.getLine(), dbgLoc.getCol(), scope->getDirectory().data(), scope->getFilename().data()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BfIRCodeGenBase::Fail(error);
|
||||||
|
}
|
||||||
|
|
||||||
void BfIRCodeGen::PrintModule()
|
void BfIRCodeGen::PrintModule()
|
||||||
{
|
{
|
||||||
Beefy::debug_ostream os;
|
Beefy::debug_ostream os;
|
||||||
|
@ -362,60 +505,6 @@ void BfIRCodeGen::SetResult(int id, llvm::MDNode* md)
|
||||||
mResults.TryAdd(id, entry);
|
mResults.TryAdd(id, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
BfIRCodeGen::BfIRCodeGen()
|
|
||||||
{
|
|
||||||
mStream = NULL;
|
|
||||||
mBfIRBuilder = NULL;
|
|
||||||
|
|
||||||
mNopInlineAsm = NULL;
|
|
||||||
mAsmObjectCheckAsm = NULL;
|
|
||||||
mHasDebugLoc = false;
|
|
||||||
mAttrSet = NULL;
|
|
||||||
mIRBuilder = NULL;
|
|
||||||
mDIBuilder = NULL;
|
|
||||||
mDICompileUnit = NULL;
|
|
||||||
mActiveFunction = NULL;
|
|
||||||
|
|
||||||
mLLVMContext = new llvm::LLVMContext();
|
|
||||||
mLLVMModule = NULL;
|
|
||||||
mIsCodeView = false;
|
|
||||||
mCmdCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BfIRCodeGen::~BfIRCodeGen()
|
|
||||||
{
|
|
||||||
mDebugLoc = llvm::DebugLoc();
|
|
||||||
mSavedDebugLocs.Clear();
|
|
||||||
|
|
||||||
delete mStream;
|
|
||||||
delete mIRBuilder;
|
|
||||||
delete mDIBuilder;
|
|
||||||
delete mLLVMModule;
|
|
||||||
delete mLLVMContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BfIRCodeGen::Fail(const StringImpl& error)
|
|
||||||
{
|
|
||||||
if (mFailed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mHasDebugLoc)
|
|
||||||
{
|
|
||||||
auto dbgLoc = mIRBuilder->getCurrentDebugLocation();
|
|
||||||
if (dbgLoc)
|
|
||||||
{
|
|
||||||
llvm::DIFile* file = NULL;
|
|
||||||
if (llvm::DIScope* scope = llvm::dyn_cast<llvm::DIScope>(dbgLoc.getScope()))
|
|
||||||
{
|
|
||||||
BfIRCodeGenBase::Fail(StrFormat("%s at line %d:%d in %s/%s", error.c_str(), dbgLoc.getLine(), dbgLoc.getCol(), scope->getDirectory().data(), scope->getFilename().data()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BfIRCodeGenBase::Fail(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BfIRCodeGen::ProcessBfIRData(const BfSizedArray<uint8>& buffer)
|
void BfIRCodeGen::ProcessBfIRData(const BfSizedArray<uint8>& buffer)
|
||||||
{
|
{
|
||||||
struct InlineAsmErrorHook
|
struct InlineAsmErrorHook
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue