LD:链接描述文件中的 ALIGN 与 SUBALIGN
LD: ALIGN vs SUBALIGN in linker scripts
它们有什么不同?
我读到 SUBALIGN() 以某种方式强制进行某种对齐。还有其他区别吗?
什么时候应该使用 ALIGN(),什么时候应该使用 SUBALIGN()?
SUBALIGN
是
专门用于调整 input 部分 within 输出部分的对齐方式。
举例说明:
$ cat one.c
char a_one __attribute__((section(".mysection"))) = 0;
char b_one __attribute__((section(".mysection"))) = 0;
$ cat two.c
char a_two __attribute__((section(".mysection"))) = 0;
char b_two __attribute__((section(".mysection"))) = 0;
$ gcc -c one.c two.c
案例一
$ cat foo_1.lds
SECTIONS
{
. = 0x10004;
.mysection ALIGN(8) : {
*(.mysection)
}
}
$ ld -T foo_1.lds one.o two.o -o foo1.out
$ readelf -s foo1.out
Symbol table '.symtab' contains 9 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 one.c
4: 0000000000000000 0 FILE LOCAL DEFAULT ABS two.c
5: 000000000001000b 1 OBJECT GLOBAL DEFAULT 1 b_two
6: 0000000000010008 1 OBJECT GLOBAL DEFAULT 1 a_one
7: 0000000000010009 1 OBJECT GLOBAL DEFAULT 1 b_one
8: 000000000001000a 1 OBJECT GLOBAL DEFAULT 1 a_two
$ readelf -t foo1.out | grep -A3 mysection
[ 1] .mysection
PROGBITS PROGBITS 0000000000010008 0000000000010008 0
0000000000000004 0000000000000000 0 1
[0000000000000003]: WRITE, ALLOC
这里,ALIGN(8)
将.mysection
对齐到下一个8字节边界,0x10008,
在 0x10004.
之后
来自输入部分 one.o(.mysection)
的 char
符号 a_one
位于 .mysection
的开头
在下一个字节后跟 b_two
,也来自输入部分 one.o(.mysection)
。在下一个字节,
是 a_two
,来自输入部分 two.o(.mysection)
,然后是 b_two
,也来自 two.o(.mysection)
。所有 4
来自所有输入部分 *(.mysection)
的对象只是从输出部分 .mysection
的开头端到端放置。
案例二
$ cat foo_2.lds
SECTIONS
{
. = 0x10004;
.mysection ALIGN(8) : SUBALIGN(16) {
*(.mysection)
}
}
$ ld -T foo_2.lds one.o two.o -o foo2.out
$ readelf -s foo2.out
Symbol table '.symtab' contains 9 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 one.c
4: 0000000000000000 0 FILE LOCAL DEFAULT ABS two.c
5: 0000000000010021 1 OBJECT GLOBAL DEFAULT 1 b_two
6: 0000000000010010 1 OBJECT GLOBAL DEFAULT 1 a_one
7: 0000000000010011 1 OBJECT GLOBAL DEFAULT 1 b_one
8: 0000000000010020 1 OBJECT GLOBAL DEFAULT 1 a_two
$ readelf -t foo2.out | grep -A3 mysection
[ 1] .mysection
PROGBITS PROGBITS 0000000000010008 0000000000010008 0
000000000000001a 0000000000000000 0 16
[0000000000000003]: WRITE, ALLOC
这次.mysection
的8字节对齐地址不变。但是
SUBALIGN(16)
的效果是符号 a_one
,来自输入
one.o(.mysection)
节位于 下一个 16 字节处
边界,0x10010,在.mysection
和符号b_one
之后,来自
相同 输入部分在下一个字节。但是符号 a_two
,来自输入部分
two.o(.mysection)
在下一个16字节边界,0x10020;和 b_two
,即将到来
也来自 two.o(.mysection)
,在那之后是 1 个字节。
它们有什么不同?
我读到 SUBALIGN() 以某种方式强制进行某种对齐。还有其他区别吗?
什么时候应该使用 ALIGN(),什么时候应该使用 SUBALIGN()?
SUBALIGN
是
专门用于调整 input 部分 within 输出部分的对齐方式。
举例说明:
$ cat one.c
char a_one __attribute__((section(".mysection"))) = 0;
char b_one __attribute__((section(".mysection"))) = 0;
$ cat two.c
char a_two __attribute__((section(".mysection"))) = 0;
char b_two __attribute__((section(".mysection"))) = 0;
$ gcc -c one.c two.c
案例一
$ cat foo_1.lds
SECTIONS
{
. = 0x10004;
.mysection ALIGN(8) : {
*(.mysection)
}
}
$ ld -T foo_1.lds one.o two.o -o foo1.out
$ readelf -s foo1.out
Symbol table '.symtab' contains 9 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 one.c
4: 0000000000000000 0 FILE LOCAL DEFAULT ABS two.c
5: 000000000001000b 1 OBJECT GLOBAL DEFAULT 1 b_two
6: 0000000000010008 1 OBJECT GLOBAL DEFAULT 1 a_one
7: 0000000000010009 1 OBJECT GLOBAL DEFAULT 1 b_one
8: 000000000001000a 1 OBJECT GLOBAL DEFAULT 1 a_two
$ readelf -t foo1.out | grep -A3 mysection
[ 1] .mysection
PROGBITS PROGBITS 0000000000010008 0000000000010008 0
0000000000000004 0000000000000000 0 1
[0000000000000003]: WRITE, ALLOC
这里,ALIGN(8)
将.mysection
对齐到下一个8字节边界,0x10008,
在 0x10004.
来自输入部分 one.o(.mysection)
的 char
符号 a_one
位于 .mysection
的开头
在下一个字节后跟 b_two
,也来自输入部分 one.o(.mysection)
。在下一个字节,
是 a_two
,来自输入部分 two.o(.mysection)
,然后是 b_two
,也来自 two.o(.mysection)
。所有 4
来自所有输入部分 *(.mysection)
的对象只是从输出部分 .mysection
的开头端到端放置。
案例二
$ cat foo_2.lds
SECTIONS
{
. = 0x10004;
.mysection ALIGN(8) : SUBALIGN(16) {
*(.mysection)
}
}
$ ld -T foo_2.lds one.o two.o -o foo2.out
$ readelf -s foo2.out
Symbol table '.symtab' contains 9 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 one.c
4: 0000000000000000 0 FILE LOCAL DEFAULT ABS two.c
5: 0000000000010021 1 OBJECT GLOBAL DEFAULT 1 b_two
6: 0000000000010010 1 OBJECT GLOBAL DEFAULT 1 a_one
7: 0000000000010011 1 OBJECT GLOBAL DEFAULT 1 b_one
8: 0000000000010020 1 OBJECT GLOBAL DEFAULT 1 a_two
$ readelf -t foo2.out | grep -A3 mysection
[ 1] .mysection
PROGBITS PROGBITS 0000000000010008 0000000000010008 0
000000000000001a 0000000000000000 0 16
[0000000000000003]: WRITE, ALLOC
这次.mysection
的8字节对齐地址不变。但是
SUBALIGN(16)
的效果是符号 a_one
,来自输入
one.o(.mysection)
节位于 下一个 16 字节处
边界,0x10010,在.mysection
和符号b_one
之后,来自
相同 输入部分在下一个字节。但是符号 a_two
,来自输入部分
two.o(.mysection)
在下一个16字节边界,0x10020;和 b_two
,即将到来
也来自 two.o(.mysection)
,在那之后是 1 个字节。