windows 读取Dump 堆栈信息

https://github.com/junligong/WinCrashHandler.git

1、创建MiniDump

2、获取到dump信息

3、自定义完成(上报功能,需要自定义完成)

4、相关流程

       stepA:注册崩溃handlers

void main()
{
	WinCrashHandler ch;
	ch.SetProcessExceptionHandlers();
	ch.SetThreadExceptionHandlers();
	
    .............
}

       stepB:崩溃Handlers实现

#pragma once
#include "stdafx.h"

class WinCrashHandler  
{
public:

    // Constructor
    WinCrashHandler();

    // Destructor
    virtual ~WinCrashHandler();

    // Sets exception handlers that work on per-process basis
    void SetProcessExceptionHandlers();

    // Installs C++ exception handlers that function on per-thread basis
    void SetThreadExceptionHandlers();

	// Collects current process state.
    static void GetExceptionPointers(
        DWORD dwExceptionCode, 
        EXCEPTION_POINTERS** pExceptionPointers);

	// This method creates minidump of the process
	static void CreateMiniDump(EXCEPTION_POINTERS* pExcPtrs);

    /* Exception handler functions. */

    static LONG WINAPI SehHandler(PEXCEPTION_POINTERS pExceptionPtrs);
    static void __cdecl TerminateHandler();
    static void __cdecl UnexpectedHandler();

    static void __cdecl PureCallHandler();

    static void __cdecl InvalidParameterHandler(const wchar_t* expression, 
        const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved);

    static int __cdecl NewHandler(size_t);

    static void SigabrtHandler(int);
    static void SigfpeHandler(int /*code*/, int subcode);
    static void SigintHandler(int);
    static void SigillHandler(int);
    static void SigsegvHandler(int);
    static void SigtermHandler(int);


};


#include "stdafx.h"
#include "WinCrashHandler.h"
#include "StackTracer.h"

#ifndef _AddressOfReturnAddress

// Taken from: http://msdn.microsoft.com/en-us/library/s975zw7k(VS.71).aspx
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif

// _ReturnAddress and _AddressOfReturnAddress should be prototyped before use 
EXTERNC void * _AddressOfReturnAddress(void);
EXTERNC void * _ReturnAddress(void);

#endif 

WinCrashHandler::WinCrashHandler()
{	
}

WinCrashHandler::~WinCrashHandler()
{    
}

void WinCrashHandler::SetProcessExceptionHandlers()
{
	// Install top-level SEH handler
	SetUnhandledExceptionFilter(SehHandler);    

	// Catch pure virtual function calls.
	// Because there is one _purecall_handler for the whole process, 
	// calling this function immediately impacts all threads. The last 
	// caller on any thread sets the handler. 
	// http://msdn.microsoft.com/en-us/library/t296ys27.aspx
	_set_purecall_handler(PureCallHandler);    

	// Catch new operator memory allocation exceptions
	_set_new_handler(NewHandler);

	// Catch invalid parameter exceptions.
	_set_invalid_parameter_handler(InvalidParameterHandler); 

	// Set up C++ signal handlers

	_set_abort_behavior(_CALL_REPORTFAULT, _CALL_REPORTFAULT);

	// Catch an abnormal program termination
	signal(SIGABRT, SigabrtHandler);  

	// Catch illegal instruction handler
	signal(SIGINT, SigintHandler);     

	// Catch a termination request
	signal(SIGTERM, SigtermHandler);          

}

void WinCrashHandler::SetThreadExceptionHandlers()
{

	// Catch terminate() calls. 
	// In a multithreaded environment, terminate functions are maintained 
	// separately for each thread. Each new thread needs to install its own 
	// terminate function. Thus, each thread is in charge of its own termination handling.
	// http://msdn.microsoft.com/en-us/library/t6fk7h29.aspx
	set_terminate(TerminateHandler);       

	// Catch unexpected() calls.
	// In a multithreaded environment, unexpected functions are maintained 
	// separately for each thread. Each new thread needs to install its own 
	// unexpected function. Thus, each thread is in charge of its own unexpected handling.
	// http://msdn.microsoft.com/en-us/library/h46t5b69.aspx  
	set_unexpected(UnexpectedHandler);    

	// Catch a floating point error
	typedef void (*sigh)(int);
	signal(SIGFPE, (sigh)SigfpeHandler);     

	// Catch an illegal instruction
	signal(SIGILL, SigillHandler);     

	// Catch illegal storage access errors
	signal(SIGSEGV, SigsegvHandler);   

}

