这个问题may have been asked,但是我有一个玩具程序可以很好地说明这个问题。
使用gcc 4.9用gcc -g
进行编译时,所包含的调试符号(尤其是对于外部声明的全局变量而言)是预期的和熟悉的数量。切换到gcc 6.3时,所包含的调试符号数量似乎过多且多余。尝试使用以下标志:
-feliminate-unused-debug-symbols
-feliminate-unused-debug-types
-femit-struct-debug-baseonly
没有差异。这在使用非常大的代码库时会产生一个问题,该代码库会产生较大的库归档文件,而新的编译器与较旧的编译器相比,库的归档文件最终(文件大小)要大几个数量级。
a.c:
#include <stdlib.h>
#include <stdio.h>
#include "big.h"
int main (void) {
printf("%s\n", big_time);
return 0;
}
b.c:
#include "big.h"
char* big_time = "BIG_TIME";
char* big_mama = "BIG_MAMA";
c.c:
#include "big.h"
char* big_stuf = "BIG_STUF";
char* big_leee = "BIG_LEEE";
big.h:
#ifndef _BIG_H_
#define _BIG_H_
extern char* big_time;
extern char* big_mama;
extern char* big_stuf;
extern char* big_leee;
#endif // _BIG_H_
Makefile:
CC = gcc
CFLAGS = -g
CFLAGS += -feliminate-unused-debug-symbols
test: prog
@for i in a.o b.o c.o prog; \
do echo $$i; \
readelf --debug-dump $$i | grep big_; \
done
prog: a.o b.o c.o
gcc $(CFLAGS) -o $@ $^
clean:
@$(RM) a.o b.o c.o prog
$ make
gcc -g -feliminate-unused-debug-symbols -c -o a.o a.c
gcc -g -feliminate-unused-debug-symbols -c -o b.o b.c
gcc -g -feliminate-unused-debug-symbols -c -o c.o c.c
gcc -g -feliminate-unused-debug-symbols -o prog a.o b.o c.o
a.o
<a5> DW_AT_name : (indirect string, offset: 0xb4): big_time
0x000000b0 696e7400 6269675f 74696d65 00756e73 int.big_time.uns
b.o
<1e> DW_AT_name : (indirect string, offset: 0x9): big_time
<40> DW_AT_name : (indirect string, offset: 0x0): big_mama
0x00000000 6269675f 6d616d61 00626967 5f74696d big_mama.big_tim
c.o
<1e> DW_AT_name : (indirect string, offset: 0x9): big_stuf
<40> DW_AT_name : (indirect string, offset: 0x0): big_leee
0x00000000 6269675f 6c656565 00626967 5f737475 big_leee.big_stu
prog
<a5> DW_AT_name : (indirect string, offset: 0x95): big_time
<ce> DW_AT_name : (indirect string, offset: 0x95): big_time
<f0> DW_AT_name : (indirect string, offset: 0xd7): big_mama
<123> DW_AT_name : (indirect string, offset: 0xe9): big_stuf
<145> DW_AT_name : (indirect string, offset: 0xe0): big_leee
0x00000090 20696e74 00626967 5f74696d 6500756e int.big_time.un
0x000000d0 7a657479 70650062 69675f6d 616d6100 zetype.big_mama.
0x000000e0 6269675f 6c656565 00626967 5f737475 big_leee.big_stu
$ make
gcc -g -feliminate-unused-debug-symbols -c -o a.o a.c
gcc -g -feliminate-unused-debug-symbols -c -o b.o b.c
gcc -g -feliminate-unused-debug-symbols -c -o c.o c.c
gcc -g -feliminate-unused-debug-symbols -o prog a.o b.o c.o
a.o
<312> DW_AT_name : (indirect string, offset: 0x20e): big_time
<31d> DW_AT_name : (indirect string, offset: 0x1eb): big_mama
<328> DW_AT_name : (indirect string, offset: 0x286): big_stuf
<333> DW_AT_name : (indirect string, offset: 0x90): big_leee
0x00000090 6269675f 6c656565 006c6f6e 6720696e big_leee.long in
0x000001e0 74005f49 4f5f4649 4c450062 69675f6d t._IO_FILE.big_m
0x00000280 6636345f 74006269 675f7374 7566005f f64_t.big_stuf._
b.o
<1e> DW_AT_name : (indirect string, offset: 0x9): big_time
<36> DW_AT_name : (indirect string, offset: 0x0): big_mama
<41> DW_AT_name : (indirect string, offset: 0x12): big_stuf
<4c> DW_AT_name : (indirect string, offset: 0x1b): big_leee
0x00000000 6269675f 6d616d61 00626967 5f74696d big_mama.big_tim
0x00000010 65006269 675f7374 75660062 69675f6c e.big_stuf.big_l
c.o
<1e> DW_AT_name : (indirect string, offset: 0x9): big_time
<36> DW_AT_name : (indirect string, offset: 0x0): big_mama
<41> DW_AT_name : (indirect string, offset: 0x12): big_stuf
<4c> DW_AT_name : (indirect string, offset: 0x1b): big_leee
0x00000000 6269675f 6d616d61 00626967 5f74696d big_mama.big_tim
0x00000010 65006269 675f7374 75660062 69675f6c e.big_stuf.big_l
prog
<312> DW_AT_name : (indirect string, offset: 0x1d2): big_time
<31d> DW_AT_name : (indirect string, offset: 0x1af): big_mama
<328> DW_AT_name : (indirect string, offset: 0x245): big_stuf
<333> DW_AT_name : (indirect string, offset: 0x84): big_leee
<379> DW_AT_name : (indirect string, offset: 0x1d2): big_time
<391> DW_AT_name : (indirect string, offset: 0x1af): big_mama
<39c> DW_AT_name : (indirect string, offset: 0x245): big_stuf
<3a7> DW_AT_name : (indirect string, offset: 0x84): big_leee
<3f2> DW_AT_name : (indirect string, offset: 0x1d2): big_time
<40a> DW_AT_name : (indirect string, offset: 0x1af): big_mama
<415> DW_AT_name : (indirect string, offset: 0x245): big_stuf
<420> DW_AT_name : (indirect string, offset: 0x84): big_leee
0x00000080 656e6400 6269675f 6c656565 005f666c end.big_leee._fl
0x000001d0 73006269 675f7469 6d65002f 686f6d65 s.big_time./home
0x00000240 36345f74 00626967 5f737475 66005f49 64_t.big_stuf._I
gcc 4.9:
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.9.2-10+deb8u1' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --with-arch-32=i586 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.9.2 (Debian 4.9.2-10+deb8u1)
gcc 6.3:
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/6/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 6.3.0-18+deb9u1' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-6 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-6-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)
在两种情况下,最终prog
可执行文件中包含的符号都是每个目标文件中的符号的总和(正如预期的那样),因此我认为行为没有错。但是关键的区别在于每个目标文件。对于较旧的编译器,仅包含与模块相关的符号。在较新的版本中,即使在该模块中未使用或引用该变量,也可以获得每个外部声明的变量的每个符号。这对最终可执行文件的调试信息量具有乘积作用。
此玩具程序模仿的是正在使用的大型第三方SDK中看到的源代码结构。此问题的最终结果是图书馆档案文件比以前大了几个数量级。
-g
调试信息需要保留,因此不能排除该信息或使用strip
。使用-g1
确实可以将调试信息的数量降低到正常(或更小)数量,但是一旦有用的调试信息进入gdb
内,其代价就是。
Obi Wan Kenobi,请帮助我。你是我唯一的希望。