c ++函数地址在附加的探查器库中与主题代码库中不同
c++ function addresses coming out different in attached profiler library than in the subject code base
我用 C++ 编写了一个 instrument-er,通过挂钩进入和退出调用来记录进入和退出函数。它按预期与遗留代码库一起工作。然而,在挂钩我从 git 下载的项目时,我保存在主题代码中的外部变量中的函数地址,它们在探查器库中出现了不同。这搞乱了挂钩函数和保存函数之间的函数指针比较。
主体代码主文件中的函数地址,断点在当前profiler代码中的_penter钩子函数内
同一条目在探查器代码中显示了函数名称前面带有“_”的不同地址
我不知道它是如何更改地址的,想知道我是否做错了什么。
我这样做的方式是,我有一个函数指针(及其名称)的外部数组,它是用主题主文件(所有函数都可用)中的主题代码函数引用初始化的。在库的钩子函数(_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
}
}
来自 main.c 的片段(主题代码主文件)
#include "../Profile/Profile.h"
Signature FuncTable[] = {
{ (int)TetrisView_ProcessPauseMenu, "TetrisView_ProcessPauseMenu" },
{ NULL }
};
我认为这是因为增量链接。当它打开时,您将获得增量链接 Table (ILT)。 ILT 包含一个跳跃 table。当一个函数被调用时,它是通过这个ILT调用的。
在FuncTable
中,你会得到一个在ILT中的地址,它不会是实际函数的地址。但在 _penter
中,它的 return 地址将是实际函数(这是 pCaller
中的内容)。
关闭增量链接,你会没事的。
我用 C++ 编写了一个 instrument-er,通过挂钩进入和退出调用来记录进入和退出函数。它按预期与遗留代码库一起工作。然而,在挂钩我从 git 下载的项目时,我保存在主题代码中的外部变量中的函数地址,它们在探查器库中出现了不同。这搞乱了挂钩函数和保存函数之间的函数指针比较。
主体代码主文件中的函数地址,断点在当前profiler代码中的_penter钩子函数内
同一条目在探查器代码中显示了函数名称前面带有“_”的不同地址
我不知道它是如何更改地址的,想知道我是否做错了什么。
我这样做的方式是,我有一个函数指针(及其名称)的外部数组,它是用主题主文件(所有函数都可用)中的主题代码函数引用初始化的。在库的钩子函数(_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
}
}
来自 main.c 的片段(主题代码主文件)
#include "../Profile/Profile.h"
Signature FuncTable[] = {
{ (int)TetrisView_ProcessPauseMenu, "TetrisView_ProcessPauseMenu" },
{ NULL }
};
我认为这是因为增量链接。当它打开时,您将获得增量链接 Table (ILT)。 ILT 包含一个跳跃 table。当一个函数被调用时,它是通过这个ILT调用的。
在FuncTable
中,你会得到一个在ILT中的地址,它不会是实际函数的地址。但在 _penter
中,它的 return 地址将是实际函数(这是 pCaller
中的内容)。
关闭增量链接,你会没事的。