问题描述
我已经用C ++编写了一个Instrument-er,用于通过挂接enter和exit调用来记录进入和退出功能.它可以使用旧版代码库正常工作.但是,在挂钩我从git下载的项目时,我保存在主题代码中的extern变量中的函数地址,它们在事件探查器库中的输出是不同的.这搞砸了已钩函数和已保存函数之间的函数指针比较.
I have written an instrument-er in C++ to log entry and exit functions by hooking on enter and exit calls. It is working as supposed to with a legacy code base. However on hooking with a project that I downloaded from git, function addresses that I save in an extern variable in the subject code, they are coming out different in the profiler library. That is messing up the function pointer comparison between hooked and saved functions.
主题代码主文件中的函数地址,断点位于当前探查器代码中的_penter hook函数内
Function address in subject code main file, breakpoint is inside the _penter hook function in the profiler code currently
在分析器代码中,同一条目显示了一个不同的地址,该地址的函数名称前面带有"_"
The same entry is showing a different address with a "_" preceding the function name, in the profiler code
我不知道它是如何更改地址的,想知道我是否做错了事.
I have no idea how it is changing the addresses and want to know if I am doing something wrong.
我这样做的方法是,我有一个外部函数指针数组(及其名称),该函数数组在主体主文件(可用的所有函数)中用主体代码函数的引用进行了初始化.在库的挂钩函数(_penter)中,我得到刚输入的函数的地址.因此,我将其与extern数组中的地址进行比较,如果匹配,则记录输入的函数.
The way I am doing it is, I have an extern array of function pointers( and their names) that is initialized with subject code functions' references in the subject main file(where all functions are available). In hook function (_penter) of the library, I get the address of the function just entered. So I compare it with the addresses in the extern array, and if it is a match, I log the entered function.
摘自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
}
}
来自main.c的片段(主题代码主文件)
#include "../Profile/Profile.h"
Signature FuncTable[] = {
{ (int)TetrisView_ProcessPauseMenu, "TetrisView_ProcessPauseMenu" },
{ NULL }
};
推荐答案
我认为这是因为增量链接.启用后,您将获得一个增量链接表(ILT). ILT包含一个跳转表.调用函数时,将通过此ILT对其进行调用.
I think it is because of Incremental Linking. When it is turned on, you'll get an Incremental Linking Table (ILT). ILT contains a jump table. When a function is called, it is called via this ILT.
在FuncTable
中,您将获得一个位于ILT中的地址,而不是实际函数的地址.但是在_penter
中,其返回地址将是实际函数(这是pCaller
中的内容).
In FuncTable
, you'll get an address which is in ILT, it won't be the address of the actual function. But in _penter
, its return address will be the actual function (this is what is put in pCaller
).
关闭增量链接,就可以了.
Turn off incremental linking, and you'll be fine.
这篇关于在附加的探查器库中输出的c ++函数地址与主题代码库中的c ++函数地址不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!