如果x64dbg不去创建MiniDump文件夹会怎样?
还是代码说话吧#include <windows.h>
#pragma warning(push)
#pragma warning(disable:4091)
#include <dbghelp.h>
#pragma warning(pop)
#include <stdio.h>
#include <exception>
#include <signal.h>
#include "crashdump.h"
#define PROCESS_CALLBACK_FILTER_ENABLED 0x1
BOOL
(WINAPI*
MiniDumpWriteDumpPtr)(
_In_ HANDLE hProcess,
_In_ DWORD ProcessId,
_In_ HANDLE hFile,
_In_ MINIDUMP_TYPE DumpType,
_In_opt_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
_In_opt_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
_In_opt_ PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);
BOOL
(WINAPI*
SetProcessUserModeExceptionPolicyPtr)(
_In_ DWORD PolicyFlags
);
BOOL
(WINAPI*
GetProcessUserModeExceptionPolicyPtr)(
_Out_ LPDWORD PolicyFlags
);
void CrashDumpInitialize()
{
// Get handles to kernel32 and dbghelp
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
HMODULE hDbghelp = LoadLibraryA("dbghelp.dll");
if(hDbghelp)
*(FARPROC*)&MiniDumpWriteDumpPtr = GetProcAddress(hDbghelp, "MiniDumpWriteDump");
if(hKernel32)
{
*(FARPROC*)&SetProcessUserModeExceptionPolicyPtr = GetProcAddress(hKernel32, "SetProcessUserModeExceptionPolicy");
*(FARPROC*)&GetProcessUserModeExceptionPolicyPtr = GetProcAddress(hKernel32, "GetProcessUserModeExceptionPolicy");
}
if(MiniDumpWriteDumpPtr)
SetUnhandledExceptionFilter(CrashDumpExceptionHandler);
// Ensure that exceptions are not swallowed when dispatching certain Windows
// messages.
//
// http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/
// https://support.microsoft.com/en-gb/kb/976038
if(SetProcessUserModeExceptionPolicyPtr && GetProcessUserModeExceptionPolicyPtr)
{
DWORD flags = 0;
if(GetProcessUserModeExceptionPolicyPtr(&flags))
SetProcessUserModeExceptionPolicyPtr(flags & ~PROCESS_CALLBACK_FILTER_ENABLED);
}
// If not running under a debugger, redirect purecall, terminate, abort, and
// invalid parameter callbacks to force generate a dump.
if(!IsDebuggerPresent())
{
_set_purecall_handler(TerminateHandler); // https://msdn.microsoft.com/en-us/library/t296ys27.aspx
_set_invalid_parameter_handler(InvalidParameterHandler);// https://msdn.microsoft.com/en-us/library/a9yf33zb.aspx
set_terminate(TerminateHandler); // http://en.cppreference.com/w/cpp/error/set_terminate
signal(SIGABRT, AbortHandler); // https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx
}
}
void CrashDumpFatal(const char* Format, ...)
{
char buffer;
va_list va;
va_start(va, Format);
vsnprintf_s(buffer, _TRUNCATE, Format, va);
va_end(va);
MessageBoxA(nullptr, buffer, "Error", MB_ICONERROR);
}
void CrashDumpCreate(EXCEPTION_POINTERS* ExceptionPointers)
{
// Generate a crash dump file in the minidump directory
wchar_t dumpFile;
wchar_t dumpDir;
if(!GetCurrentDirectoryW(ARRAYSIZE(dumpDir), dumpDir))
{
CrashDumpFatal("Unable to obtain current directory during crash dump");
return;
}
wcscat_s(dumpDir, L"\\minidump");
CreateDirectoryW(dumpDir, nullptr);
// Append the name with generated timestamp
SYSTEMTIME st;
GetLocalTime(&st);
swprintf_s(dumpFile, L"%ws\\dump-%02d%02d%04d_%02d%02d%02d%04d.dmp", dumpDir,
st.wDay,
st.wMonth,
st.wYear,
st.wHour,
st.wMinute,
st.wSecond,
st.wMilliseconds);
// Open the file
HANDLE fileHandle = CreateFileW(dumpFile, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if(fileHandle == INVALID_HANDLE_VALUE)
{
CrashDumpFatal("Failed to open file path '%ws' while generating crash dump", dumpFile);
return;
}
// Create the minidump with DbgHelp
MINIDUMP_EXCEPTION_INFORMATION info;
memset(&info, 0, sizeof(MINIDUMP_EXCEPTION_INFORMATION));
info.ThreadId = GetCurrentThreadId();
info.ExceptionPointers = ExceptionPointers;
info.ClientPointers = TRUE;
if(!MiniDumpWriteDumpPtr(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, MiniDumpNormal, &info, nullptr, nullptr))
CrashDumpFatal("MiniDumpWriteDump failed. Error: %u", GetLastError());
// Close the file & done
CloseHandle(fileHandle);
}
LONG CALLBACK CrashDumpExceptionHandler(EXCEPTION_POINTERS* ExceptionInfo)
{
// Any "exception" under 0x1000 is usually a failed remote procedure call (RPC)
if(ExceptionInfo && ExceptionInfo->ExceptionRecord->ExceptionCode > 0x1000)
{
switch(ExceptionInfo->ExceptionRecord->ExceptionCode)
{
case DBG_PRINTEXCEPTION_C:// OutputDebugStringA
case 0x4001000A: // OutputDebugStringW
case STATUS_INVALID_HANDLE: // Invalid TitanEngine handle
case 0x406D1388: // SetThreadName
return EXCEPTION_CONTINUE_SEARCH;
}
CrashDumpCreate(ExceptionInfo);
}
return EXCEPTION_CONTINUE_SEARCH;
}
void InvalidParameterHandler(const wchar_t* Expression, const wchar_t* Function, const wchar_t* File, unsigned int Line, uintptr_t Reserved)
{
CrashDumpFatal("Invalid parameter passed to CRT function! Program will now generate an exception.\n\nFile: %ws\nFunction: %ws\nExpression: %ws",
Function ? Function : L"???",
File ? File : L"???",
Expression ? Expression : L"???");
// RaiseException: avoid the use of throw/C++ exceptions and possible __fastfail calls
RaiseException(0x78646267, EXCEPTION_NONCONTINUABLE, 0, nullptr);
}
void TerminateHandler()
{
CrashDumpFatal("Process termination was requested in an unusual way. Program will now generate an exception.");
// See InvalidParameterHandler()
RaiseException(0x78646267, EXCEPTION_NONCONTINUABLE, 0, nullptr);
}
void AbortHandler(int Signal)
{
TerminateHandler();
}
再来看下一段
/**
\file _global.cpp
\brief Implements the global class.
*/
#include "_global.h"
#include <objbase.h>
#include <shlobj.h>
#include <psapi.h>
#include "DeviceNameResolver/DeviceNameResolver.h"
/**
\brief x64dbg library instance.
*/
HINSTANCE hInst;
/**
\brief Number of allocated buffers by emalloc(). This should be 0 when x64dbg ends.
*/
static int emalloc_count = 0;
#ifdef ENABLE_MEM_TRACE
/**
\brief Path for debugging, used to create an allocation trace file on emalloc() or efree(). Not used.
*/
static char alloctrace = "";
static std::unordered_map<void*, int> alloctracemap;
static CRITICAL_SECTION criticalSection;
#endif
/**
\brief Allocates a new buffer.
\param size The size of the buffer to allocate (in bytes).
\param reason The reason for allocation (can be used for memory allocation tracking).
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
*/
void* emalloc(size_t size, const char* reason)
{
ASSERT_NONZERO(size);
#ifdef ENABLE_MEM_TRACE
unsigned char* a = (unsigned char*)GlobalAlloc(GMEM_FIXED, size + sizeof(void*));
#else
unsigned char* a = (unsigned char*)GlobalAlloc(GMEM_FIXED, size);
#endif //ENABLE_MEM_TRACE
if(!a)
{
wchar_t sizeString;
swprintf_s(sizeString, L"%p bytes", size);
MessageBoxW(0, L"Could not allocate memory (minidump will be created)", sizeString, MB_ICONERROR);
//__debugbreak();
//ExitProcess(1);
}
emalloc_count++;
#ifdef ENABLE_MEM_TRACE
EnterCriticalSection(&criticalSection);
memset(a, 0, size + sizeof(void*));
FILE* file = fopen(alloctrace, "a+");
fprintf(file, "DBG%.5d:alloc:%p:%p:%s:%p\n", emalloc_count, a, _ReturnAddress(), reason, size);
fclose(file);
alloctracemap++;
*(void**)a = _ReturnAddress();
LeaveCriticalSection(&criticalSection);
return a + sizeof(void*);
#else
memset(a, 0, size);
return a;
#endif //ENABLE_MEM_TRACE
}
/**
\brief Reallocates a buffer allocated with emalloc().
\param Pointer to memory previously allocated with emalloc(). When NULL a new buffer will be allocated by emalloc().
\param size The new memory size.
\param reason The reason for allocation (can be used for memory allocation tracking).
\return Always returns a valid pointer to the buffer you requested. Will quit the application on errors.
*/
void* erealloc(void* ptr, size_t size, const char* reason)
{
ASSERT_NONZERO(size);
// Free the memory if the pointer was set (as per documentation).
if(ptr)
efree(ptr, reason);
return emalloc(size, reason);
}
/**
\brief Free memory previously allocated with emalloc().
\param Pointer to the memory to free.
\param reason The reason for freeing, should be the same as the reason for allocating.
*/
void efree(void* ptr, const char* reason)
{
emalloc_count--;
#ifdef ENABLE_MEM_TRACE
EnterCriticalSection(&criticalSection);
char* ptr2 = (char*)ptr - sizeof(void*);
FILE* file = fopen(alloctrace, "a+");
fprintf(file, "DBG%.5d: free:%p:%p:%s\n", emalloc_count, ptr, *(void**)ptr2, reason);
fclose(file);
if(alloctracemap.find(*(void**)ptr2) != alloctracemap.end())
{
if(--alloctracemap.at(*(void**)ptr2) < 0)
{
String str = StringUtils::sprintf("address %p, reason %s", *(void**)ptr2, reason);
MessageBoxA(0, str.c_str(), "Freed memory more than once", MB_OK);
__debugbreak();
}
}
else
{
String str = StringUtils::sprintf("address %p, reason %s", *(void**)ptr2, reason);
MessageBoxA(0, str.c_str(), "Trying to free const memory", MB_OK);
__debugbreak();
}
LeaveCriticalSection(&criticalSection);
GlobalFree(ptr2);
#else
GlobalFree(ptr);
#endif //ENABLE_MEM_TRACE
}
void* json_malloc(size_t size)
{
#ifdef ENABLE_MEM_TRACE
return emalloc(size, "json:ptr");
#else
return emalloc(size);
#endif
}
void json_free(void* ptr)
{
#ifdef ENABLE_MEM_TRACE
return efree(ptr, "json:ptr");
#else
return efree(ptr);
#endif
}
/**
\brief Gets the number of memory leaks. This number is only valid in _dbg_dbgexitsignal().
\return The number of memory leaks.
*/
int memleaks()
{
#ifdef ENABLE_MEM_TRACE
EnterCriticalSection(&criticalSection);
auto leaked = false;
for(auto & i : alloctracemap)
{
if(i.second != 0)
{
String str = StringUtils::sprintf("memory leak at %p : count %d", i.first, i.second);
MessageBoxA(0, str.c_str(), "memory leak", MB_OK);
leaked = true;
}
}
if(leaked)
__debugbreak();
LeaveCriticalSection(&criticalSection);
#endif
return emalloc_count;
}
#ifdef ENABLE_MEM_TRACE
/**
\brief Sets the path for the allocation trace file.
\param file UTF-8 filepath.
*/
void setalloctrace(const char* file)
{
InitializeCriticalSection(&criticalSection);
strcpy_s(alloctrace, file);
}
#endif //ENABLE_MEM_TRACE
/**
\brief Compares two strings without case-sensitivity.
\param a The first string.
\param b The second string.
\return true if the strings are equal (case-insensitive).
*/
bool scmp(const char* a, const char* b)
{
if(!a || !b)
return false;
return !_stricmp(a, b);
}
/**
\brief Queries if a given file exists.
\param file Path to the file to check (UTF-8).
\return true if the file exists on the hard drive.
*/
bool FileExists(const char* file)
{
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(file).c_str());
return (attrib != INVALID_FILE_ATTRIBUTES && !(attrib & FILE_ATTRIBUTE_DIRECTORY));
}
/**
\brief Queries if a given directory exists.
\param dir Path to the directory to check (UTF-8).
\return true if the directory exists.
*/
bool DirExists(const char* dir)
{
DWORD attrib = GetFileAttributesW(StringUtils::Utf8ToUtf16(dir).c_str());
return (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0);
}
/**
\brief Gets file path from a file handle.
\param hFile File handle to get the path from.
\param szFileName Buffer of size MAX_PATH.
\return true if it succeeds, false if it fails.
*/
bool GetFileNameFromHandle(HANDLE hFile, char* szFileName)
{
if(!hFile)
return false;
wchar_t wszFileName = L"";
if(!PathFromFileHandleW(hFile, wszFileName, _countof(wszFileName)))
return false;
strncpy_s(szFileName, MAX_PATH, StringUtils::Utf16ToUtf8(wszFileName).c_str(), _TRUNCATE);
return true;
}
bool GetFileNameFromProcessHandle(HANDLE hProcess, char* szFileName)
{
wchar_t wszDosFileName = L"";
wchar_t wszFileName = L"";
auto result = false;
if(GetProcessImageFileNameW(hProcess, wszDosFileName, _countof(wszDosFileName)))
{
if(!DevicePathToPathW(wszDosFileName, wszFileName, _countof(wszFileName)))
result = !!GetModuleFileNameExW(hProcess, 0, wszFileName, _countof(wszFileName));
else
result = true;
}
else
result = !!GetModuleFileNameExW(hProcess, 0, wszFileName, _countof(wszFileName));
if(result)
strncpy_s(szFileName, MAX_PATH, StringUtils::Utf16ToUtf8(wszFileName).c_str(), _TRUNCATE);
return result;
}
bool GetFileNameFromModuleHandle(HANDLE hProcess, HMODULE hModule, char* szFileName)
{
wchar_t wszDosFileName = L"";
wchar_t wszFileName = L"";
auto result = false;
if(GetMappedFileNameW(hProcess, hModule, wszDosFileName, _countof(wszDosFileName)))
{
if(!DevicePathToPathW(wszDosFileName, wszFileName, _countof(wszFileName)))
result = !!GetModuleFileNameExW(hProcess, hModule, wszFileName, _countof(wszFileName));
else
result = true;
}
else
result = !!GetModuleFileNameExW(hProcess, hModule, wszFileName, _countof(wszFileName));
if(result)
strncpy_s(szFileName, MAX_PATH, StringUtils::Utf16ToUtf8(wszFileName).c_str(), _TRUNCATE);
return result;
}
/**
\brief Get a boolean setting from the configuration file.
\param section The section of the setting (UTF-8).
\param name The name of the setting (UTF-8).
\return true if the setting was set and equals to true, otherwise returns false.
*/
bool settingboolget(const char* section, const char* name)
{
duint setting;
if(!BridgeSettingGetUint(section, name, &setting))
return false;
if(setting)
return true;
return false;
}
/**
\brief Query if x64dbg is running in Wow64 mode.
\return true if running in Wow64, false otherwise.
*/
bool IsWow64()
{
BOOL bIsWow64Process = FALSE;
//x64dbg supports WinXP SP3 and later only, so ignore the GetProcAddress crap :D
IsWow64Process(GetCurrentProcess(), &bIsWow64Process);
return !!bIsWow64Process;
}
//Taken from: http://www.cplusplus.com/forum/windows/64088/
//And: https://codereview.stackexchange.com/a/2917
bool ResolveShortcut(HWND hwnd, const wchar_t* szShortcutPath, wchar_t* szResolvedPath, size_t nSize)
{
if(szResolvedPath == NULL)
return SUCCEEDED(E_INVALIDARG);
//Initialize COM stuff
if(!SUCCEEDED(CoInitialize(NULL)))
return false;
//Get a pointer to the IShellLink interface.
IShellLinkW* psl = NULL;
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl);
if(SUCCEEDED(hres))
{
//Get a pointer to the IPersistFile interface.
IPersistFile* ppf = NULL;
hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if(SUCCEEDED(hres))
{
//Load the shortcut.
hres = ppf->Load(szShortcutPath, STGM_READ);
if(SUCCEEDED(hres))
{
//Resolve the link.
hres = psl->Resolve(hwnd, 0);
if(SUCCEEDED(hres))
{
//Get the path to the link target.
wchar_t linkTarget;
hres = psl->GetPath(linkTarget, _countof(linkTarget), NULL, SLGP_RAWPATH);
//Expand the environment variables.
wchar_t expandedTarget;
auto expandSuccess = !!ExpandEnvironmentStringsW(linkTarget, expandedTarget, _countof(expandedTarget));
if(SUCCEEDED(hres) && expandSuccess)
{
wcscpy_s(szResolvedPath, nSize, expandedTarget);
}
}
}
//Release the pointer to the IPersistFile interface.
ppf->Release();
}
//Release the pointer to the IShellLink interface.
psl->Release();
}
//Uninitialize COM stuff
CoUninitialize();
return SUCCEEDED(hres);
}
void WaitForThreadTermination(HANDLE hThread, DWORD timeout)
{
WaitForSingleObject(hThread, timeout);
CloseHandle(hThread);
}
void WaitForMultipleThreadsTermination(const HANDLE* hThread, int count, DWORD timeout)
{
WaitForMultipleObjects(count, hThread, TRUE, timeout);
for(int i = 0; i < count; i++)
CloseHandle(hThread);
}
或换句话说MiniDump 和 memdumps 这样的文件夹起到何作用?
也许是我不会看 用windbg也不能理解 MiniDump 崩溃在何问题上? 我记得其中有一个是存储调试工程的来着,保存之后文件夹中就会出现内容 Link_Stark 发表于 2023-4-22 10:26
我记得其中有一个是存储调试工程的来着,保存之后文件夹中就会出现内容
你说的是跟踪窗口保存的那个吧?
我说的是崩溃后产生的
年-月-日.dump文件 冥界3大法王 发表于 2023-4-22 10:40
你说的是跟踪窗口保存的那个吧?
我说的是崩溃后产生的
年-月-日.dump文件
用windbg 配合 pdb 文件定位异常原因 yp17792351859 发表于 2023-4-23 13:32
用windbg 配合 pdb 文件定位异常原因
定位了,日了一个文件,就编译通过了。
看来这dump文件删除的想法也不对。
页:
[1]