在 gcc 中使用 `-fdata-sections` 和 `-ffunction-sections` 这两个选项的目的是什么?

lap*_*oge 4 c linux embedded gcc

正如手册页所说:

\n
\n

-ffunction-sections
\n-fdata-sections
\n\xc2\xa0\xc2\xa0
如果目标支持任意部分,则将每个函数或数据项放入 \n\xc2\xa0\xc2\xa0 输出文件中自己的部分中。\
n\xc2\xa0\xc2\xa0 函数的名称或数据项的名称决定
输出文件中节的名称。

\n
\n

编译此代码后:

\n
...\n\nint bss_var_1 = 0;\nint bss_var_2;\nint bss_var_3;\n\nint data_var_1 = 90;\nint data_var_2 = 47;\nint data_var_3[128] = {212};\n\nint foo() {\n    printf("hello, foo()\\n");\n}\n\nint func() {\n    printf("hello, func()\\n");\n}\n\nint main(void) {\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我有main.o进入了我的文件夹,然后列出了它的所有部分,它确实将每个函数和数据放入了自己的部分中,但是为什么开发人员需要这两个选项?(例如,完成工作的任何特殊用途)

\n
$ readelf build/main.o -S\nThere are 34 section headers, starting at offset 0xeb0:\n\nSection Headers:\n  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al\n  [ 0]                   NULL            00000000 000000 000000 00      0   0  0\n  [ 1] .text             PROGBITS        00000000 000034 000000 00  AX  0   0  2\n  [ 2] .data             PROGBITS        00000000 000034 000000 00  WA  0   0  1\n  [ 3] .bss              NOBITS          00000000 000034 000000 00  WA  0   0  1\n  [ 4] .bss.bss_var_1    NOBITS          00000000 000034 000004 00  WA  0   0  4\n  [ 5] .bss.bss_var_2    NOBITS          00000000 000034 000004 00  WA  0   0  4\n  [ 6] .bss.bss_var_3    NOBITS          00000000 000034 000004 00  WA  0   0  4\n  [ 7] .data.data_var_1  PROGBITS        00000000 000034 000004 00  WA  0   0  4\n  [ 8] .data.data_var_2  PROGBITS        00000000 000038 000004 00  WA  0   0  4\n  [ 9] .data.data_var_3  PROGBITS        00000000 00003c 000200 00  WA  0   0  4\n  [10] .rodata           PROGBITS        00000000 00023c 000047 00   A  0   0  4\n  [11] .text.foo         PROGBITS        00000000 000284 000014 00  AX  0   0  4\n  [12] .rel.text.foo     REL             00000000 000b78 000010 08   I 31  11  4\n  [13] .text.func        PROGBITS        00000000 000298 000014 00  AX  0   0  4\n  [14] .rel.text.func    REL             00000000 000b88 000010 08   I 31  13  4\n  [15] .text.main        PROGBITS        00000000 0002ac 000028 00  AX  0   0  4\n  [16] .rel.text.main    REL             00000000 000b98 000020 08   I 31  15  4\n\n  ...\n\n
Run Code Online (Sandbox Code Playgroud)\n

Arm*_*das 6

这允许链接器删除未使用的部分[来源]

从最终可执行文件中删除未使用的代码和数据的操作由链接器直接执行。

为了做到这一点,它必须使用使用以下选项编译的对象:-ffunction-sections -fdata-sections。

这些选项可用于 C 和 Ada 文件。他们将分别将每个函数或数据放置在生成的目标文件中的单独部分中。

一旦使用这些选项创建了对象和静态库,链接器就可以执行死代码消除。您可以通过将 -Wl,--gc-sections 选项设置为 gcc 命令或在 gnatmake 的 -largs 部分中来完成此操作。这将对从未引用的代码和数据执行垃圾收集。

此外, Haris 链接的标志的文档中提供了使用指南:

与链接器垃圾收集(链接器 --gc-sections 选项)一起,这些选项可能会导致更小的静态链接可执行文件(剥离后)。

在 ELF/DWARF 系统上,这些选项不会降低调试信息的质量。其他目标文件/调试信息格式可能存在问题。

仅当这样做可以带来显着好处时才使用这些选项。当您指定这些选项时,汇编器和链接器会创建更大的目标文件和可执行文件,并且速度也会变慢。这些选项会影响代码生成。它们阻止编译器和汇编器使用翻译单元内的相对位置进行优化,因为这些位置在链接时之前是未知的。这种优化的一个例子是放宽对短调用指令的调用。