如何指定DLL导出的“干净”名称?

问题描述 投票:0回答:1

我已经定义了DLL导出如下:

__declspec(dllexport) 
DWORD WINAPI DllBootstrap(LPVOID addr) {
    return 0;
}

现在,使用DUMPBIN,符号显示如下:

  1    0 0001100A ?DllBootstrap@@YGKPAX@Z = @ILT+5(?DllBootstrap@@YGKPAX@Z)

这就是内存在Visual Studio中的外观:

¡}....ReflectDLL.dll.?DllBootstrap@@YGKPAX@Z..........................................

检查PIMAGE_EXPORT_DIRECTORY.AddressOfNames时。

我需要的是一个干净的符号,即DUMPBIN应输出如下内容:

  1    0 0001100A DllBootstrap

PIMAGE_EXPORT_DIRECTORY.AddressOfNames应指向:

DllBootstrap..........................................

我怎样才能做到这一点?

windows portable-executable
1个回答
1
投票

WIN32建议:

正如@RbMm指出的那样,为了保持您的函数名称不存在并且没有名称修饰,您必须使用.DEF文件(并删除__declspec(dllexport)说明符)。然后使用下面的行创建一个DEF文件,并使用/ DEF链接器选项指定它或将其添加到Visual Studio项目中,链接器将自动拾取它:

EXPORTS DllBootstrap

如果您不想处理外部.DEF文件并且您将使用Visual C ++编译器,那么使用代码限制修饰的最简单方法是使用'extern“C”'声明您的函数。这导致装饰包括前面的下划线,并附加“@”以及参数的十进制字节数。以下代码为例:

extern "C" __declspec(dllexport)
DWORD WINAPI DllBootstrap(LPVOID addr) {
    return 0;
}

生成一个导出的名称:

_DllBootstrap@4

这是使用'extern“C”'禁用C ++名称修改时装饰stdcall函数的方法。注意:WINAPI映射到__stdcall。保留'extern“C”'并将约定更改为__cdecl,您将无法获得任何装饰,但模块入口点通常应保持stdcall,因为您已在样本中列出它。

如果您仍想避免使用.DEF文件,那么您可以使用最后一个hack。将以下行添加到您的代码中:

#pragma comment(linker,"/EXPORT:DllBootstrap=_DllBootstrap@4")

这将向链接器传递一个参数,创建一个新的未修饰的名称符号,该符号映射到修饰的名称。这不是很干净,因为原始名称仍然存在于您的DLL中,但您将获得干净的导出名称。

WIN64 BUILDS(更新):

正如Hans Passant评论的那样,对于任何使用Visual C ++ 64位编译器的人来说,只有64位调用约定(stdcall,cdecl等关键字被忽略)。虽然在此编译器下仍会发生C ++重整,但不会对导出的名称进行额外修饰。在这种情况下,当样本编译为C ++代码时,'extern“C”'就足够了;如果编译为C,则不需要进行任何修改。

© www.soinside.com 2019 - 2024. All rights reserved.