从 DLL 中去除特定符号
Posted
技术标签:
【中文标题】从 DLL 中去除特定符号【英文标题】:Strip specific symbols from DLL 【发布时间】:2014-01-09 17:42:03 【问题描述】:我使用 MSVC 2010 创建了一个 Win32-DLL,其中包含不需要的导出 C++ 符号。我正在使用模块定义文件 (.def
) 和 __stdcall
约定来处理我想要导出的特定功能。但是,由于我也在使用 Boost 序列化,因此有大量从 Boost 导出的 C++ 符号。由于这个事实,这些符号由 Boost 导出(找到 here):
我正在使用 1.44.0 的 boost::serialization。我注意到的一件事 是静态链接到序列化库会添加几个 我得到的最终 exe 文件中有一百个导出。使用
dumpbin /exports my_program.exe
这些函数不是从库中显式调用的。但是他们 ARE 作为序列化过程的一部分调用。它只是那个 MSVC 没有看到他们。因此,当您编译发布时,MSVC 链接器 剥离它们,程序将不再工作。为了工作 围绕这一点,这些函数被显式导出。这可以防止 MSVC 从剥离它们。有关更多信息,请参阅 force_include.hpp
导出的符号(摘录):
class boost::archive::detail::extra_detail::map<class boost::archive::binary_oarchive> & >boost::serialization::singleton<class boost::archive::detail::extra_detail::map<class boost::archive::binary_oarchive> >::get_instance(void)'::`2'::`local static guard'2'
您可以通过创建一个 DLL 项目并包含 Boost(链接到 libboost_serialization-vc100-mt-gd-1_55.lib
)来重现这种情况:
#include <boost/archive/binary_oarchive.hpp>
#include <fstream>
extern "C" int __stdcall test();
int __stdcall test()
std::fstream stream;
boost::archive::binary_oarchive o(stream, boost::archive::no_header);
return 1;
我测试了 GNU 实用程序 strip
from binutils
。但是,它似乎总是删除所有符号。例如。使用这个命令
strip --strip-symbol=test DllBoostTest.dll -o test.dll
这个简单的测试不起作用。它应该只删除测试符号。不幸的是,它也删除了所有符号。使用通配符和-N
也不起作用,因为它也会删除所有导出。
那么有没有办法删除所有不需要的 boost C++ 符号?比如说,删除所有带有“boost”文本的符号?
如果您需要更多信息,我很乐意提供。
注意:这与调试或 PDB 文件无关!
【问题讨论】:
【参考方案1】:这很难以干净的方式解决。真正的解决方法是消除 boost hack 以强制包含这些符号。这将需要删除 __declspec(dllexport) 属性并使用 /OPT:NOREF 链接器选项来抑制优化或使用 /INCLUDE(或 #pragma 注释)来确保包含符号。然而,这需要重建 boost 库,并且由于名称混乱的不可预测性,维护起来很麻烦。所以你可能不喜欢这个选项,Boost 团队显然不喜欢。
我认为尝试破解 strip 不会让你走到任何地方,重要的是链接器仍然可以看到这些符号,因此它不会优化它们。您只能在构建 DLL 之后执行此操作,这需要重写文件中的导出表。这在技术上是可行的,但并不容易做到。
一种可能性是阻止这些名称可见。 DEF 文件为您提供了该选项,您可以使用 NONAME 属性来防止名称可见,并使用 PRIVATE 属性来防止名称在导入库中可见。让它看起来像这样:
EXPORTS
??_B?1??get_instance@?$singleton@V?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@boost@@@serialization@boost@@CAAAV?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@3@XZ@51 @1 NONAME PRIVATE
??_B?1??get_instance@?$singleton@V?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@@serialization@boost@@CAAAV?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@XZ@51 @2 NONAME PRIVATE
?get_const_instance@?$singleton@V?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@boost@@@serialization@boost@@SAABV?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@3@XZ @3 NONAME PRIVATE
?get_const_instance@?$singleton@V?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@@serialization@boost@@SAABV?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@XZ @4 NONAME PRIVATE
?get_instance@?$singleton@V?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@boost@@@serialization@boost@@CAAAV?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@3@XZ @5 NONAME PRIVATE
?get_instance@?$singleton@V?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@@serialization@boost@@CAAAV?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@XZ @6 NONAME PRIVATE
?get_mutable_instance@?$singleton@V?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@boost@@@serialization@boost@@SAAAV?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@3@XZ @7 NONAME PRIVATE
?get_mutable_instance@?$singleton@V?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@@serialization@boost@@SAAAV?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@XZ @8 NONAME PRIVATE
?instance@?$singleton@V?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@boost@@@serialization@boost@@0AAV?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@3@A @9 NONAME PRIVATE
?instance@?$singleton@V?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@@serialization@boost@@0AAV?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@A @10 NONAME PRIVATE
?is_destroyed@?$singleton@V?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@boost@@@serialization@boost@@SA_NXZ @11 NONAME PRIVATE
?is_destroyed@?$singleton@V?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@@serialization@boost@@SA_NXZ @12 NONAME PRIVATE
?t@?1??get_instance@?$singleton@V?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@boost@@@serialization@boost@@CAAAV?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@4@XZ@4V?$singleton_wrapper@V?$map@Vbinary_oarchive@archive@boost@@@extra_detail@detail@archive@boost@@@734@A @13 NONAME PRIVATE
?t@?1??get_instance@?$singleton@V?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@@serialization@boost@@CAAAV?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@XZ@4V?$singleton_wrapper@V?$multiset@PBVextended_type_info@serialization@boost@@Ukey_compare@detail@23@V?$allocator@PBVextended_type_info@serialization@boost@@@std@@@std@@@detail@34@A @14 NONAME PRIVATE
_test@0 = _test@0
您将收到 LNK4197 警告,因为链接器看到两个导出请求,一个来自 __declspec(dllexport),另一个来自 DEF 文件。这些警告是良性的,您可以忽略它们。请注意,您可能需要调整这些名称,我使用 VS2012 和 Boost 版本 1.53 对此进行了测试
删除 PDB 文件后(不要忘记),导出如下所示:
ordinal hint RVA name
15 0 0001582F _test@0
1 0004DE94 [NONAME]
2 0004DEB8 [NONAME]
3 0001524E [NONAME]
4 000153A2 [NONAME]
5 00015AA5 [NONAME]
6 00015460 [NONAME]
7 000154E7 [NONAME]
8 00016199 [NONAME]
9 0004DE7C [NONAME]
10 0004DEA0 [NONAME]
11 00015AFF [NONAME]
12 00015B9F [NONAME]
13 0004DE84 [NONAME]
14 0004DEA8 [NONAME]
【讨论】:
对。这似乎是唯一可用的选项。除了您对 boost 的导出符号之外,我找不到任何其他答案。但是,这当然不是一种选择。所以感谢 DEF 文件提示。【参考方案2】:使用 MSVC 2010,您可能没有任何适合您的选项,但是在 VS2012/2013 you have an option 'pdbcopy.exe' 中。 从帮助中,您可能会找到您需要的内容:
PDBCopy v11.00.50307
usage: PDBCopy <source_pdb> <destination_pdb> [-p] [-s] [-f] [-F] [-a] [-A] [-?]
[-p] remove private debug information
[-s] create new signature
[-f:@file|symbol] filter specific public symbols out of stripped pdb
[-F:@file|symbol] leave only specific public symbols in stripped pdb
[-a] leave all annotation symbols in stripped pdb
[-a:@file|symbol] filter specific annotation symbols out of stripped pdb
[-A:@file|symbol] leave only specific annotation symbols in stripped pdb
[-?] display this message
【讨论】:
以上是关于从 DLL 中去除特定符号的主要内容,如果未能解决你的问题,请参考以下文章
如何去除重音符号并将字母变成“普通”的 ASCII 字符? [复制]