// The following code gets exception pointers using a workaround found in CRT code.
void WinCrashHandler::GetExceptionPointers(DWORD dwExceptionCode, 
										 EXCEPTION_POINTERS** ppExceptionPointers)
{
	// The following code was taken from VC++ 8.0 CRT (invarg.c: line 104)

	EXCEPTION_RECORD ExceptionRecord;
	CONTEXT ContextRecord;
	memset(&ContextRecord, 0, sizeof(CONTEXT));

#ifdef _X86_

	__asm {
		mov dword ptr [ContextRecord.Eax], eax
			mov dword ptr [ContextRecord.Ecx], ecx
			mov dword ptr [ContextRecord.Edx], edx
			mov dword ptr [ContextRecord.Ebx], ebx
			mov dword ptr [ContextRecord.Esi], esi
			mov dword ptr [ContextRecord.Edi], edi
			mov word ptr [ContextRecord.SegSs], ss
			mov word ptr [ContextRecord.SegCs], cs
			mov word ptr [ContextRecord.SegDs], ds
			mov word ptr [ContextRecord.SegEs], es
			mov word ptr [ContextRecord.SegFs], fs
			mov word ptr [ContextRecord.SegGs], gs
			pushfd
			pop [ContextRecord.EFlags]
	}

	ContextRecord.ContextFlags = CONTEXT_CONTROL;
#pragma warning(push)
#pragma warning(disable:4311)
	ContextRecord.Eip = (ULONG)_ReturnAddress();
	ContextRecord.Esp = (ULONG)_AddressOfReturnAddress();
#pragma warning(pop)
	ContextRecord.Ebp = *((ULONG *)_AddressOfReturnAddress()-1);


#elif defined (_IA64_) || defined (_AMD64_)

	/* Need to fill up the Context in IA64 and AMD64. */
	RtlCaptureContext(&ContextRecord);

#else  /* defined (_IA64_) || defined (_AMD64_) */

	ZeroMemory(&ContextRecord, sizeof(ContextRecord));

#endif  /* defined (_IA64_) || defined (_AMD64_) */

	ZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD));

	ExceptionRecord.ExceptionCode = dwExceptionCode;
	ExceptionRecord.ExceptionAddress = _ReturnAddress();

	///

	EXCEPTION_RECORD* pExceptionRecord = new EXCEPTION_RECORD;
	memcpy(pExceptionRecord, &ExceptionRecord, sizeof(EXCEPTION_RECORD));
	CONTEXT* pContextRecord = new CONTEXT;
	memcpy(pContextRecord, &ContextRecord, sizeof(CONTEXT));

	*ppExceptionPointers = new EXCEPTION_POINTERS;
	(*ppExceptionPointers)->ExceptionRecord = pExceptionRecord;
	(*ppExceptionPointers)->ContextRecord = pContextRecord;  
}

