C++ - 从结束地址获取函数的起始地址/获取函数的大小

标签 c++ visual-studio profiling compiler-options

我正在使用 visual studio 的/Gh 和/GH 编译器选项来分析一堆代码。使用的两种方法是 _penter 和 _pexit,当在被分析的代码中进入或退出函数时调用它们。由于我需要分析/调试特定函数,因此我使用了一个已经定义的数组 FuncTable,其中包含我需要使用其名称作为字符串进行检测的函数的地址。因此,当输入一个函数时,主要包含寄存器内容的 pStack[0] 包含到正在执行的代码的当前行的地址。同样,当函数退出时,pStack[0] 包含最后一行代码的地址。

问题:当输入一个函数(调用_penter)时,我在 pStack[0] 中得到函数第一行的地址,因此我可以通过减去一个函数的地址constant(-5) 并将其保存到我的列表中,以便稍后在 _pexit 函数中检索。但是由于在 _pexit 中我得到函数最后一行的地址,我需要找到函数的大小以便从 pStack[0] 中的地址减去该大小以到达函数的起始地址然后进行比较该地址保存在我的列表中。下面粘贴的是代码。

void _stdcall EnterFunc0(unsigned * pStack)
{
    void      * pCaller;
    pCaller = (void *)(pStack[0] - 5); // pStack[0] is first line, -5 for function address
    Signature * funct = FuncTable;

    while (funct->function)
    {
        const BYTE * func = (const BYTE *)funct->function;
        if ((func == (const BYTE *)pCaller) || ((*func == 0xE9) && ((func + *(DWORD *)(func + 1) + 5) == (const BYTE *)pCaller)))
        {
            Stack_Push(funct->name, funct->returnType, true, pCaller);          
        }
        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
    }
}
void _stdcall ExitFunc0(unsigned * pStack)
{
    if (startRecording) 
    {
        StackEntry * start = top;
        while (start != NULL)
        {
            //**HERE I NEED TO COMPARE THE ADDRESS OF THE FUNCTION WITH THE ONE ALREADY IN MY STACK**
                            if ((void *)(pStack[0] - sizeOfTheFunction) == start->Address)
            {
                OutputDebugString("Function Found\n");
            }
            start = start->next;
        }
    }

}
extern "C" __declspec(naked) void __cdecl _pexit()
{
    _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   ExitFunc0

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

最佳答案

您已经知道 _pexit() 函数中的地址,它是在 _penter() 函数中传递给您的。您所要做的就是支持嵌套函数调用。 std::stack<> 对此很有帮助。使用 push() 将地址保存在 _penter 中,使用 _pexit 函数中的 top() 检索它并调用 pop()。

根本不需要知道函数体的大小。

关于C++ - 从结束地址获取函数的起始地址/获取函数的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38252265/

相关文章:

c++ - #define 到底有什么用?

c++ - 通过引用 : TypeError: No to_python (by-value) converter found for C++ type: 调用 Boost.Python

c# - 如何添加 Controller ?

asp.net-mvc - 初学者的分析 Qn - ASP .NET MVC + Mini-Profiler + Chrome 开发者工具

ruby - 分析 Sinatra 应用程序的最佳方式是什么?

c++ - 如何为 map < map<int,int> , bool > 赋值?

c++ - 使用 Boost C++ 的多线程 - 同步问题

.net - vs 编译器提示 project.json 中缺少引用,但 .net proj 不是核心

c# - IIS Express 停止 Web 应用程序后立即关闭正在运行的站点

http - CouchDB/MochiWeb : negative effect of persistent connections