c++函数地址在附加的探查器库中与主题代码库中不同

标签 c++ profiler trace instrumentation

我用 C++ 编写了一个 instrument-er,通过 Hook 进入和退出调用来记录进入和退出函数。它按预期与遗留代码库一起工作。然而,在 Hook 我从 git 下载的项目时,我保存在主题代码中的外部变量中的函数地址,它们在探查器库中出现不同。这搞乱了 Hook 函数和保存函数之间的函数指针比较。

主体代码主文件中的函数地址,断点在当前profiler代码中的_penter钩子(Hook)函数内 enter image description here

同一个条目在探查器代码中显示了一个不同的地址,函数名称前面有一个“_” The same entry is showing a different address with a "_" preceding the function

我不知道它是如何更改地址的,我想知道我是否做错了什么。

我这样做的方式是,我有一个函数指针(及其名称)的外部数组,它使用主题主文件(所有函数都可用)中的主题代码函数引用进行了初始化。在库的钩子(Hook)函数(_penter)中,我得到了刚刚进入的函数的地址。所以我将它与外部数组中的地址进行比较,如果匹配,我记录输入的函数。

来自 PROFILE.H 的片段(分析器)

extern Signature FuncTable[3000]; 

来自 PROFILE.CPP 的片段(分析器)

void _stdcall EnterFunc0(unsigned * pStack)
{
    void      * pCaller;
    pCaller = (void *)(pStack[0] - 5); // the instruction for calling _penter is 5 bytes long
    Signature * funct = FuncTable; //the table that has references to functions and their names
    funct = FuncTable;
    while (funct->function)
    {
        //const BYTE * func = (const BYTE *)funct->function;
        if ((void *)(pStack[0] - 5) == (void *)(funct->function))
        {
            int a = 0;
            linesBuffer = linesBuffer + "Entering " + funct->signature + ";";
            linesBuffer = linesBuffer + "\n";
            WriteToFile(false); //function buffers 100kb before writing
            break;
        }
        funct++;
    }
}
extern "C" __declspec(naked) void __cdecl _penter()
{
    _asm
    {
        pushad              // save all general purpose registers
            mov    eax, esp     // current stack pointer
            add    eax, 32      // stack pointer before pushad
            push   eax          // push pointer to return address as parameter to EnterFunc0

            call   EnterFunc0

            popad               // restore general purpose registers
            ret                 // start executing original function
    }
}

SNIPPET FROM main.c(主题代码主文件)

#include "../Profile/Profile.h"
Signature FuncTable[] = {
    { (int)TetrisView_ProcessPauseMenu, "TetrisView_ProcessPauseMenu" },
    { NULL }
};

最佳答案

我认为这是因为增量链接。当它打开时,您将获得一个增量链接表 (ILT)。 ILT 包含一个跳转表。当一个函数被调用时,它是通过这个 ILT 调用的。

FuncTable 中,您会得到一个ILT 中的地址,它不会是实际函数的地址。但在 _penter 中,它的返回地址将是实际函数(这是放在 pCaller 中的内容)。

关闭增量链接,你会没事的。

关于c++函数地址在附加的探查器库中与主题代码库中不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45003759/

相关文章:

c++ - 从派生类中调用 operator =

c++ - 在 C++ 中计算矩阵秩的最快方法/库是什么

profiler - JMH 的 DTraceAsmProfiler 在 Mac 上失败并显示 '[sudo: a password is required'

java - 带有 RMI 调用的类加载器

winapi - Windows 上的低开销 I/O 监控

c++ - 防止在模板中使用某些类型

c++ - 是否可以更改只读编辑控件的背景颜色

像 JetBrains dotTrace 这样的 JavaScript Profiler?

C# 最简单的跟踪或日志

linux - 分析一个(可能受 I/O 限制的)进程以减少延迟