LiteLoaderBDS-1.16.40/Tools/CrashLogger/CrashLogger_Daemon/Logger.cpp
2022-09-21 19:47:03 +08:00

149 lines
4.5 KiB
C++

#include <windows.h>
#include <cstdio>
#include <string>
#include <filesystem>
#include <ctime>
#include <map>
#include "../include/LoggerShareData.h"
#include "SymbolHelper.h"
using namespace std;
HANDLE hProcess;
HANDLE hThread;
DWORD dProcessId;
DWORD dThreadId;
FILE* fLog;
HANDLE hDumpFile;
extern wstring bdsVersion;
#define log(format,...) \
printf(format, __VA_ARGS__); \
fflush(stdout); \
if (fLog != NULL) \
{ \
fprintf(fLog, format, __VA_ARGS__); \
fflush(fLog); \
}
string GetDateTime()
{
time_t t = time(NULL);
tm *ts = localtime(&t);
char buf[24] = { 0 };
strftime(buf, 24, "%Y%m%d_%H-%M-%S", ts);
return string(buf);
}
bool CreateLogFiles()
{
filesystem::create_directories(filesystem::path(DUMP_OUTPUT_PATH_PREFIX).remove_filename());
string dateTimeStr = GetDateTime();
string dumpPath = DUMP_OUTPUT_PATH_PREFIX + dateTimeStr + ".dmp";
hDumpFile = CreateFileA(dumpPath.c_str(), GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDumpFile == INVALID_HANDLE_VALUE || hDumpFile == NULL)
{
log("[CrashLogger][ERROR] Fail to open CoreDump file! Error Code: 0x%X\n", GetLastError());
}
string tracePath = STACKTRACE_OUTPUT_PATH_PREFIX + dateTimeStr + ".log";
fLog = fopen(tracePath.c_str(), "w");
if (fLog == NULL)
{
log("[CrashLogger][ERROR] Fail to open Log file! %s\n", strerror(errno));
}
return true;
}
void CoreDump(PEXCEPTION_POINTERS e)
{
if (hDumpFile != INVALID_HANDLE_VALUE)
{
MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
memset(&dumpInfo, 0, sizeof(MINIDUMP_EXCEPTION_INFORMATION));
dumpInfo.ExceptionPointers = e;
dumpInfo.ThreadId = dThreadId;
dumpInfo.ClientPointers = FALSE;
if (!MiniDumpWriteDump(hProcess, dProcessId, hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL))
{
log("[CrashLogger][ERROR] Fail to Generate Minidump! Error Code: 0x%X\n", GetLastError());
}
else
printf("-- Minidump generated in Directory ./logs/Crash\n");
}
}
void TraceBack(PEXCEPTION_POINTERS e)
{
STACKFRAME64 stackFrame = { 0 };
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrPC.Offset = e->ContextRecord->Rip;
stackFrame.AddrStack.Mode = AddrModeFlat;
stackFrame.AddrStack.Offset = e->ContextRecord->Rsp;
stackFrame.AddrFrame.Mode = AddrModeFlat;
stackFrame.AddrFrame.Offset = e->ContextRecord->Rbp;
PCONTEXT pContext = e->ContextRecord;
while (StackWalk64(MACHINE_TYPE, hProcess, hThread, &stackFrame, pContext, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
{
DWORD64 address = stackFrame.AddrPC.Offset;
//Function
PSYMBOL_INFO info;
HMODULE hModule = (HMODULE)SymGetModuleBase64(hProcess, (DWORD64)address);
std::wstring moduleName = MapModuleFromAddr(hProcess, (void*)address);
std::wstring moduleVersion = GetModuleVersionStr(hProcess, hModule);
if (moduleVersion.empty() && (moduleName == L"bedrock_server_mod.exe" || moduleName == L"bedrock_server.exe"))
moduleVersion = bdsVersion;
if (!moduleVersion.empty())
moduleName += L"<" + moduleVersion + L">";
if (info = GetSymbolInfo(hProcess, (void*)address))
{
log("[StackTrace] Function %ls at 0x%llX [%ls]\n", info->Name, info->Address, moduleName.c_str());
//Line
DWORD displacement = 0;
IMAGEHLP_LINE64 line{};
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
if (SymGetLineFromAddrW64(hProcess, address, &displacement, &line))
log("-- At File %ls : Line %d \n", line.FileName, line.LineNumber);
delete info;
}
else
log("[StackTrace] Function ???????? at 0x%llX [%ls]\n", address, moduleName.c_str());
}
}
void LogCrash(PEXCEPTION_POINTERS e, HANDLE hPro, HANDLE hThr, DWORD dProId, DWORD dThrId)
{
hProcess = hPro;
hThread = hThr;
dProcessId = dProId;
dThreadId = dThrId;
if (!CreateLogFiles() || !CreateModuleMap(hProcess))
return;
printf("\n");
log("[Crashed!]\n");
log("-- Unhandled Exception in -> %ls\n", MapModuleFromAddr(hProcess, e->ExceptionRecord->ExceptionAddress).c_str());
log("-- Exception Code: 0x%X\n", e->ExceptionRecord->ExceptionCode);
if(e->ExceptionRecord->ExceptionCode == CRT_EXCEPTION_CODE)
log("-- C++ STL Exception detected!\n")
CoreDump(e);
CloseHandle(hDumpFile);
log("\n");
TraceBack(e);
if (fLog != NULL && fLog != INVALID_HANDLE_VALUE)
fclose(fLog);
printf("\n");
}