如何剥离共享对象(Shared Object)中除指定符号外的所有符号?
如何在共享对象中仅保留指定公开符号并隐藏其余符号
有两种可靠的方法可以实现你的需求:只让SoMain()作为公开符号,隐藏其他所有函数名,避免被反汇编工具识别。
方法一:编译时设置默认符号隐藏,显式公开目标符号
通过-fvisibility=hidden编译选项将所有符号默认设为隐藏,再给需要公开的SoMain()添加visibility("default")属性,确保它能被外部识别。
修改后的代码:
#include <fstream> #include <iostream> // 这些函数默认会被隐藏,无需额外标记 void PrintMessage(std::string msg) { std::cout << msg << std::endl; } void HelloWorld() { std::string s = "HelloWorld!"; std::cout << s << std::endl; } // 显式指定该符号为公开可见,同时保留constructor属性 extern "C" __attribute__((constructor, visibility("default"))) void SoMain() { std::ofstream file("HelloWorld"); file.close(); HelloWorld(); }
对应的编译命令:
g++ -shared -fPIC -fvisibility=hidden -o test.so test.cpp
方法二:使用链接脚本控制符号导出
如果你不想修改代码,可以通过链接脚本精确指定要导出的符号,其余全部隐藏。
- 创建一个名为
export.lds的链接脚本文件,内容如下:
{ global: SoMain; # 仅公开SoMain符号 local: *; # 所有其他符号设为局部(隐藏) };
- 编译时指定该链接脚本:
g++ -shared -fPIC -Wl,--version-script=export.lds -o test.so test.cpp
验证效果
编译完成后,可以用以下命令检查动态符号表,确认只有SoMain可见:
nm -D test.so # 或者 readelf -s test.so
执行后你会发现,HelloWorld、PrintMessage等函数不会出现在动态符号表中,反汇编工具自然无法识别这些函数名。
内容的提问来源于stack exchange,提问作者MegaMagnum
相关产品推荐
相关产品推荐

