Home > Net >  Discard theoretically used but technically unused function
Discard theoretically used but technically unused function

Time:11-22

Is it somehow possible to discard a function/symbol from an output file (.exe/.elf) even if it could be called?

Let's say, a third party library does something like this:

int lib_func_get(int c) {
   if (c < 5) {
       return foo();
   } else {
       return bar()
   }
}

And you know for sure, c is never < 5, then I would like to omit/remove foo() from my executable to reduce the binary size.

How can I do this? Maybe with the help of the linker script and discarding .text.foo?

GCC's linker has a similar section for this, /DISCARD/, but the linking fails because the function is used:

refers [symbol], which is defined in a discarded section

The background of my question is reducing the binary size of embedded applications, especially bootloaders, where you cannot recompile a third party library or the library is part of the toolchain (libgcc e.g.) and you don't want to modify and rebuild the whole toolchain.

I know, this is may be a hacky approach but I would like to do this.

CodePudding user response:

In cases where the issue is local the best approach would be to provide a compiler hint:

#define ASSUME(cond) do {      \
    if (!(cond))               \
      __builtin_unreachable(); \
  } while (0)

int lib_func_get(int c) {
   ASSUME(c >= 5);
   if (c < 5) {
       return foo();
   } else {
       return bar()
   }
}

This would drop both function definition and surrounding code.

Otherwise you can override the symbol at link time:

$ gcc tmp.c -Wl,--defsym=printf=0
$ objdump -d tmp.c | grep printf
113d:   e8 be ee ff ff          callq  0 <printf>

CodePudding user response:

Is it somehow possible to discard a function/symbol from an output file (.exe/.elf) even if it could be called?

No.

you know for sure, c is never < 5, then I would like to omit/remove foo() ... How can I do this?

So refactor the code and remove the call to foo().


Mark the symbol as weak and replace it with an implementation that calls abort, or if you are really brave, just returns. Similarly, you can use --wrap. For example:

objcopy --weak-symbols=foo the_lib_with_foo.o the_lib_with_weak_foo.o
echo 'void foo() { return; }' | gcc -xc - -o foo.o 
gcc foo.o the_lib_with_weak_foo.o -o the_exe.out
  • Related