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

Why do common C compilers include the source filename in the output?

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

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

为什么编译器包含此信息?

I have learnt from this recent answer that gcc includes the source filename somewhere in the binary as metadata, even when debugging is not enabled.

不完全。在现代 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
$

因此,为了保护您的隐私,删除可执行文件,或 compile/link 使用 -s

GCC 包含文件名的原因主要是为了调试目的,因为它允许程序员识别给定符号来自哪个源文件,如 ELF spec p1-17 and further expanded upon in some Oracle docs on linking.[=17 中(简洁地)概述的那样=]

使用 STT_FILE 部分的示例由 this SO question 给出。

我仍然很困惑,为什么即使您指定 -g0,GCC 和 Clang 仍然包含它,但您可以阻止它包含 STT_FILE-s。我找不到任何解释,也找不到 "official reason" 为什么 STT_FILE 包含在 ELF 规范中(非常 简洁)。