Reputation: 1549
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
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:
Mike's case 1 (my case 2 and 3) fails to link at all.
Mike's case 2 (my case 1) fails to align the variable bb
in the expected way.
Mike's case 3 (my case 5) successfully aligns the variable bb
Using SUBALIGN
(my case 4) correctly aligns the variable bb
, but would also align every input section in that output section.
$ 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
$ 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'
$ 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'
$ 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
$ 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
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