// This method creates minidump of the process
void WinCrashHandler::CreateMiniDump(EXCEPTION_POINTERS* pExcPtrs)
{   

	std::string str_msg = StackTracer::GetExceptionStackTrace(pExcPtrs);

    HMODULE hDbgHelp = NULL;
    HANDLE hFile = NULL;
    MINIDUMP_EXCEPTION_INFORMATION mei;
    MINIDUMP_CALLBACK_INFORMATION mci;
    
    // Load dbghelp.dll
    hDbgHelp = LoadLibrary(_T("dbghelp.dll"));
    if(hDbgHelp==NULL)
    {
        // Error - couldn't load dbghelp.dll
		return;
    }

    // Create the minidump file
    hFile = CreateFile(
        _T("crashdump.dmp"),
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if(hFile==INVALID_HANDLE_VALUE)
    {
        // Couldn't create file
		return;
    }
   
    // Write minidump to the file
    mei.ThreadId = GetCurrentThreadId();
    mei.ExceptionPointers = pExcPtrs;
    mei.ClientPointers = FALSE;
    mci.CallbackRoutine = NULL;
    mci.CallbackParam = NULL;

    typedef BOOL (WINAPI *LPMINIDUMPWRITEDUMP)(
        HANDLE hProcess, 
        DWORD ProcessId, 
        HANDLE hFile, 
        MINIDUMP_TYPE DumpType, 
        CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, 
        CONST PMINIDUMP_USER_STREAM_INFORMATION UserEncoderParam, 
        CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);

    LPMINIDUMPWRITEDUMP pfnMiniDumpWriteDump = 
        (LPMINIDUMPWRITEDUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
    if(!pfnMiniDumpWriteDump)
    {    
        // Bad MiniDumpWriteDump function
        return;
    }

    HANDLE hProcess = GetCurrentProcess();
	DWORD dwProcessId = GetCurrentProcessId();

    BOOL bWriteDump = pfnMiniDumpWriteDump(
        hProcess,
        dwProcessId,
        hFile,
        MiniDumpNormal,
        &mei,
        NULL,
        &mci);

    if(!bWriteDump)
    {    
        // Error writing dump.
        return;
    }

    // Close file
    CloseHandle(hFile);

    // Unload dbghelp.dll
    FreeLibrary(hDbgHelp);
}

// Structured exception handler
LONG WINAPI WinCrashHandler::SehHandler(PEXCEPTION_POINTERS pExceptionPtrs)
{ 
	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    
	
	// Unreacheable code  
	return EXCEPTION_EXECUTE_HANDLER;
}

// CRT terminate() call handler
void __cdecl WinCrashHandler::TerminateHandler()
{
	// Abnormal program termination (terminate() function was called)

	// Retrieve exception information
	EXCEPTION_POINTERS* pExceptionPtrs = NULL;
	GetExceptionPointers(0, &pExceptionPtrs);

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    
}

// CRT unexpected() call handler
void __cdecl WinCrashHandler::UnexpectedHandler()
{
	// Unexpected error (unexpected() function was called)

	// Retrieve exception information
	EXCEPTION_POINTERS* pExceptionPtrs = NULL;
	GetExceptionPointers(0, &pExceptionPtrs);

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    	    
}

// CRT Pure virtual method call handler
void __cdecl WinCrashHandler::PureCallHandler()
{
	// Pure virtual function call

	// Retrieve exception information
	EXCEPTION_POINTERS* pExceptionPtrs = NULL;
	GetExceptionPointers(0, &pExceptionPtrs);

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    
	 
}


// CRT invalid parameter handler
void __cdecl WinCrashHandler::InvalidParameterHandler(
	const wchar_t* expression, 
	const wchar_t* function, 
	const wchar_t* file, 
	unsigned int line, 
	uintptr_t pReserved)
{
	pReserved;

	// Invalid parameter exception

	// Retrieve exception information
	EXCEPTION_POINTERS* pExceptionPtrs = NULL;
	GetExceptionPointers(0, &pExceptionPtrs);

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    
	   
}

// CRT new operator fault handler
int __cdecl WinCrashHandler::NewHandler(size_t)
{
	// 'new' operator memory allocation exception

	// Retrieve exception information
	EXCEPTION_POINTERS* pExceptionPtrs = NULL;
	GetExceptionPointers(0, &pExceptionPtrs);

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);
	
	// Unreacheable code
	return 0;
}

// CRT SIGABRT signal handler
void WinCrashHandler::SigabrtHandler(int)
{
	// Caught SIGABRT C++ signal

	// Retrieve exception information
	EXCEPTION_POINTERS* pExceptionPtrs = NULL;
	GetExceptionPointers(0, &pExceptionPtrs);

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);   
	
}

// CRT SIGFPE signal handler
void WinCrashHandler::SigfpeHandler(int /*code*/, int subcode)
{
	// Floating point exception (SIGFPE)

	EXCEPTION_POINTERS* pExceptionPtrs = (PEXCEPTION_POINTERS)_pxcptinfoptrs;
	
	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    
	
}

