在x64 DLL中强制名称变化 [英] Forcing name mangling in x64 DLL

查看:157
本文介绍了在x64 DLL中强制名称变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将32位应用程序移植到64位。该应用程序支持的DLL是DLL。不幸的是,每个插件需要具有的一个强制性功能称为 FreeLibrary ,这当然与 kernel32 API同名。我的插件API使用 FreeLibrary 名称的原因是应用程序起源于不同的平台,其中 FreeLibrary 不与任何操作系统API冲突。但是,即使是使用 FreeLibrary 的32位Windows也不是问题,因为32位DLL使用名称变换,即该函数存储为 _FreeLibrary ,因此不会与 kernel32 API冲突。



虽然64位,但是现在有一个问题,因为64位似乎并没有使用名称调整。在64位编译器上创建一个名为 FreeLibrary 的符号,这当然与同名的 kernel32 API冲突并拒绝链接,导致以下错误:

  Microsoft(R)增量链接器版本9.00.30729.01 
版权所有(C)微软公司。版权所有。

kernel32.lib(KERNEL32.dll):错误LNK2005:已经在test.o
中定义的FreeLibrary创建库test.lib和对象test.exp
test.dll:fatal错误LNK1169:找到一个或多个多重定义符号

因此,我想知道是否有任何方式强制x64 DLL使用32位的名称修改,以便我的DLL可以导出一个名为 FreeLibrary 的符号,而不会与 kernel32



还有其他解决方案可以解决这个问题吗?



唯一的解决方案是重命名 FreeLibrary 不会与我的应用程序的x64版本的操作系统API冲突,但我当然希望避免这种情况,因为它减少了我应用程序的插件的一致性API。如果可能,我想在所有平台和体系结构中保留 FreeLibrary 名称。



任何想法?我猜,如果在一个DLL中使用32位的保留名称,例如$ code> FreeLibrary ,那么应该有一种方法可以在64位上执行,在那里?但是我看不到如何...

解决方案

我不会试图说服编译器来调用函数的名称。为了澄清,您唯一的问题是连接插件DLL时的重复符号。



应用程序本身不应该关心这些函数的名称,因为它将通过 GetProcAddress 收到的函数指针调用插件入口点。



假设插件不需要调用kernel32.dll中实现的Windows API,可以尝试从链接器命令中省略kernel32.dll。 (请参阅 / NODEFAULTLIB 选项。)如果kernel32.dll不是链接的一部分,那么应该没有碰撞。



但是这不会奏效,因为命令行中的 / MT 意味着您依赖于C运行时库,而依赖于某些kernel32 .dll API。 (另外,您确定要将插件与静态运行库相关联,而不是DLL版本?)



所以剩下的选项是更改名称的功能。这应该是微不足道的,因为你正在移植。您甚至可以在编译插件时使用预处理器来破解名称,以便您不需要更改其源代码。

  cl / EHsc / c / DFreeLibrary = Plugin_FreeLibrary /Fotest.o test.c 

然后更改 GetProcAddress 在应用程序中调用以查找 Plugin_FreeLibrary 而不是 FreeLibrary ,我假设发生在一个地方。


I am porting a 32-bit application to 64-bit. The application supports plugins which are DLLs. Unfortunately, one of the mandatory functions each plugin needs to have is called FreeLibrary which of course conflicts with the kernel32 API of the same name. The reason why my plugin API uses the FreeLibrary name is that the application originated on a different platform where FreeLibrary doesn't clash with any OS APIs.

However, even on 32-bit Windows using FreeLibrary is not a problem because 32-bit DLLs use name mangling, i.e. the function is stored as _FreeLibrary and hence doesn't clash with the kernel32 API.

On 64-bit, though, I have a problem now because 64-bit doesn't seem to use name mangling. On 64-bit the compiler creates a symbol named FreeLibrary and this of course clashes with the kernel32 API of the same name and refuses to link, leading to the following error:

Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

kernel32.lib(KERNEL32.dll) : error LNK2005: FreeLibrary already defined in test.o
    Creating library test.lib and object test.exp
test.dll : fatal error LNK1169: one or more multiply defined symbols found

Thus, I'm wondering whether there is any way to force x64 DLLs to use name mangling as on 32-bit so that my DLL can export a symbol named FreeLibrary without any clashes with kernel32?

Or is there any other solution to work around this problem?

The only solution I see is to rename FreeLibrary to something that doesn't clash with OS APIs for the x64 versions of my application but of course I'd like to avoid this because it reduces the consistency of my application's plugin API. If possible, I'd like to keep the FreeLibrary name across all platforms and architectures.

Any ideas? I guess if it was possible on 32-bit to use reserved names like FreeLibrary in a DLL then there should be a way to do it on 64-bit as well, shouldn't there? But I don't see how...

解决方案

I would not try to convince the compiler to mangle the names of the functions. That way lies madness.

To clarify, your only issue is the duplicate symbols when linking plugin DLLs. The application itself shouldn't care what the functions are named, because it's going to call the plugin entry points through function pointers received via GetProcAddress.

Assuming, the plugins don't ever need to call Windows APIs implemented in kernel32.dll, you could try omitting kernel32.dll from the linker command. (See the /NODEFAULTLIB option.) If kernel32.dll isn't part of the link, there should be no collision.

But that won't work because /MT in the command line implies you depend on the C run-time library, which, in turn, depends on some kernel32.dll APIs. (Also, are you sure you want to link the plugins against the static run-time library and not the DLL version?)

So the remaining option is to change the name of the function. This should be trivial, since you're porting anyway. You could even use the preprocessor to hack the name when compiling the plugins so that you don't need to change their source code:

cl /EHsc /c /DFreeLibrary=Plugin_FreeLibrary /Fotest.o test.c

And then change the GetProcAddress call in the application to look for Plugin_FreeLibrary instead of FreeLibrary, which I assume happens in just one place.

这篇关于在x64 DLL中强制名称变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