如何从Android NDK .so文件中去除符号?

8
如何从Android的.so本地代码库中删除符号?
我有一个已构建好的.so文件,其中有成千上万个符号在十六进制编辑器中明显可见。IDA Pro根据可执行文件中的符号自动反汇编出正确的符号。
然而,如果我要求nm转储符号表,则会显示没有符号。strip和objcopy也没有效果。
C:\AndroidProject.apk\lib\armeabi-v7a>arm-linux-androideabi-strings.exe libMeow.so | findstr _ZN11SecretClass14SecretFunctionERKS_
_ZN11SecretClass14SecretFunctionERKS_

C:\AndroidProject.apk\lib\armeabi-v7a>arm-linux-androideabi-nm.exe libMeow.so
arm-linux-androideabi-nm.exe: libMeow.so: no symbols

C:\AndroidProject.apk\lib\armeabi-v7a>copy /y libMeow.so libMeow-test.so
        1 file(s) copied.

C:\AndroidProject.apk\lib\armeabi-v7a>sha1sum libMeow.so libMeow-test.so
0a36701ba44b4cfb31e6f6506349493d5466cd70 *libMeow.so
0a36701ba44b4cfb31e6f6506349493d5466cd70 *libMeow-test.so

C:\AndroidProject.apk\lib\armeabi-v7a>arm-linux-androideabi-strip.exe libMeow-test.so

C:\AndroidProject.apk\lib\armeabi-v7a>sha1sum libMeow.so libMeow-test.so
0a36701ba44b4cfb31e6f6506349493d5466cd70 *libMeow.so
0a36701ba44b4cfb31e6f6506349493d5466cd70 *libMeow-test.so

C:\AndroidProject.apk\lib\armeabi-v7a>arm-linux-androideabi-strip.exe -g libMeow-test.so

C:\AndroidProject.apk\lib\armeabi-v7a>sha1sum libMeow.so libMeow-test.so
0a36701ba44b4cfb31e6f6506349493d5466cd70 *libMeow.so
0a36701ba44b4cfb31e6f6506349493d5466cd70 *libMeow-test.so

为保护罪犯隐私,人名已被更改。

2个回答

11
由于.so是一个将被动态加载的共享库,因此需要在外部提供一些符号。使用nm -D libMeow.so可以查看这些符号。剥离不会删除这些符号,否则库将无法使用。
由于某些函数需要在外部加载,因此不能仅删除所有动态符号,否则没有人能够与.so进行接口。如果您的.so是JNI库,则需要使JNI入口点函数在外部可见,而如果它是另一个.so链接的共享库,则需要至少使您的库的公共接口可见。
要隐藏内部符号,可以阅读https://gcc.gnu.org/wiki/Visibility获取完整信息。大致上,您有以下选择:
  • 在不希望在库外部可见的每个符号上使用__attribute__ ((visibility ("hidden"))).(这可能是相当多的工作,因为需要跟踪下每一个符号。)
  • 在编译时加上-fvisibility=hidden,这会隐式地设置在每个外部符号上,并在那些实际需要导出的符号上添加__attribute__ ((visibility ("default")))。(这可能要少得多。)
  • 使用“版本脚本”来限制要导出的函数列表。在链接时,传递-Wl,-version-script -Wl, mylib.ver
对于版本脚本案例,mylib.ver应该像这样:
{ global:
PublicFunction1;
PublicFunction2;
local: *; };

“-D”选项,不管它是什么,都让我最终看到了符号。 - Myria
2
你还应该考虑使用-fvisibility-inlines-hidden,因为你提到了可见性的事情。如果链接其他库,则必须使用-Wl,--exclude-libs,ALL。没有-Wl,--exclude-libs,ALL,即使使用-fvisibility = hidden -fvisibility-inlines-hidden,我们的共享对象也将重新导出数百个符号。另请参见如何将gcc -fvisibility选项应用于静态库中的符号? - jww
2
另一组可能有助于减小大小和符号的选项是编译器标志-ffunction-sections -fdata-sections和链接器标志-Wl,--gc-sections - jww
JNIEXPORT 允许您标记您的 JNI 函数并使用 -fvisibility=hidden。更多详情请参见:https://dev59.com/-WIk5IYBdhLWcg3wRcQo#21452277 - Danny Parker

0

你可能使用的是 BSD 的 nm,而不是 GNU 的。请尝试使用 objdump -TC ......


我从示例中删除了路径名,以使其更易于阅读。实际上,我特别运行的是Android NDK目录中的那些文件。 - Myria

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接