为什么常见的 C 编译器在输出中包含源文件名?
Why do common C compilers include the source filename in the output?
我从 了解到 gcc
和 clang
将源文件名作为元数据包含在二进制文件的某处,即使未启用调试也是如此。
我真的不明白为什么这是个好主意。除了微小的隐私风险外,当对生成的二进制文件 (-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 规范中(非常 简洁)。
我从 gcc
和 clang
将源文件名作为元数据包含在二进制文件的某处,即使未启用调试也是如此。
我真的不明白为什么这是个好主意。除了微小的隐私风险外,当对生成的二进制文件 (-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 规范中(非常 简洁)。