// CRT sigill signal handler
void WinCrashHandler::SigillHandler(int)
{
	// Illegal instruction (SIGILL)

	// Retrieve exception information
	EXCEPTION_POINTERS* pExceptionPtrs = NULL;
	GetExceptionPointers(0, &pExceptionPtrs);

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    
	
}

// CRT sigint signal handler
void WinCrashHandler::SigintHandler(int)
{
	// Interruption (SIGINT)

	// Retrieve exception information
	EXCEPTION_POINTERS* pExceptionPtrs = NULL;
	GetExceptionPointers(0, &pExceptionPtrs);

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    
	
}

// CRT SIGSEGV signal handler
void WinCrashHandler::SigsegvHandler(int)
{
	// Invalid storage access (SIGSEGV)

	PEXCEPTION_POINTERS pExceptionPtrs = (PEXCEPTION_POINTERS)_pxcptinfoptrs;

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    
	
}

// CRT SIGTERM signal handler
void WinCrashHandler::SigtermHandler(int)
{
	// Termination request (SIGTERM)

	// Retrieve exception information
	EXCEPTION_POINTERS* pExceptionPtrs = NULL;
	GetExceptionPointers(0, &pExceptionPtrs);

	// Write minidump file
	CreateMiniDump(pExceptionPtrs);

	// Terminate process
	TerminateProcess(GetCurrentProcess(), 1);    
	
}


       stepC:注册信息转字符串

#pragma once

#include <map>
#include <vector>
#include <sstream>
#include <tchar.h>
#include "windows.h"

struct FunctionCall
{
    DWORD64 Address;
    std::string ModuleName;
    std::string FunctionName;
    std::string FileName;
    int			LineNumber;

public:
    FunctionCall() :
        Address(0),
        ModuleName(""),
        FunctionName(""),
        FileName(""),
        LineNumber(0)
    {
    }

public:
    static std::string GetFileName(const std::string& fullpath)
    {
        size_t index = fullpath.find_last_of('\\');
            if (index == std::string::npos)
            {
                return fullpath;
            }

        return fullpath.substr(index + 1);
    }
};

class StackTracer
{
public:
    static std::string GetExceptionStackTrace(LPEXCEPTION_POINTERS e);

private:
    // Always return EXCEPTION_EXECUTE_HANDLER after getting the call stack
    LONG ExceptionFilter(LPEXCEPTION_POINTERS e);

    // return the exception message along with call stacks
    std::string GetExceptionMsg();

    // Return exception code and call stack data structure so that 
    // user could customize their own message format
    DWORD GetExceptionCode();
    std::vector<FunctionCall> GetExceptionCallStack();

private:
    StackTracer(void);
    ~StackTracer(void);

    // The main function to handle exception
    LONG __stdcall HandleException(LPEXCEPTION_POINTERS e);

    // Work through the stack upwards to get the entire call stack
    void TraceCallStack(CONTEXT* pContext);

private:
    DWORD m_dwExceptionCode;

    std::vector<FunctionCall> m_vecCallStack;

    typedef std::map<DWORD, const char*> CodeDescMap;
    CodeDescMap m_mapCodeDesc;

    DWORD m_dwMachineType; // Machine type matters when trace the call stack (StackWalk64)

};
#include "stdafx.h"
#include "StackTracer.h"
#include <sstream>
#include <tchar.h>

#pragma warning(push)
#pragma warning(disable : 4091)
#include <DbgHelp.h>
#pragma warning(pop)

#pragma comment(lib, "Dbghelp.lib")

const int CALLSTACK_DEPTH = 24;

// Translate exception code to description
#define CODE_DESCR(code) CodeDescMap::value_type(code, #code)

