去除可执行文件中没用到的符号或函数
1.编译阶段使用:
-ffunction-sections
-fdata-sections
2.链接阶段使用:
-Wl,--gc-sections
在GCC,LD官方文档中如下讲解:
在GCC,LD官方文档中如下讲解:
-ffunction-sections
-fdata-sections
Place each function or data item into its own section in the outputfile if the target supports arbitrary sections. The name of thefunction or the name of the data item determines the section's namein the output file. Use these options on systems where the linkercan perform optimizations to improve locality of reference in theinstruction space. Most systems using the ELF object format andSPARC processors running Solaris 2 have linkers with suchoptimizations. AIX may have these optimizations in thefuture.
Only use these options when there are significant benefits fromdoing so. When you specify these options, the assembler and linkerwill create larger object and executable files and will also beslower. You will not be able to use gprof on all systems if youspecify this option and you may have problems with debugging if youspecify both this option and -g.
--gc-sections
--no-gc-sections
Enable garbage collection of unused input sections. It is ignoredon targets that do not support this option. The default behaviour(of not performing this garbage collection) can be restored byspecifying `--no-gc-sections' on the commandline.
`--gc-sections' decides which input sections are used by examiningsymbols and relocations. The section containing the entry symboland all sections containing symbols undefined on the command-linewill be kept, as will sections containing symbols referenced bydynamic objects. Note that when building shared libraries, thelinker must assume that any visible symbol is referenced. Once thisinitial set of sections has been determined, the linker recursivelymarks as used any section referenced by their relocations. See`--entry' and `--undefined'.
This option can be set when doing a partial link (enabled withoption `-r'). In this case the root of symbols kept must beexplicitly specified either by an `--entry' or `--undefined' optionor by a ENTRY command in the linker script.
因为GCC链接操作以section作为最小的处理单元,只要一个section中有某个符号被引用,该section就会被加入。
如果我们的某个.c程序中所有function都加入同一个section.则如果用到这个.c生成的.o的其中任何一个function.则必须将所有
function(符号)加入其中。如此,则使用-ffunction-sections和 -fdata-sections将每个符号创建为一个sections.sections名
与function,data名保持一致。
则在link阶段,-Wl,--gc-sections申明去掉不用的section。就可以去掉没用的function(符号)了。
验证如下:
#catmain.c
#include
int data_main[20];
extern int ff(void);
intfun(void)
{
return 0;
}
int main(void)
{
ff();
return 0;
}
#cat ff.c
#include
int data_ff[30];
int ff(void)
{
printf("ff\n");
return 0;
}
int jj(void)
{
printf("jj\n");
return 0;
}
int hh(void)
{
printf("hh\n");
return 0;
}
int gg(void)
{
printf("gg\n");
return 0;
}
1不去除无用符号
# gcc -c ff.c -off.o
# readelf -S ff.o
There are 11 section headers, starting at offset 0x11c:
Section Headers:
[Nr]Name Type Addr Off Size ES Flg Lk Inf Al
[0] NULL 00000000 000000 00000000 0 0 0
[ 1].text PROGBITS 00000000 000034 000064 00 AX 0 0 4
[ 2].rel.text REL 00000000 0003d4 00004008 9 1 4
[ 3].data PROGBITS 00000000 000098 000000 00 WA 0 0 4
[ 4].bss NOBITS 00000000 000098 000000 00 WA 0 0 4
[ 5].rodata PROGBITS 00000000 000098 00000c 00 A 0 0 1
[ 6].comment PROGBITS 00000000 0000a4 000024 01 MS 0 0 1
[ 7].note.GNU-stack PROGBITS 00000000 0000c8 00000000 0 0 1
[ 8].shstrtab STRTAB 00000000 0000c8 00005100 0 0 1
[ 9].symtab SYMTAB 00000000 0002d4 0000e010 10 8 4
[10].strtab STRTAB 00000000 0003b4 00001f00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S(strings)
I (info), L (link order), G (group), x(unknown)
O (extra OS processing required) o (OSspecific), p (processor specific)
# ls -lff.o
-rw-r--r-- 1 root root 1044 2011-12-06 23:20 ff.o
# gcc ff.o main.c -o main.elf
# nm -S main.elf
08049f20 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
0804852c 00000004 R _IO_stdin_used
w _Jv_RegisterClasses
08049f10 d __CTOR_END__
08049f0c d __CTOR_LIST__
08049f18 D __DTOR_END__
08049f14 d __DTOR_LIST__
0804853c r __FRAME_END__
08049f1c d __JCR_END__
08049f1c d __JCR_LIST__
0804a018 A __bss_start
0804a00c D __data_start
080484e0 t __do_global_ctors_aux
08048360 t __do_global_dtors_aux
0804a010 D __dso_handle
w __gmon_start__
080484da T __i686.get_pc_thunk.bx
08049f0c d __init_array_end
08049f0c d __init_array_start
08048470 00000005 T __libc_csu_fini
08048480 0000005a T __libc_csu_init
U
0804a018 A _edata
0804a0b8 A _end
0804850c T _fini
08048528 00000004 R _fp_hw
080482b8 T _init
08048330 T _start
0804a020 00000001 b completed.7021
0804a014 00000004 D data_a
0804a040 00000078 Bdata_ff
0804a00c W data_start
0804a024 00000004 b dtor_idx.7023
080483e4 00000019 T ff
080483c0 t frame_dummy
08048448 0000000a T fun
0804842f 00000019 T gg
08048416 00000019 T hh
080483fd 00000019 T jj
08048452 00000014 T main
U
2 去除无用符号
# gcc-ffunction-sections -fdata-sections -c ff.c -o ff.o
# readelf -S ff.o
There are 18 section headers, starting at offset 0x14c:
Section Headers:
[Nr]Name Type Addr Off Size ES Flg Lk Inf Al
[0] NULL 00000000 000000 00000000 0 0 0
[ 1].text PROGBITS 00000000 000034 000000 00 AX 0 0 4
[ 2].data PROGBITS 00000000 000034 000000 00 WA 0 0 4
[ 3].bss NOBITS 00000000 000034 000000 00 WA 0 0 4
[ 4].rodata PROGBITS 00000000 000034 00000c 00 A 0 0 1
[ 5].text.ff PROGBITS 00000000 000040 000019 00 AX 0 0 1
[ 6].rel.text.ff REL 00000000 00055c 00001008 16 5 4
[ 7].text.jj PROGBITS 00000000 000059 000019 00 AX 0 0 1
[ 8].rel.text.jj REL 00000000 00056c 00001008 16 7 4
[ 9].text.hh PROGBITS 00000000 000072 000019 00 AX 0 0 1
[10].rel.text.hh REL 00000000 00057c 00001008 16 9 4
[11].text.gg PROGBITS 00000000 00008b 000019 00 AX 0 0 1
[12].rel.text.gg REL 00000000 00058c 00001008 16 11 4
[13].comment PROGBITS 00000000 0000a4 000024 01 MS 0 0 1
[14].note.GNU-stack PROGBITS 00000000 0000c8 00000000 0 0 1
[15].shstrtab STRTAB 00000000 0000c8 00008100 0 0 1
[16].symtab SYMTAB 00000000 00041c 00012010 17 12 4
[17].strtab STRTAB 00000000 00053c 00001f00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S(strings)
I (info), L (link order), G (group), x(unknown)
O (extra OS processing required) o (OSspecific), p (processor specific)
# ls -lff.o
-rw-r--r-- 1 root root 1436 2011-12-06 23:15 ff.o
# gcc -Wl,--gc-sections ff.o main.c -o main.elf
# nm -S main.elf
08049f20 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080484b8 00000004 R _IO_stdin_used
w _Jv_RegisterClasses
08049f10 d __CTOR_END__
08049f0c d __CTOR_LIST__
08049f18 D __DTOR_END__
08049f14 d __DTOR_LIST__
080484c8 r __FRAME_END__
08049f1c d __JCR_END__
08049f1c d __JCR_LIST__
0804a00c A __bss_start
08048470 t __do_global_ctors_aux
08048340 t __do_global_dtors_aux
w __gmon_start__
0804846a T __i686.get_pc_thunk.bx
08049f0c d __init_array_end
08049f0c d __init_array_start
08048400 00000005 T __libc_csu_fini
08048410 0000005a T __libc_csu_init
U
0804a00c A _edata
0804a014 A _end
0804849c T _fini
08048298 T _init
08048310 T _start
0804a00c 00000001 b completed.7021
0804a010 00000004 b dtor_idx.7023
080483c3 00000019 T ff
080483a0 t frame_dummy
080483dc 0000000a T fun
080483e6 00000014 T main
U
绿色部分为两者的区别,仔细分析即可发现该编译选项的作用。
文章来源: blog.csdn.net,作者:悟空胆好小,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/xushx_bigbear/article/details/9410925
- 点赞
- 收藏
- 关注作者
评论(0)