如何在 x64 程序中获取堆栈调用信息?

问题描述

#ifdef X86
void TestGetCallStack_X86()
{
    std::cout << "Call -> TestGetCallStack_X86" << std::endl;
    std::cout << "***************************************" << std::endl;
    DWORD _ebp,_esp;
    __asm mov _ebp,ebp
    __asm mov _esp,esp

    for (unsigned int index = 0; index < CALLSTACK_NUM; index++) {
        void* pAddr = (void*)ULongToPtr(*(((DWORD*)ULongToPtr(_ebp)) + 1));
        if (!pAddr)
            return;

        IMAGEHLP_LINE64 Line;
        Line.SizeOfStruct = sizeof(Line);
        memset(&Line,sizeof(Line));
        DWORD Offset = 0;
        if (fnSymGetLineFromAddr64(s_Process,(DWORD64)pAddr,&Offset,&Line))
        {
            std::cout << index << " [" << pAddr << "]";

            std::cout << "  File Name:" << Line.FileName << "  " << "Line Count:" << Line.LineNumber << std::endl;
            std::cout << std::endl;
        }
        else
        {
            DWORD error = GetLastError();
            if (error == 487)
            {
                OutputDebugString(TEXT("No debug info in current module\n"));
            }
            else if (error == 126)
            {
                OutputDebugString(TEXT("Debug info in current module has not loaded\n"));
            }
            else
            {
                OutputDebugString(TEXT("SymGetLineFromAddr64 Failed\n"));
            }
            std::cout << std::endl;
        }
        _ebp = *(DWORD*)ULongToPtr(_ebp);
        if (_ebp == 0 || 0 != (_ebp & 0xFC000000) || _ebp < _esp)
            break;
    }
    std::cout << "***************************************" << std::endl;
}
#endif // X86

run result


  • 我编写了一个 x64 版本,发现 x64 的 MSVC 不支持内联汇编。
  • 我尝试编写一个 .asm 文件并以 C++ 代码加载该函数。但它不起作用。 (其实我不擅长汇编语言)
  • 我找到了很多方法。到目前为止,我已经使用 _ReturnAddress 来实现。
void TestGetCallStack_X64()
{
    void* pAddr = _ReturnAddress();
    if (!pAddr)
        return;
    std::cout << "0" << "\t" << pAddr << std::endl;
    std::cout << "Use GetLineFromAddress64:" << std::endl;

    IMAGEHLP_LINE64 Line;
    Line.SizeOfStruct = sizeof(Line);
    memset(&Line,sizeof(Line));
    DWORD Offset = 0;
    if (fnSymGetLineFromAddr64(s_Process,&Line))
    {
        std::cout << "File Name:" << Line.FileName << "\t" << "Line Count:" << Line.LineNumber << std::endl;
        std::cout << std::endl;
    }
    else
    {
        //Can not find...
    }
}

Run Result

  • 但是这种方式不能完全显示堆栈调用的信息。怎样才能达到和x86版本一样的效果

PS:我无法理解 x86 代码中的中断条件。有谁能解答,求解答!先谢谢了。

//what's the mean that <_ebp & 0xFC000000>

if (_ebp == 0 || 0 != (_ebp & 0xFC000000) || _ebp < _esp)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)