Search code examples
assemblygccbuildlinkercompiler-optimization

Function alignment in .o / .obj modules


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?

Solution

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