3

我正在开发一个项目来生成一个用于离线测试的虚拟 DLL。我们有真正的 DLL 及其头文件,尽管它们看起来不兼容。DLL 中的名称未被破坏,但函数前向声明声明被调用为__stdcall

例子.h

DWORD __stdcall DoSomething(byte aByte);

Dependency Walker 中的 example.dll:

2 (0x0002)   2 (0x0002)   DoSomething   0x000831C0

据我所知,如果可以在__stdcall约定中导出一个函数,它的名称应该在依赖 walker 中读取为:

2 (0x0002)   2 (0x0002)   _DoSomething@1   0x000831C0

这是否意味着我们的头文件与编译的 DLL 不对应,还是我遗漏了什么?

最终,我如何形成虚拟函数的导出,使其行为方式与我正在模拟的真实 DLL 相同?

4

2 回答 2

5

只有两种方法可以获取 __stdcall 名称修饰:

  • 您必须使用 .def 文件来重命名导出。通过不使用它来获得成功。

  • 您构建了针对 x64 的代码。由于它只有一个调用约定,编译器将忽略您的 __stdcall 属性,并且不会修饰名称。现在您需要一个 .def 文件来重命名导出。永远不要这样做,没有人会期望在 64 位代码中使用装饰。

请注意,如果经过修饰,导出的名称将为 _DoSomething@4。名称的 @ 部分表示堆栈激活帧的大小。换句话说,在函数返回之前需要从堆栈中弹出的字节数。对于 32 位代码,它永远不能是 1,它始终是 4 的倍数。这种名称装饰之所以存在是因为 __stdcall 非常危险,函数弹出的堆栈比预期的多或少会导致很难诊断堆栈不平衡。链接器捕获函数原型声明错误。

于 2014-06-25T13:27:50.923 回答
0

停止更改您之前使用 __stdcall 的过程名称:如果您使用 gnu c++ 编译器-Wl,--kill-at,请在链接器中添加“”参数。

如果您使用代码块:

"Settings" -> "Compiler..."
"Global compiler settings"
"Linker settings"
"Other linker options":
add: "-Wl,--kill-at"

如果你使用 devc++

project->project options
Parameters
add "-Wl,--kill-at" to linker
于 2016-01-20T02:58:00.887 回答