oyvind
oyvind

Reputation: 1549

LD: Different ways to use ALIGN()

What is the difference between these?

mysection ALIGN(4): {...}

and

mysection: {. = ALIGN(4); ...}

and

. = ALIGN(4); 
mysection: {...}

Are the results the same?

Upvotes: 1

Views: 1186

Answers (2)

oyvind
oyvind

Reputation: 1549

I did my own experiment based on @Mike Kinghan's cases. The numbers don't quite line up with his cases, but test the same techniques, but using multiple memory regions.

Observations:

  1. Mike's case 1 (my case 2 and 3) fails to link at all.

  2. Mike's case 2 (my case 1) fails to align the variable bb in the expected way.

  3. Mike's case 3 (my case 5) successfully aligns the variable bb

  4. Using SUBALIGN (my case 4) correctly aligns the variable bb, but would also align every input section in that output section.

Case 1

$ cat bar.c
char aa __attribute__((section(".section_a"))) = 0;
char bb __attribute__((section(".section_b"))) = 0;

$ gcc -c bar.c

$ cat bar1.lds
MEMORY {
    FLASH (rx)  : ORIGIN = 0x00000001, LENGTH = 0x100000
    RAM   (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
}

SECTIONS
{
    . = 0x10004;
    . = ALIGN(8);
    .section_a : {
        *(.section_a)
    } > RAM
    _myvar = .;
    . = ALIGN(8);
    .section_b : {
        *(.section_b)
    } > FLASH
}

$ ld -T bar1.lds bar.o -o bar.out

$ readelf -s bar.out
Symbol table '.symtab' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000020000000     0 SECTION LOCAL  DEFAULT    1
     2: 0000000000000001     0 SECTION LOCAL  DEFAULT    2
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS bar.c
     5: 0000000000000001     1 OBJECT  GLOBAL DEFAULT    2 bb
     6: 0000000020000000     1 OBJECT  GLOBAL DEFAULT    1 aa
     7: 0000000020000001     0 NOTYPE  GLOBAL DEFAULT    1 _myvar

Case 2

$ cat bar2.lds
MEMORY {
    FLASH (rx)  : ORIGIN = 0x00000001, LENGTH = 0x100000
    RAM   (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
}

SECTIONS
{
    . = 0x10004;
    . = ALIGN(8);
    .section_a : {
        *(.section_a)
    } > RAM
    _myvar = .;
    .section_b ALIGN(8) : {
        *(.section_b)
    } > FLASH
}

$ ld -T bar2.lds bar.o -o bar.out
ld: address 0x20000009 of bar.out section `.section_b' is not within region `FLASH'
ld: address 0x20000009 of bar.out section `.section_b' is not within region `FLASH'

Case 3

$ cat bar3.lds
MEMORY {
    FLASH (rx)  : ORIGIN = 0x00000001, LENGTH = 0x100000
    RAM   (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
}

SECTIONS
{
    . = 0x10004;
    . = ALIGN(8);
    .section_a : {
        *(.section_a)
    } > FLASH
    _myvar = .;
    .section_b ALIGN(8) : {
        *(.section_b)
    } > RAM
}

$ ld -T bar3.lds bar.o -o bar.out
ld: address 0x9 of bar.out section `.section_b' is not within region `RAM'
ld: address 0x9 of bar.out section `.section_b' is not within region `RAM'

Case 4

$ cat bar4.lds
MEMORY {
    FLASH (rx)  : ORIGIN = 0x00000001, LENGTH = 0x100000
    RAM   (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
}

SECTIONS
{
    . = 0x10004;
    . = ALIGN(8);
    .section_a : {
        *(.section_a)
    } > RAM
    _myvar = .;
    .section_b : SUBALIGN(8){
        *(.section_b)
    } > FLASH
}

$ ld -T bar4.lds bar.o -o bar.out

$ readelf -s bar.out
Symbol table '.symtab' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000020000000     0 SECTION LOCAL  DEFAULT    1
     2: 0000000000000008     0 SECTION LOCAL  DEFAULT    2
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS bar.c
     5: 0000000000000008     1 OBJECT  GLOBAL DEFAULT    2 bb
     6: 0000000020000000     1 OBJECT  GLOBAL DEFAULT    1 aa
     7: 0000000020000001     0 NOTYPE  GLOBAL DEFAULT    1 _myvar

Case 5

$ cat bar5.lds
MEMORY {
    FLASH (rx)  : ORIGIN = 0x00000001, LENGTH = 0x100000
    RAM   (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000
}

SECTIONS
{
    . = 0x10004;
    . = ALIGN(8);
    .section_a : {
        *(.section_a)
    } > RAM
    _myvar = .;
    .section_b : {
        . = ALIGN(8);
        *(.section_b)
    } > FLASH
}

$ ld -T bar5.lds bar.o -o bar.out

$ readelf -s bar.out
Symbol table '.symtab' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000020000000     0 SECTION LOCAL  DEFAULT    1
     2: 0000000000000001     0 SECTION LOCAL  DEFAULT    2
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS bar.c
     5: 0000000000000008     1 OBJECT  GLOBAL DEFAULT    2 bb
     6: 0000000020000000     1 OBJECT  GLOBAL DEFAULT    1 aa
     7: 0000000020000001     0 NOTYPE  GLOBAL DEFAULT    1 _myvar

Upvotes: 0

Mike Kinghan
Mike Kinghan

Reputation: 61620

See:

$ cat foo.c
int mysym __attribute__((section(".mysection"))) = 42;

$ gcc -c foo.c

Case 1

$ cat foo_1.lds
SECTIONS
{
    . = 0x10004;
    .mysection ALIGN(8): {
        *(.mysection)
    }
}

$ ld -T foo_1.lds foo.o -o foo1.out
$ readelf -s foo1.out

Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000010008     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS foo.c
     4: 0000000000010008     4 OBJECT  GLOBAL DEFAULT    1 mysym

$ readelf -t foo1.out | grep -A3 '.mysection'
  [ 1] .mysection
       PROGBITS               PROGBITS         0000000000010008  0000000000010008  0
       0000000000000004 0000000000000000  0                 4
       [0000000000000003]: WRITE, ALLOC

Case 2

$ cat foo_2.lds
SECTIONS
{
    . = 0x10004;
    . = ALIGN(8);
    .mysection : {
        *(.mysection)
    }
}

$ ld -T foo_2.lds foo.o -o foo2.out
$ readelf -s foo2.out 

Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000010008     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS foo.c
     4: 0000000000010008     4 OBJECT  GLOBAL DEFAULT    1 mysym

$ readelf -t foo2.out | grep -A3 '.mysection'
  [ 1] .mysection
       PROGBITS               PROGBITS         0000000000010008  0000000000010008  0
       0000000000000004 0000000000000000  0                 4
       [0000000000000003]: WRITE, ALLOC

Case 3

$ cat foo_3.lds
SECTIONS
{
    . = 0x10004;
    .mysection : {
        . = ALIGN(8);
        *(.mysection)
    }
}

$ ld -T foo_3.lds foo.o -o foo3.out
$ readelf -s foo3.out 

Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000010004     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS foo.c
     4: 0000000000010008     4 OBJECT  GLOBAL DEFAULT    1 mysym

$ readelf -t foo3.out | grep -A3 '.mysection'
  [ 1] .mysection
       PROGBITS               PROGBITS         0000000000010004  0000000000010004  0
       0000000000000008 0000000000000000  0                 4
       [0000000000000003]: WRITE, ALLOC

So, Case 1 is equivalent to Case 2 . Both of them align .mysection to the next 8-byte boundary, 0x10008, after 0x10004, and mysym is at the same address.

But Case 3 does not align .mysection to 0x10008. It remains at 0x10004. Then the location counter is aligned to 0x10008 after the start of .mysection, and mysym is at that address.

In all cases the address of the first symbol in .mysection is 0x10008, but only in Case 1 and Case 2 is that the address of .mysection

Later

How is case 2 affected if I have multiple sections placed into different memory regions?

Whenever the script invokes:

. = ALIGN(N);

it simply sets the location counter to the next N-byte aligned boundary after its current position. That is all. So:

Case 4

$ cat bar.c
char aa __attribute__((section(".section_a"))) = 0;
char bb __attribute__((section(".section_b"))) = 0;

$ cat bar.lds 
SECTIONS
{
    . = 0x10004;
    . = ALIGN(8);
    .section_a : {
        *(.section_a)
    }
    . = 0x20004;
    .section_b : {
        *(.section_b)
    }
}

$ gcc -c bar.c
$ ld -T bar.lds bar.o -o bar.out

$ readelf -s bar.out

Symbol table '.symtab' contains 7 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000010008     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000020004     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS bar.c
     5: 0000000000020004     1 OBJECT  GLOBAL DEFAULT    2 bb
     6: 0000000000010008     1 OBJECT  GLOBAL DEFAULT    1 aa

$ readelf -t bar.out | egrep -A3 '(section_a|section_b)'
  [ 1] .section_a
       PROGBITS               PROGBITS         0000000000010008  0000000000010008  0
       0000000000000001 0000000000000000  0                 1
       [0000000000000003]: WRITE, ALLOC
  [ 2] .section_b
       PROGBITS               PROGBITS         0000000000020004  0000000000020004  0
       0000000000000001 0000000000000000  0                 1
       [0000000000000003]: WRITE, ALLOC

Here, . = ALIGN(8); has the effect that .section_a, and the first object within it, aa, are aligned to the first 8-byte boundary, 0x10008, after 0x10004. But . = 0x20004; moves the location counter to an address that happens not to be 8-byte aligned, so .section_b and its first object bb are not 8-byte aligned. Indeed, if we deleted . = 0x20004; then .section_b and the object bb would be placed right after aa, at 0x10009.

Upvotes: 1

Related Questions