我正在尝试获取函数地址以使用 memcpy 将其内容复制到缓冲区中。
我遇到的问题是获取函数地址。这是我的代码:
__declspec(noinline) int gio()
{
const char yle[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
return 7;
}
int main(int argc, TCHAR* argv[])
{
int(*funcptr)() = gio;
unsigned char *p = (unsigned char *)&funcptr;
size_t ik;
for (ik = 0; ik < sizeof funcptr; ik++)
{
printf("%02x ", p[ik]);
}
putchar('\n');
printf("gio x -> %x\n", gio);
printf("gio p -> %p\n", gio);
}
我创建了一个小测试程序,尝试用不同的方式打印函数地址。
我正在使用 Visual Studio 并关闭了优化和内联函数扩展(但无论如何都使用了 noinline)。所有打印语句打印相同的输出(0x00d213ca
screenshot)但是当我将光标(在 VS 中)放在 gio
函数上时,它显示完全不同的地址(0x00d218c0
screenshot )。
当我右键单击 gio 函数并 Go To Dissassembler
时,我跳转到了将光标放在它上面时显示的地址 (0x00d218c0
screenshot )。这清楚地显示了此功能的真正位置。
我在这里有点困惑,好像我不明白什么。
为什么打印语句显示不正确的值?获取“真实”函数地址的方法是什么?
最佳答案
Visual Studio 在这里对您“撒谎”。当您打印 funcptr
或 gio
时,您会看到实际地址,即您在编写时跳转到的地址
gio() // or funcptr()
与 Incremental Linking由于 thunking,当您将鼠标悬停在 gio
上时,此值不同于 Visual Studio 告诉您的值,请参阅 /INCREMENTAL .
May contain jump thunks to handle relocation of functions to new addresses.
要找出代码的地址,您可以禁用增量链接或
使用 DIA SDK :
// initialize DIA SDK, etc.
void (*fp)() = &foo;
printf("foo(): %p\n\n", foo);
HMODULE hModule = GetModuleHandle(NULL);
DWORD rva = (DWORD)((size_t)fp - (size_t)hModule);
IDiaSymbol *pDiaSymbol;
hr = pDiaSession->findSymbolByRVA(rva, SymTagPublicSymbol, &pDiaSymbol);
if(FAILED(hr) || !pDiaSymbol)
return hr;
ULONGLONG targetVA;
hr = pDiaSymbol->get_targetVirtualAddress(&targetVA);
pDiaSymbol->Release();
if(FAILED(hr))
return hr;
if(hr == S_OK)
printf("foo is a thunk, actual address: %p\n\n", (LPVOID)((size_t)hModule + targetVA));
但可能还有一种我不知道的更简单的方法。
关于c++ - Windows:在 C++ 中获取函数地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48966988/