StackTracer::StackTracer(void)
    :m_dwExceptionCode(0)
{
    // Get machine type
    m_dwMachineType = 0;
    size_t Count = 256;
    TCHAR wszProcessor[256] = { 0 };
    ::_tgetenv_s(&Count, wszProcessor, _T("PROCESSOR_ARCHITECTURE"));

    if (wszProcessor)
    {
        if ((!wcscmp(_T("EM64T"), wszProcessor)) || !wcscmp(_T("AMD64"), wszProcessor))
        {
            m_dwMachineType = IMAGE_FILE_MACHINE_AMD64;
        }
        else if (!wcscmp(_T("x86"), wszProcessor))
        {
            m_dwMachineType = IMAGE_FILE_MACHINE_I386;
        }
    }

    // Exception code description
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_ACCESS_VIOLATION));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_DATATYPE_MISALIGNMENT));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_BREAKPOINT));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_SINGLE_STEP));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_ARRAY_BOUNDS_EXCEEDED));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_FLT_DENORMAL_OPERAND));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_FLT_DIVIDE_BY_ZERO));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_FLT_INEXACT_RESULT));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_FLT_INVALID_OPERATION));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_FLT_OVERFLOW));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_FLT_STACK_CHECK));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_FLT_UNDERFLOW));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_INT_DIVIDE_BY_ZERO));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_INT_OVERFLOW));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_PRIV_INSTRUCTION));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_IN_PAGE_ERROR));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_ILLEGAL_INSTRUCTION));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_NONCONTINUABLE_EXCEPTION));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_STACK_OVERFLOW));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_INVALID_DISPOSITION));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_GUARD_PAGE));
    m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_INVALID_HANDLE));
    //m_mapCodeDesc.insert(CODE_DESCR(EXCEPTION_POSSIBLE_DEADLOCK));      
    // Any other exception code???
}

StackTracer::~StackTracer(void)
{
}

std::string StackTracer::GetExceptionStackTrace(LPEXCEPTION_POINTERS e)
{
    StackTracer tracer;
    tracer.HandleException(e);

    return tracer.GetExceptionMsg();
}

LONG StackTracer::ExceptionFilter(LPEXCEPTION_POINTERS e)
{
    return HandleException(e);
}

std::string StackTracer::GetExceptionMsg()
{
    std::ostringstream  m_ostringstream;

    // Exception Code
    CodeDescMap::iterator itc = m_mapCodeDesc.find(m_dwExceptionCode);

    char Code[72];
    sprintf_s(Code, "0x%x", m_dwExceptionCode);

    m_ostringstream << "Exception Code: " << Code << "\n";

    if (itc != m_mapCodeDesc.end())
    {
        m_ostringstream << "Exception: " << itc->second << "\n";
    }

        // Call Stack
    std::vector<FunctionCall>::iterator itbegin = m_vecCallStack.begin();
    std::vector<FunctionCall>::iterator itend = m_vecCallStack.end();
    std::vector<FunctionCall>::iterator it;
    for (it = itbegin; it < itend; it++)
    {
        std::string strModule = it->ModuleName.empty() ? "UnknownModule" : it->ModuleName;

        m_ostringstream << strModule << "\n";
        char Addrs[128];
        sprintf_s(Addrs, "0x%llx", it->Address);
        m_ostringstream << Addrs;

        if (!it->FunctionName.empty())
        {
            m_ostringstream << " " << it->FunctionName;
        }

        if (!it->FileName.empty())
        {
            m_ostringstream << " " << it->FileName << "[" << it->LineNumber << "]";
        }

        m_ostringstream << " ";
    }

    return m_ostringstream.str();
}

DWORD StackTracer::GetExceptionCode()
{
    return m_dwExceptionCode;
}

std::vector<FunctionCall> StackTracer::GetExceptionCallStack()
{
    return m_vecCallStack;
}

LONG __stdcall StackTracer::HandleException(LPEXCEPTION_POINTERS e)
{
    m_dwExceptionCode = e->ExceptionRecord->ExceptionCode;
    m_vecCallStack.clear();

    HANDLE hProcess = INVALID_HANDLE_VALUE;

    // Initializes the symbol handler
    if (!SymInitialize(GetCurrentProcess(), NULL, TRUE))
    {
        SymCleanup(hProcess);
        return EXCEPTION_EXECUTE_HANDLER;
    }

    // Work through the call stack upwards.
    TraceCallStack(e->ContextRecord);

    // ...
    SymCleanup(hProcess);

    return(EXCEPTION_EXECUTE_HANDLER);
}

