diff --git a/CrashLogger.sln b/CrashLogger.sln new file mode 100644 index 0000000..377f814 --- /dev/null +++ b/CrashLogger.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30907.101 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CrashLogger", "CrashLogger.vcxproj", "{B9492785-E9A2-42BA-A6C0-5AFE14FA3614}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B9492785-E9A2-42BA-A6C0-5AFE14FA3614}.Debug|x64.ActiveCfg = Debug|x64 + {B9492785-E9A2-42BA-A6C0-5AFE14FA3614}.Debug|x64.Build.0 = Debug|x64 + {B9492785-E9A2-42BA-A6C0-5AFE14FA3614}.Debug|x86.ActiveCfg = Debug|Win32 + {B9492785-E9A2-42BA-A6C0-5AFE14FA3614}.Debug|x86.Build.0 = Debug|Win32 + {B9492785-E9A2-42BA-A6C0-5AFE14FA3614}.Release|x64.ActiveCfg = Release|x64 + {B9492785-E9A2-42BA-A6C0-5AFE14FA3614}.Release|x64.Build.0 = Release|x64 + {B9492785-E9A2-42BA-A6C0-5AFE14FA3614}.Release|x86.ActiveCfg = Release|Win32 + {B9492785-E9A2-42BA-A6C0-5AFE14FA3614}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {29B42EF8-B025-4731-B09B-70A1AB99F47C} + EndGlobalSection +EndGlobal diff --git a/CrashLogger.vcxproj b/CrashLogger.vcxproj new file mode 100644 index 0000000..4cbba39 --- /dev/null +++ b/CrashLogger.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {b9492785-e9a2-42ba-a6c0-5afe14fa3614} + CrashLogger + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;CRASHLOGGER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;CRASHLOGGER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + %(AdditionalDependencies) + + + + + Level3 + true + _DEBUG;CRASHLOGGER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + NDEBUG;CRASHLOGGER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/CrashLogger.vcxproj.filters b/CrashLogger.vcxproj.filters new file mode 100644 index 0000000..faea664 --- /dev/null +++ b/CrashLogger.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + 头文件 + + + + + 源文件 + + + 源文件 + + + + + + \ No newline at end of file diff --git a/CrashLogger.vcxproj.user b/CrashLogger.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/CrashLogger.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dllmain.cpp b/dllmain.cpp new file mode 100644 index 0000000..7b2db44 --- /dev/null +++ b/dllmain.cpp @@ -0,0 +1,109 @@ +#include "pch.h" +#include +#include +#include +#include +#include + +#define MAX_STACK_FRAMES 50 +#define LOG_OUTPUT_PATH ".\\logs\\TrackBack.log" +#define DUMP_OUTPUT_PATH L".\\logs\\CrashDump.dmp" + +PTOP_LEVEL_EXCEPTION_FILTER SystemHandler; +FILE* fLog; + +void log(const char* format, ...) +{ + va_list args; + va_start(args, format); + vprintf(format, args); + fflush(stdout); + if (fLog != NULL) + { + vfprintf(fLog, format, args); + fflush(fLog); + } + va_end(args); +} + +LONG WINAPI CrashLogger(PEXCEPTION_POINTERS pe) +{ + log("[Crashed!]\n"); + HANDLE hProcess = GetCurrentProcess(); + HANDLE hThread = GetCurrentThread(); + + /// + /// StackWalk + /// + /// + /// + SymInitialize(hProcess, NULL, TRUE); + void* pStack[MAX_STACK_FRAMES]; + WORD frames = CaptureStackBackTrace(0, MAX_STACK_FRAMES, pStack, NULL); + + for (WORD i = 0; i < frames; ++i) { + DWORD64 address = (DWORD64)(pStack[i]); + + DWORD64 displacementSym = 0; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); + pSymbol->MaxNameLen = MAX_SYM_NAME; + + DWORD displacementLine = 0; + IMAGEHLP_LINE64 line; + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + //Function + if (SymFromAddr(hProcess, address, &displacementSym, pSymbol)) + if(strcmp(pSymbol->Name,"UnhandledExceptionFilter") != 0) + log("[TrackBack] Function %s at (0x%llX)\n", pSymbol->Name, pSymbol->Address); + //Line + if (SymGetLineFromAddr64(hProcess, address, &displacementLine, &line)) + log("[TrackBack] At File %s : Line %d \n", line.FileName, line.LineNumber); + } + SymCleanup(hProcess); + + /// + /// CrashDump + /// + /// + /// + HANDLE hDumpFile = CreateFile(DUMP_OUTPUT_PATH, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hDumpFile != INVALID_HANDLE_VALUE) + { + MINIDUMP_EXCEPTION_INFORMATION dumpInfo; + dumpInfo.ExceptionPointers = pe; + dumpInfo.ThreadId = GetCurrentThreadId(); + dumpInfo.ClientPointers = TRUE; + MiniDumpWriteDump(hProcess, GetCurrentProcessId(), hDumpFile, MiniDumpNormal, + &dumpInfo, NULL, NULL); + } + + return SystemHandler(pe); +} + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + SystemHandler = SetUnhandledExceptionFilter(CrashLogger); + fopen_s(&fLog, LOG_OUTPUT_PATH, "w"); + printf("[CrashLogger] CrashLogger loaded.\n"); + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + fclose(fLog); + break; + } + return TRUE; +} + diff --git a/framework.h b/framework.h new file mode 100644 index 0000000..80cbbc9 --- /dev/null +++ b/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 +// Windows 头文件 +#include diff --git a/pch.cpp b/pch.cpp new file mode 100644 index 0000000..b6fb8f4 --- /dev/null +++ b/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: 与预编译标头对应的源文件 + +#include "pch.h" + +// 当使用预编译的头时,需要使用此源文件,编译才能成功。 diff --git a/pch.h b/pch.h new file mode 100644 index 0000000..9660927 --- /dev/null +++ b/pch.h @@ -0,0 +1,13 @@ +// pch.h: 这是预编译标头文件。 +// 下方列出的文件仅编译一次,提高了将来生成的生成性能。 +// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 +// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 +// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + +#ifndef PCH_H +#define PCH_H + +// 添加要在此处预编译的标头 +#include "framework.h" + +#endif //PCH_H