gcc .o / .obj模块中的函数对齐

gijlo24d  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(139)

根据编译器标志和源代码,编译器可能会在编译后的模块(.o文件)中添加对齐字节。这些字节随后会在最终的二进制文件中结束,例如,请参见this SO question
以下三个选项在理论上可以对齐.o文件中的函数:
(1)函数前的对齐字节:

NOP(s)
function_start
...
function_end

(2)函数内的对齐字节

function_start
...
NOP(s)
...
function_end

(3)函数后的对齐字节

function_start
...
function_end
NOP(s)

我看过(2)和(3)。

  • 是不是可以放心地假定(1)不做呢?
  • 在(1)或(3)的情况下,当链接/合并.o文件以创建最终的二进制文件时,链接器是否可能添加或删除对齐字节?链接时间优化是否是一个特殊情况?
wsewodh2

wsewodh21#

编译器执行(1)。为函数发出的汇编代码的形式为

.align ...
function:
    ... code for the function ...

对于每个目标文件中的第一个函数,这没有任何影响。对于后续函数,它可能会有影响。当您使用objdump转储代码时,您会发现该工具不知道函数何时结束。它只知道函数何时开始。但是函数在发出用于对齐的填充之后开始,因此它最终看起来像是填充“属于”前一个函数。当它真的为下面的函数发出时。
当您将多个目标文件链接在一起时,链接器会添加额外的填充,以使它粘贴在一起的每个部分达到其所需的对齐。此对齐要求是其中给定的最高值.align指令的值(即,即使是第一个函数的初始.align指令也很重要)。

t9eec4r0

t9eec4r02#

是不是可以放心地假定(1)不做呢?
通常,目标文件包含一些信息,即段应具有一些对齐(例如,对齐到16字节)。
然后,链接器将在节之间添加字节(可能是NOP0x00),以确保节正确对齐。
通过插入额外的NOP,您无法实现比截面对齐“更大”的对齐:如果区段对齐16个字节,您就无法借由插入NOP s来将某些程式码对齐32个字节。
因此,区段中的第一个字节将永远具有可能的“最佳”对齐,而且...
是不是可以放心地假定(1)不做呢?
...只有当您明确希望函数“未对齐”时(例如,如果函数应位于8*N+5形式的地址,以确保函数中间的某条指令位于8对齐的地址),才有意义在段中的第一个函数前添加NOP s。
然而,在这种情况下,将允许编译器在函数之前添加对齐字节。
(3)函数后的对齐字节
同一节中两个函数之间的对齐字节是有意义的。
仅当对节的大小有限制时(例如,节大小必须是16的倍数或类似值),节末尾的对齐字节才有意义。
链接器是否可能在链接时添加...对齐字节
通常,链接器甚至必须在节之间添加对齐字节,但不是在节内部。
链接器是否可能在链接时删除对齐字节
通常,链接器不区分对齐字节和“有用”字节。因此,它不能删除对齐字节。

相关问题