c++ - Windows:在 C++ 中获取函数地址

标签 c++ windows function pointers

我正在尝试获取函数地址以使用 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 在这里对您“撒谎”。当您打印 funcptrgio 时,您会看到实际地址,即您在编写时跳转到的地址

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/

相关文章:

windows - ec2 block 设备映射列表与 Windows 驱动器之间的映射

sql - 是否可以在 Sql server 级别创建全局存储过程

c++ - 错误 : cast from 'Foo*' to 'unsigned int' loses precision

c++ - 指向销毁类失效的指针

c++ - C++ RTTI 是否始终适用于所有平台?

javascript - 需要帮助更改变量值以更改显示的消息

PHP组合两个或多个数组

c++ - 检测函数对象(仿函数)和 lambda 特征

windows - 将自签名 XAP 部署到 Windows Phone 8

mysql - 子查询不适用于 Windows,但适用于 Linux