ALIGN in Linker Scripts
Asked Answered
Z

5

27

What does the ALIGN keyword do in linker scripts? I read many tutorials about linker scripts but I cant understand what really ALIGN do. Can any one explain it simply. Thanks!

Zapateado answered 10/12, 2011 at 16:43 Comment(0)
P
37

A typical usage is

. = ALIGN(8);

This means: insert padding bytes until current location becomes aligned on 8-byte boundary. That is:

while ((current_location & 7) != 0)
  *current_location++ = padding_value;
Pharos answered 11/12, 2011 at 4:20 Comment(1)
Thanks for explaining it in such a simple fashion. For the life of me I couldn't find a place that explains it just that simpleExplode
R
7

The ALIGN() instructions tell the linker that section(bss, text) should be this much aligned.

For a typical idea, you can take a look here (4.6.3 "Output Section Description")

e.g.

    //.data is aligned by word size on the 32-bit architecture and direct it to the data section
For a 32-bit machine, it typically needs to be word aligned 

        .data : ALIGN(4) 
        {
           *(.data*)
        } > data_sdram
Rubble answered 14/9, 2018 at 9:43 Comment(0)
F
3

After some nasty behavior & unexpected results, here are my conclusions:

ALING(exp) works as expected only if exp is 2^ (power of 2) !!!

Some documentations shows this poorly, but some not at all!
https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_14.html

ALIGN will be eqivalent of

(. + exp - 1) & ~(exp - 1)   

As you can see, there is a & (AND) with a mask (exp-1) which will work only if exp is 2^ !!!

Let's take this example:

  .fini_array : {

    . = ALIGN(4);

    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);

    . = ALIGN(1024);

  } >FLASH  : FLASH_PHDR =0xDD

Here, the last ALIGN(1024) will make sure that (.) cursor (or next address that will be used) is aligned to 1024 bytes. To illustrate this, I used 0xDD to fill padding areas that linker will introduce in order to fulfill 1024 divisible topic.

Here are the results:

enter image description here

As you can see, linker just added 316 bytes (0xDD) after useful data as padding, in order that (.) next cursor to be aligned to 1024.

Next cursor (address) is 31744 which is divisible by 1024.

Let's take a wrong example (unexpected results):

  .fini_array : {

    . = ALIGN(4);

    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);

    . = ALIGN(13);

  } >FLASH  : FLASH_PHDR =0xDD

The next (.) cursor will NOT be aligned to 13 bytes as one my expect !!!

enter image description here

The next (.) address is 31439 which is obviously wrong (unexpected) because masking in equivalent formula above with something that is not a full mask.

Hope this clarifies things a little bit!

Fireeater answered 10/6, 2023 at 10:20 Comment(0)
S
2

. = ALIGN(8)

Corresponds to the following (working link script example using operators):

data = .;

. = ((data + 0x8 - 1) & ~(0x8 - 1)) - data;
Subscript answered 13/9, 2018 at 14:5 Comment(0)
S
2

There are two typical uses for ALIGN.

  • To align the start of a section to a required boundary

  • To pad a section to a required size.

      /* . = ALIGN(BEGIN) ;  equivalent to below, if VMA==LMA */
      .section : ALIGN(BEGIN) 
      {
        /* . = ALIGN(BEGIN) ; !!Not equivalent to above!! */
        ...
        . = ALIGN(END);
      }
    

The first ALIGN ensure the starting value is a multiple of BEGIN as a power of 2. The 2nd ALIGN will ensure that the size of a multiple of END. Normally you will want them to be equal and powers of two which indicate how many address bits are needed and can help with caching.

For instance copy loops can be optimized with large transfer sizes if the size is prohibited by the linker script to have fixed size multiples.

The ALIGN(BEGIN) inside the '.section' would result in some junk at the beginning of the sections. See: FILL() and =fill for ways to control what is written. See below on reason why not to use this; it actually does nothing.

Some example of structure that need to be aligned are,

  • a vector table
  • an mmu table
  • time critical routines that need cache fills
  • .bss and .initdata for initialization efficiency

The Gnu ld syntax allows you the ability to use ALIGN anywhere. If you were to custom code structures with BYTE, LONG, you might need to align tables/structures in a section. This is fairly obtuse use of a linker scripts, but is possible and an exception to the opening two uses. However, for most beginning to understand ld, that two uses are almost always the desired use.


Operation inside a section works as if all of the addresses are relative. So the start of the section is zero (and code commented not equivalent does not work due to this). As the last thing is . = ALIGN(...);, this sets the size of the section because it is zero based. This will even work if the start address of the section is not aligned.

Sanitarium answered 11/7, 2022 at 18:9 Comment(2)
For non-bare metal users with LMA==VMA, a lot of issues won't matter. However, the placement of the ALIGN will dictate as to what is being aligned. VMA is the execution address. LMA is the load address or position in a binary; startup code will copy one to the other. For non-bare metal, a loader sets up everything and may process an ELF file to place sections at appropriate addresses.Sanitarium
The accepted answer does not differentiate LMA,VMA nor inside a section versus outside a section. This is generally related to the behavior of '.' and not ALIGN() directly. However, 90+% of all uses of ALIGN() are to set the current location. It can be used with expressions directly (good luck with that).Sanitarium

© 2022 - 2024 — McMap. All rights reserved.