StackWalk64

Posted hjbf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了StackWalk64相关的知识,希望对你有一定的参考价值。

#include <Windows.h>  

#define  PULONG_PTR ULONG**
#define  PULONG ULONG*
#define  ULONG_PTR ULONG*
 
#include <DbgHelp.h>  
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>

// 添加对dbghelp.lib的编译依赖  
//  
#pragma comment(lib, "dbghelp.lib") 
  
   
const int MAX_ADDRESS_LENGTH = 32;  
const int MAX_NAME_LENGTH = 1024;  
  
// 崩溃信息  
//   

  
// 安全拷贝字符串函数  
//  

  
// 得到程序崩溃信息  
//  

// 得到CallStack信息  
//  
#define  GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS         (0x04)  // lpModuleName是模块中的一个地址
typedef BOOL (WINAPI* GetModuleHandleExA_T)(
                                            DWORD        dwFlags,
                                            LPCSTR     lpModuleName,
                                            HMODULE*    phModule
                                            );
HMODULE getmodulename(char* buffer,int size,void* addri)
{
    HMODULE hmodule;
    char FileName[MAX_PATH] = {0};
    GetModuleHandleExA_T GetModuleHandleExA=(GetModuleHandleExA_T)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetModuleHandleExA");
    GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)addri, &hmodule);
    GetModuleFileNameA(hmodule, buffer, size);
    return hmodule;
}
char* gettimestring(char* buffer)
{
    SYSTEMTIME  systemtime;
    GetSystemTime( &systemtime);
    sprintf(buffer,"[%2.2d.%2.2d]",systemtime.wHour,systemtime.wMinute,systemtime.wSecond,systemtime.wMilliseconds);
    return buffer;
}
void log(const char*format,...)
{
    va_list v;
    char buffer[300];
    char tbuffer[100];
    
    va_start(v,format);
    _vsnprintf(buffer,299,format,v);
    va_end(v);    
    char fname[100];
    sprintf(fname,"%d.txt",GetCurrentThreadId());
    
    FILE* fd = fopen(fname,"a+b");
    fprintf(fd,"  %s[%d.%d]%s
",gettimestring(tbuffer),GetCurrentProcessId(),GetCurrentThreadId(),buffer);
    fclose(fd);
    //OutputDebugStringA(buffer);
    
}
void logthread(DWORD threadid,const char*format,...)
{
    va_list v;
    char buffer[300];
    char tbuffer[100];
    
    va_start(v,format);
    _vsnprintf(buffer,299,format,v);
    va_end(v);    
    char fname[100];
    sprintf(fname,"%d.txt",threadid);
    
    FILE* fd = fopen(fname,"a+b");
    fprintf(fd,"  %s[%d.%d]%s
",gettimestring(tbuffer),GetCurrentProcessId(),GetCurrentThreadId(),buffer);
    fclose(fd);
    //OutputDebugStringA(buffer);
    
}
void PrintCallStackFromContext(const CONTEXT *pContext,HANDLE hThread,DWORD dwThreadId) ;
typedef HANDLE (WINAPI * OPENTHREADFUN)(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwThreadId);  
DWORD WINAPI __printstack(void* p)
{
    DWORD dwThreadId = (DWORD)p;
    DWORD error;    
    //1:kernel32 大部分程序都自动加载了kernel32.dll  所以再获得句柄之前不需要Loadlibray  
    HMODULE hKernel32 = ::GetModuleHandle("kernel32.dll");      
    //2获得函数指针  
    OPENTHREADFUN pFun = (OPENTHREADFUN)GetProcAddress(hKernel32,"OpenThread");  
    HANDLE hThread  = pFun(THREAD_GET_CONTEXT,0,dwThreadId);
    if(hThread==0){
        error = GetLastError();
        ::MessageBox(0,"error1",0,0);
        return -1;
    }
    CONTEXT tagContext;
    tagContext.ContextFlags = CONTEXT_FULL;
    if(GetThreadContext(hThread,&tagContext)){
        PrintCallStackFromContext(&tagContext,hThread,dwThreadId);
    }else{
        error = GetLastError();
        ::MessageBox(0,"error2",0,0);
        return -2;
    }
    return 0;
}
void  PrintCurrentCallStack()
{
    HANDLE hThread = CreateThread(0,0,__printstack,(void*)GetCurrentThreadId(),0,0);
    WaitForSingleObject(hThread,-1);
}
void PrintCallStackFromContext(const CONTEXT *pContext,HANDLE hThread,DWORD dwThreadId)  
{  
    HANDLE hProcess = GetCurrentProcess();  
  
   
    CONTEXT c = *pContext;  
  
    STACKFRAME64 sf;  
    memset(&sf, 0, sizeof(STACKFRAME64));  
    DWORD dwImageType = IMAGE_FILE_MACHINE_I386;  
  
    // 不同的CPU类型,具体信息可查询MSDN  
    //  
#ifdef _M_IX86  
    sf.AddrPC.Offset = c.Eip;  
    sf.AddrPC.Mode = AddrModeFlat;  
    sf.AddrStack.Offset = c.Esp;  
    sf.AddrStack.Mode = AddrModeFlat;  
    sf.AddrFrame.Offset = c.Ebp;  
    sf.AddrFrame.Mode = AddrModeFlat;  
#elif _M_X64  
    dwImageType = IMAGE_FILE_MACHINE_AMD64;  
    sf.AddrPC.Offset = c.Rip;  
    sf.AddrPC.Mode = AddrModeFlat;  
    sf.AddrFrame.Offset = c.Rsp;  
    sf.AddrFrame.Mode = AddrModeFlat;  
    sf.AddrStack.Offset = c.Rsp;  
    sf.AddrStack.Mode = AddrModeFlat;  
#elif _M_IA64  
    dwImageType = IMAGE_FILE_MACHINE_IA64;  
    sf.AddrPC.Offset = c.StIIP;  
    sf.AddrPC.Mode = AddrModeFlat;  
    sf.AddrFrame.Offset = c.IntSp;  
    sf.AddrFrame.Mode = AddrModeFlat;  
    sf.AddrBStore.Offset = c.RsBSP;  
    sf.AddrBStore.Mode = AddrModeFlat;  
    sf.AddrStack.Offset = c.IntSp;  
    sf.AddrStack.Mode = AddrModeFlat;  
#else  
    #error "Platform not supported!"  
#endif  
  
    //HANDLE hThread = GetCurrentThread();  
    logthread(dwThreadId,"=====stackwalk64=====");
  
    while (true)  
    {  
        // 该函数是实现这个功能的最重要的一个函数  
        // 函数的用法以及参数和返回值的具体解释可以查询MSDN  
        //  
        if (!StackWalk64(dwImageType, hProcess, hThread, &sf, &c, NULL, 0, 0, NULL))  
        {  
            break;  
        }  
  
        if (sf.AddrFrame.Offset == 0)  
        {  
            break;  
        }  
                  
        // 得到函数名  
        //  
            DWORD retaddress = (DWORD)sf.AddrPC.Offset;
            char buffer[300];
            HMODULE hmod = getmodulename(buffer,300,(void*)retaddress);
             logthread(dwThreadId,"retaddress=%s %x",buffer,retaddress-(DWORD)hmod);
  
    }  
    logthread(dwThreadId,"==========");
   
 }

 

以上是关于StackWalk64的主要内容,如果未能解决你的问题,请参考以下文章

StackWalk64

Stackwalk 在调试中获取函数名、行号和文件名

c_cpp 快速代码片段,用于在统计(阻止)/ dev / rdsk中的设备时验证fstat64和stat64的行为。

Java itext为pdf 文件添加水印核心功能代码片段

linux下使用dmp输出堆栈信息方法说明

-bash: /usr/bin/ls: /lib64/ld-linux-x86-64.so.2: bad ELF interpreter: No such file or directory(代码片段