linkerldtoolchainbinutilslinaro

Correct usage of strip tool


Unpacked Linaro GCC 6.2-2016.11 toolchain occupies almost 3.4 GB of disc space and I want to make it smaller. My target is armv7-a+vfpv3+hard_float so I have already removed things I do not need (like ld.gold, libraries for Thumb, v8-a, v7ve etc) but it still occupies almost 1 GB.

So I want to use strip tool to remove redundant information from its binaries.

My main question is how to use strip safety, correctly and efficiently in this case?

In general we have different binary files in toolchain to which we can apply strip: *.exe, *.a, *.o.

As I can judge I can apply strip -s (remove all symbols) only to *.exe files (i.g. arm-eabi-gcc.exe). Am I right?

Is it possible to apply strip to libraries (i.g. libgcc.a)? As I understood (see example above) symbols in libraries may be needed for further processing.

If yes, should I use --strip-debug instead (remove debugging symbols only)?

Example below illustrates these questions and reveals more.

Assume that we have three files:

// main.c:
#include "libgcc_test.h"
int main(void)
{
    do_something();
    return 0;
}

// libgcc_test.c:
void do_something(void)
{
    return;
}

// libgcc_test.h:
void do_something(void);

In general we just compile each file separately to get object files which can be linked together:

$ ./arm-eabi-gcc.exe main.c -c
$ ./arm-eabi-gcc.exe libgcc_test.c -c

By analyzing object files we can see that do_something symbol is defined in libgcc_test.o and undefined in main.o, as expected:

$ ./arm-eabi-nm.exe main.o
         U do_something
00000000 T main

$ ./arm-eabi-nm.exe libgcc_test.o
00000000 T do_something

If we apply strip -s to both files or only to main.o and try to link them, it works:

$ ./arm-eabi-nm.exe main.o
arm-eabi-nm.exe: main.o: no symbols
$ ./arm-eabi-nm.exe libgcc_test.o
arm-eabi-nm.exe: libgcc_test.o: no symbols
$ ./arm-eabi-ld.exe libgcc_test.o main.o -o main
arm-eabi-ld.exe: warning: cannot find entry symbol _start; defaulting to 00008000

But if we apply strip -s only to libgcc_test.o, linker produces error message:

$ ./arm-eabi-strip.exe -s libgcc_test.o
$ ./arm-eabi-ld.exe libgcc_test.o main.o -o main
arm-eabi-ld.exe: warning: cannot find entry symbol _start; defaulting to 00008000
main.o: In function `main':
main.c:(.text+0x8): undefined reference to `do_something' 

As I understand presence of unresolved symbol in an object file forces linker to resolve it. What happens if I remove this symbol from an object file before linking?

Is it correct and safe to remove symbols from object files before linking them together? If yes, which symbols can be removed?

In real project if we apply strip -s to toolchain libraries (libgcc.a, libc.a, libm.a, librdimon.a etc) it similarly produces a lot of "undefined reference to..." messages during linking stage.

But if we use --strip-debug option, linker produces messages for libraries like skipping incompatible libgcc.a when searching for -lgcc. If we revert libraries, it is linked successfuly.

What does skipping incompatible... message mean in this case?

Thank you for help.


Solution

  • Just to summarize how I did it. Maybe it will be useful for someone.

    I just removed unnecessary libraries/executables and applied strip -s to *.exe files only.

    After that all the toolchain appeared to be ~230 MB.