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).
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).