Depending on the compiler flags and the source code, the compiler may add alignment bytes to a compiled module (.o file). These bytes then end up in the final binary, see e.g. this SO question.
The following three options are theoretically possible to align a function inside a .o file:
(1) Alignment bytes before the function:
NOP(s)
function_start
...
function_end
(2) Alignment bytes inside a function
function_start
...
NOP(s)
...
function_end
(3) Alignment bytes after a function
function_start
...
function_end
NOP(s)
I have seen (2) and (3).
- Is is safe to assume that (1) is not done?
- In case of (1) or (3), is it possible that the linker adds or removes alignment bytes when linking/merging the .o files to create the final binary? Could link time optimisation be a special case?
CodePudding user response:
The compiler does (1). The assembly code emitted for a function is of the form
.align ...
function:
... code for the function ...
For the first function in each object file, this has no effect. For subsequent functions, it may have an effect. When you dump the code with objdump
, you'll find that the tool does not know when a function ends. It only knows when it begins. But a function begins after the padding for alignment is issued, so it ends up looking like the padding “belongs” to the previous function, when it's really issued for the following function.
When you link multiple object files together, the linker adds additional padding to bring each of the sections it pasted together up to its required alignment. This alignment requirement is the value of the highest valued .align
directive given in it (i.e. even the initial .align
directive for the first function matters).
CodePudding user response:
Is is safe to assume that (1) is not done?
Normally, the object file contains some information that the segment shall have some alignment (e.g. align to 16 bytes).
The linker will then add bytes (maybe NOP
or 0x00
) between the sections to ensure that the section is aligned correctly.
By inserting additional NOP
s you cannot achieve a "larger" alignment than the section's alignment: If the section is aligned to 16 bytes, you cannot align some code to 32 bytes by inserting NOP
s.
Therefore, the first byte in a section will always have the "best" alignment possible, and ...
Is is safe to assume that (1) is not done?
... adding NOP
s before the first function in the section only makes sense if you explicitly want to have the function "mis-aligned" (for example if the function shall be located at an address of the form 8*N 5
to ensure some instruction in the middle of the function is located at an 8-aligned address).
However, in such a case, a compiler would be allowed to add alignment bytes before a function.
(3) Alignment bytes after a function
Alignment bytes between two functions in the same section make sense.
Alignment bytes at the end of a section only make sense if there are restrictions on the size of the section (e.g. the section size must be a multiple of 16 or similar).
is it possible that the linker adds ... alignment bytes when linking
The linker normally even must add alignment bytes between the sections. But not inside a section.
is it possible that the linker ... removes alignment bytes when linking
Typically, the linker does not distinguish between alignment bytes and "useful" bytes. For this reason, it cannot remove alignment bytes.