[FIXED] How to strip symbols from Android NDK .so file?

Issue

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.

Solution

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: *; };

Answered By – mstorsjo

Answer Checked By – Mary Flores (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published