// Work through the stack to get the entire call stack
void StackTracer::TraceCallStack(CONTEXT* pContext)
{
    // Initialize stack frame
    STACKFRAME64 sf;
    memset(&sf, 0, sizeof(STACKFRAME));

#if defined(_WIN64)
    sf.AddrPC.Offset = pContext->Rip;
    sf.AddrStack.Offset = pContext->Rsp;
    sf.AddrFrame.Offset = pContext->Rbp;
#elif defined(WIN32)
    sf.AddrPC.Offset = pContext->Eip;
    sf.AddrStack.Offset = pContext->Esp;
    sf.AddrFrame.Offset = pContext->Ebp;
#endif
    sf.AddrPC.Mode = AddrModeFlat;
    sf.AddrStack.Mode = AddrModeFlat;
    sf.AddrFrame.Mode = AddrModeFlat;

    if (0 == m_dwMachineType)
        return;

    // Walk through the stack frames.
    HANDLE hProcess = GetCurrentProcess();
    HANDLE hThread = GetCurrentThread();
    while (StackWalk64(m_dwMachineType, hProcess, hThread, &sf, pContext, 0, SymFunctionTableAccess64, SymGetModuleBase64, 0))
    {
        if (sf.AddrFrame.Offset == 0 || m_vecCallStack.size() >= CALLSTACK_DEPTH)
            break;

        // 1. Get function name at the address
        const int nBuffSize = (sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64);
        ULONG64 symbolBuffer[nBuffSize];
        PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;

        pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
        pSymbol->MaxNameLen = MAX_SYM_NAME;

        FunctionCall curCall;
        curCall.Address = sf.AddrPC.Offset;

        DWORD64 moduleBase = SymGetModuleBase64(hProcess, sf.AddrPC.Offset);
        char ModuleName[MAX_PATH];
        if (moduleBase && GetModuleFileNameA((HINSTANCE)moduleBase, ModuleName, MAX_PATH))
        {
            curCall.ModuleName = FunctionCall::GetFileName(ModuleName);
        }

        DWORD64 dwSymDisplacement = 0;
        if (SymFromAddr(hProcess, sf.AddrPC.Offset, &dwSymDisplacement, pSymbol))
        {
            curCall.FunctionName = std::string(pSymbol->Name);
        }

        //2. get line and file name at the address
        IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };
        DWORD dwLineDisplacement = 0;

        if (SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
        {
            curCall.FileName = FunctionCall::GetFileName(std::string(lineInfo.FileName));
            curCall.LineNumber = lineInfo.LineNumber;
        }

        // Call stack stored
        m_vecCallStack.push_back(curCall);
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要在 Windows 内核中获取应用程序的用户模式堆栈,可以使用以下方法: 1. 获取进程句柄 使用函数 PsGetCurrentProcess() 获取当前进程句柄。 2. 获取进程对象 使用函数 ObReferenceObjectByHandle() 获取进程对象。 3. 获取线程列表 使用函数 PsGetNextProcessThread() 获取进程对象的线程列表。 4. 获取线程堆栈 使用函数 KeStackAttachProcess() 将当前线程切换到目标进程的上下文中,然后使用函数 KeGetCurrentThreadStackLimit() 获取当前线程的堆栈限制地址,再使用函数 KeGetCurrentThreadStackBase() 获取当前线程的堆栈基地址。 5. 计算堆栈大小 通过堆栈基地址和堆栈限制地址计算出堆栈大小。 6. 获取堆栈内容 使用函数 RtlCopyMemory() 将堆栈内容复制到缓冲区中。 完整的代码示例: ```cpp PEPROCESS Process; HANDLE ProcessHandle; NTSTATUS Status; KAPC_STATE ApcState; PKTHREAD Thread; ULONG StackSize; ULONG_PTR StackBase; ULONG_PTR StackLimit; PCHAR StackBuffer; // 获取当前进程句柄 Process = PsGetCurrentProcess(); Status = ObOpenObjectByPointer(Process, OBJ_KERNEL_HANDLE, NULL, PROCESS_ALL_ACCESS, *PsProcessType, KernelMode, &ProcessHandle); if (!NT_SUCCESS(Status)) { return Status; } // 获取进程对象 if (ProcessHandle) { // 遍历线程列表 for (Thread = PsGetNextProcessThread(Process, NULL); Thread != NULL; Thread = PsGetNextProcessThread(Process, Thread)) { // 切换到目标进程上下文 KeStackAttachProcess(&Thread->tcb, Process); // 获取堆栈信息 StackLimit = (ULONG_PTR)KeGetCurrentThreadStackLimit(); StackBase = (ULONG_PTR)KeGetCurrentThreadStackBase(); StackSize = (ULONG)(StackBase - StackLimit); // 分配缓冲区 StackBuffer = (PCHAR)ExAllocatePoolWithTag(NonPagedPool, StackSize, 'stak'); if (StackBuffer) { // 复制堆栈内容 RtlCopyMemory(StackBuffer, (PVOID)StackLimit, StackSize); // 处理堆栈内容 // ... // 释放缓冲区 ExFreePoolWithTag(StackBuffer, 'stak'); } // 恢复当前线程上下文 KeUnstackDetachProcess(&ApcState); } // 关闭进程句柄 ZwClose(ProcessHandle); } return STATUS_SUCCESS; ``` ### 回答2: Windows 内核中有一种功能称为内存转储(Memory Dump),它可以存储系统在发生错误或崩溃时的内存状态。内存转储可以包含应用程序、操作系统和设备驱动程序的数据,可以为调试和故障排除提供重要信息。 在Windows操作系统中,应用层堆栈(Application Layer Stack)是指在系统崩溃时被保存的应用程序的运行状态信息。应用层堆栈包含了应用程序的调用栈(Call Stack),记录了程序执行过程中的函数调用关系。 当系统发生错误或崩溃时,Windows内核会生成一个内核转储文件,也称为内核转储(Kernel Dump)。这个内核转储文件包含了整个系统的内存状态,可以通过分析它来识别问题的根本原因。在这个内核转储文件中,应用层堆栈是其中的一部分。 应用层堆栈中的信息可以用来确定哪个应用程序最后导致系统崩溃或故障。分析应用层堆栈可以帮助开发人员或系统管理员快速定位问题,并进行相应的修复。例如,可以查看堆栈中的函数调用关系,检查是否有无线循环、内存泄露或访问越界等问题。 要获取Windows内核转储文件中的应用层堆栈信息,可以使用一些调试工具,例如WinDbg。这些工具可以加载内核转储文件,并提供一个交互式的调试环境,用于分析应用层堆栈和其他相关信息。 总之,通过分析Windows内核转储文件中的应用层堆栈,可以了解系统崩溃的原因,并采取相应的措施来修复问题。这是一项重要的技术,可以帮助保证Windows系统的稳定性和可靠性。 ### 回答3: 在Windows内核中,应用层堆栈是指一个线程在执行过程中所使用的函数调用栈。当应用程序崩溃或发生异常时,Windows内核会产生一个称为dump文件的二进制文件,用于记录当前的内存状态和调用堆栈信息Windows内核dump应用层堆栈的过程如下: 首先,当应用程序发生崩溃或异常时,操作系统会拦截这个事件,并捕获相关的异常信息。然后,操作系统会保存这些信息和应用层堆栈的调用信息到一个特定的内存区域中。 接下来,操作系统会创建一个dump文件,将之前保存的内存信息堆栈调用信息写入其中。这个dump文件通常是一个二进制文件,可以使用调试工具来进行分析和调试。 最后,开发人员或系统管理员可以使用不同的调试工具来分析dump文件,以找出导致应用程序崩溃或异常的原因。通过分析应用层堆栈的调用信息,可以确定问题发生的具体位置和可能的原因,从而进行修复或优化。 总之,Windows内核dump应用层堆栈是一种记录应用程序崩溃或异常信息的机制,它可以为开发人员或系统管理员提供快速的故障诊断和问题解决的手段。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值