How to strip symbols from Android NDK .so file?
Asked Answered
P

2

8

How do you strip symbols from an Android .so native code library?

I have a .so built that has thousands of symbols clearly visible in a hex editor. IDA Pro automatically disassembles with proper symbols based on the ones in the executable.

However, if I ask nm to dump the symbol table, it says there are none. strip and objcopy also have no effect.

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

Names have been changed to protect the guilty.

Pisgah answered 31/5, 2018 at 23:56 Comment(0)
H
11

Since the .so is a shared library that will be loaded dynamically, it needs to have some amount of symbols available externally. To view these, use nm -D libMeow.so. Strip won't remove these, or it would make the library unusable.

Since the some functions need to be loaded externally, you can't just remove all dynamic symbols, because then nobody would be able to interface with the .so. If your .so is a JNI library, you need to have the JNI entry point functions visible externally, while if it is a shared library that another .so links against, you need to have at least the public interface of your library visible.

To make the internal symbols hidden, you can read https://gcc.gnu.org/wiki/Visibility for the full story. Roughly, your options are:

  • Use __attribute__ ((visibility ("hidden"))) on every symbol you don't want to be visible outside of the library. (This probably is quite a few and it's a lot of work to track down every single one.)
  • Build with -fvisibility=hidden, which implicitly sets this on every single external symbol, and add __attribute__ ((visibility ("default"))) on the ones that you actually need to have exported (probably much fewer)
  • Use a "version script" to limit what functions to export to a select list. When linking, pass -Wl,-version-script -Wl,mylib.ver.

For the version script case, mylib.ver should look like this:

{ global:
PublicFunction1;
PublicFunction2;
local: *; };
Hike answered 1/6, 2018 at 6:27 Comment(4)
The -D option, whatever it is, allows me to see the symbols, finally.Pisgah
You should also consider -fvisibility-inlines-hidden since you mentioned the Visibility thing. And -Wl,--exclude-libs,ALL is a must if linking against other libraries. Without -Wl,--exclude-libs,ALL our shared object was re-exporting hundreds of symbols even with -fvisibility=hidden -fvisibility-inlines-hidden. Also see How to apply gcc -fvisibility option to symbols in static libraries?Piecrust
Another set of options that may help reduce size and symbols are compiler flags -ffunction-sections -fdata-sections and linker flag -Wl,--gc-sections.Piecrust
JNIEXPORT allows you to mark your JNI functions and use -fvisibility=hidden. More detail:https://mcmap.net/q/447516/-when-to-use-jniexport-and-jnicall-in-android-ndkRugged
P
0

You have probably the BSD nm not the GNU one. Try objdump -TC ......

Peloria answered 1/6, 2018 at 2:26 Comment(1)
I deleted the pathname from my example to make it easier to read. In reality, I was specifically running the ones in the Android NDK directories.Pisgah

© 2022 - 2024 — McMap. All rights reserved.