为什么常见的C编译器在输出中包含源文件名?

时间:2015-09-05 12:41:49

标签: gcc compilation clang compiler-optimization compiler-options

我从this recent answer了解到gccclang将二进制文件中的源文件名包含为元数据,即使未启用调试也是如此。

我真的不明白为什么这应该是一个好主意。除了微小的隐私风险之外,当一个人优化得到的二进制文件(-Os)的大小时也会发生这种情况,这看起来效率很低。

为什么编译器会包含这些信息?

2 个答案:

答案 0 :(得分:6)

GCC包含文件名的原因主要是出于调试目的,因为它允许程序员识别给定符号来自哪个源文件(简洁地)在ELF spec p1-17中概述,并进一步扩展到{ {3}}

使用STT_FILE部分的示例由some Oracle docs on linking提供。

我仍然感到困惑的是,即使你指定-g0,GCC和Clang仍会包含它,但你可以阻止STT_FILE-s。我找不到任何解释,也没有找到“官方理由”为什么STT_FILE包含在ELF规范中(非常简洁)。

答案 1 :(得分:5)

  

我从最近的回答中了解到,即使未启用调试,gcc也会将二进制文件中的源文件名包含为元数据。

不完全。在现代ELF目标文件中,文件名确实是FILE类型的符号:

$ readelf bignum.o    # Source bignum.c
[...]
Symbol table (.symtab) contains 36 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS bignum.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    8
     9: 00000000000003f0   172 FUNC    GLOBAL DEFAULT    1 add
    10: 00000000000004a0   104 FUNC    GLOBAL DEFAULT    1 copy

然而,一旦剥离,符号就消失了:

$ strip bignum.o
$ readelf -all bignum.o | grep bignum.c
$

为了保护您的隐私,删除可执行文件,或使用-s编译/链接。