So, how to strip a shared library?
--strip-unneeded states that it removes all symbols that are not needed for relocation processing. This is a little cryptic, because one might reasonably assume that a shared library can be "relocated", in that it can be loaded anywhere. However, what this really refers to is object files that are usually built and bundled into a .a archive for static linking. For an object in an static library archive to still be useful, global symbols must be kept, although static symbols can be removed. Take the following small example:
$ cat libtest.c static int static_var = 100; int global_var = 100; static int static_function(void) { return static_var; } int global_function(int i) { return static_function() + global_var + i; }
Before stripping:
$ gcc -c -fPIC -o libtest.o libtest.c $ readelf --symbols ./libtest.o Symbol table '.symtab' contains 18 entries: Num: Value Size Type Bind Vis Ndx Name ... 5: 00000000 4 OBJECT LOCAL DEFAULT 5 static_var 6: 00000000 22 FUNC LOCAL DEFAULT 3 static_function 13: 00000004 4 OBJECT GLOBAL DEFAULT 5 global_var 16: 00000016 36 FUNC GLOBAL DEFAULT 3 global_function
After stripping:
$ strip --strip-unneeded libtest.o $ readelf --symbols ./libtest.o Symbol table '.symtab' contains 15 entries: Num: Value Size Type Bind Vis Ndx Name ... 10: 00000004 4 OBJECT GLOBAL DEFAULT 5 global_var 13: 00000016 36 FUNC GLOBAL DEFAULT 3 global_function
If you --strip-all from this object file, it will remove the entire .symtab section and will be useless for further linking, because you'll never be able to find global_function to call it!.
Shared libraries are different, however. Shared libraries keep global symbols in a separate ELF section called .dynsym. --strip-all will not touch the dynamic symbol entires, and thus it is therefore safe to remove all the "standard" symbols from the output file, without affecting the usability of the shared library. For example, readelf will still show the .dynsym symbols even after stripping:
$ gcc -shared -fPIC -o libtest.so libtest.c $ strip --strip-all ./libtest.so $ readelf --syms ./libtest.so Symbol table '.dynsym' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name ... 6: 00000452 36 FUNC GLOBAL DEFAULT 12 global_function 10: 000015e0 4 OBJECT GLOBAL DEFAULT 21 global_var
However, --strip-unneeded is smart enough to realise that a shared-object library doesn't need the .symtab section as well and remove it.
So, conclusions? --strip-all is safe on shared libraries, because global symbols remain in a separate section, but not on objects for inclusion in static libraries (relocatable objects). --strip-unneeded is safe for both, and automatically understands shared objects do not need any .symtab entries to function and removes them; effectively doing the same work as --strip-all. So, --strip-unneeded is essentially the only tool you need for standard stripping needs!
See also