Suppose I have a function foo() in some C library and I am statically linking this library to some executable, but there is no call to this method from library or from the code within the executable. Will linker optimize the final executable by removing the function definition or will it still be the part of code? Is there any linker optimization which can turn on/off this behavior?
It should depend on your toolchain, however my gcc-7 does not include it.
You can easily test it with objdump
//foo.h
#pragma once
int foo(int x);
int foo2(int x);
//foo.c
#include "foo.h"
int foo(int x) {
return x * 2; //whatever
}
int foo2(int x) {
return x * 2; //whatever
}
//test.c
#include "foo.h"
int main() {
//foo(2);
return 0;
}
Build the static libary with
gcc -c foo.c
ar rcs libfoo.a foo.o
You can view the result with
objdump -j .text -S libfoo.a
It should look like this:
Disassembly of section .text:
0000000000000000 <foo>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 89 7d fc mov %edi,-0x4(%rbp)
7: 8b 45 fc mov -0x4(%rbp),%eax
a: 01 c0 add %eax,%eax
c: 5d pop %rbp
d: c3 retq
000000000000000e <foo2>:
e: 55 push %rbp
f: 48 89 e5 mov %rsp,%rbp
12: 89 7d fc mov %edi,-0x4(%rbp)
15: 8b 45 fc mov -0x4(%rbp),%eax
18: c1 e0 02 shl $0x2,%eax
1b: 5d pop %rbp
1c: c3 retq
However after building gcc test.c libfoo.a
it does not appear in the executable.
objdump -j .text -x a.out
SYMBOL TABLE:
00000000000004f0 l d .text 0000000000000000 .text
0000000000000520 l F .text 0000000000000000 deregister_tm_clones
0000000000000560 l F .text 0000000000000000 register_tm_clones
00000000000005b0 l F .text 0000000000000000 __do_global_dtors_aux
00000000000005f0 l F .text 0000000000000000 frame_dummy
0000000000000680 g F .text 0000000000000002 __libc_csu_fini
0000000000000610 g F .text 0000000000000065 __libc_csu_init
00000000000004f0 g F .text 000000000000002b _start
00000000000005fa g F .text 000000000000000b main
When you use the function in test.c, it will appear in the symbol-table. However if the library contains multiple functions, all will be included regardless of their usage.
SYMBOL TABLE:
00000000000004f0 l d .text 0000000000000000 .text
0000000000000520 l F .text 0000000000000000 deregister_tm_clones
0000000000000560 l F .text 0000000000000000 register_tm_clones
00000000000005b0 l F .text 0000000000000000 __do_global_dtors_aux
00000000000005f0 l F .text 0000000000000000 frame_dummy
00000000000006a0 g F .text 0000000000000002 __libc_csu_fini
000000000000061d g F .text 000000000000000f foo2
0000000000000630 g F .text 0000000000000065 __libc_csu_init
000000000000060f g F .text 000000000000000e foo
00000000000004f0 g F .text 000000000000002b _start
00000000000005fa g F .text 0000000000000015 main
You can solve this issue (on gcc) with compiler flags. (see https://gcc.gnu.org/onlinedocs/gnat_ugn/Compilation-options.html)
The idea is, that you build all object files with -ffunction-sections -fdata-sections, which causes the creation of a unique section for each function. (Normally they are all in the same .text)
gcc -c foo.c -ffunction-sections -fdata-sections
ar rcs libfoo.a foo.o
objdump -S libfoo.a
will show you this:
Disassembly of section .text.foo:
0000000000000000 <foo>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 89 7d fc mov %edi,-0x4(%rbp)
7: 8b 45 fc mov -0x4(%rbp),%eax
a: 01 c0 add %eax,%eax
c: 5d pop %rbp
d: c3 retq
Disassembly of section .text.foo2:
0000000000000000 <foo2>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 89 7d fc mov %edi,-0x4(%rbp)
7: 8b 45 fc mov -0x4(%rbp),%eax
a: c1 e0 02 shl $0x2,%eax
d: 5d pop %rbp
e: c3 retq
Using -Wl,--gc-sections will enable the garbage-collection in the linking-process, in which unused sections will be ignored/removed.
gcc test.c libfoo.a -Wl,--gc-sections
objdump -j .text -x a.out
will result in this:
SYMBOL TABLE:
00000000000004f0 l d .text 0000000000000000 .text
0000000000000520 l F .text 0000000000000000 deregister_tm_clones
0000000000000560 l F .text 0000000000000000 register_tm_clones
00000000000005b0 l F .text 0000000000000000 __do_global_dtors_aux
00000000000005f0 l F .text 0000000000000000 frame_dummy
0000000000000690 g F .text 0000000000000002 __libc_csu_fini
0000000000000620 g F .text 0000000000000065 __libc_csu_init
000000000000060f g F .text 000000000000000e foo
00000000000004f0 g F .text 000000000000002b _start
00000000000005fa g F .text 0000000000000015 main
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With