在链接脚本中,ALIGN关键字的作用是什么?我读了很多关于链接脚本的教程,但是我不明白ALIGN到底是干什么的。有人能简单解释一下吗?谢谢!
在链接脚本中,ALIGN关键字的作用是什么?我读了很多关于链接脚本的教程,但是我不明白ALIGN到底是干什么的。有人能简单解释一下吗?谢谢!
典型用法是:
. = ALIGN(8);
这意味着:插入填充字节,直到当前位置对齐在8字节边界上。也就是说:
while ((current_location & 7) != 0)
*current_location++ = padding_value;
//.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
. = ALIGN(8)
对应以下(使用运算符的工作链接脚本示例):
data = .;
. = ((data + 0x8 - 1) & ~(0x8 - 1)) - data;
将一个部分的起始位置与所需的边界对齐
将一个部分填充到所需的大小。
/* . = ALIGN(BEGIN) ; 如果VMA==LMA,则等同于下面的代码 */
.section : ALIGN(BEGIN)
{
/* . = ALIGN(BEGIN) ; !!与上面的代码不等同!! */
...
. = ALIGN(END);
}
ALIGN(BEGIN)
会导致一些垃圾出现在节的开头。请参阅:FILL()
和=fill
以控制写入的内容。请参见下面的原因,不要使用它;它实际上什么也不做。.bss
和.initdata
Gnu ld语法允许您在任何地方使用ALIGN
。
如果您要使用BYTE
、LONG
自定义代码结构,可能需要在一个部分中对表格/结构进行对齐。这是链接器脚本的一种相当晦涩的用法,但是可以实现,并且是对前两种用法的例外情况。然而,对于大多数初学者来说,了解ld
,这两种用法几乎总是期望的用法。
. = ALIGN(...);
,所以它设置了部分的大小,因为它是基于零的。即使部分的起始地址没有对齐,这也能正常工作。ALIGN
的放置将决定正在对齐什么。VMA是执行地址。LMA是二进制文件中的加载地址或位置;启动代码将把一个复制到另一个。对于非裸机,加载器设置所有内容并可能处理ELF文件以将部分放置在适当的地址处。 - artless noiseALIGN()
有关。然而,90%以上的ALIGN()
使用都是用来设置当前位置的。它可以直接与表达式一起使用(祝你好运)。 - artless noise经过一些恶劣的行为和意外的结果,这是我的结论:
只有当exp是2的幂次方时,ALING(exp)才能按预期工作!!!
一些文档对此解释不清楚,而另一些则根本没有提到!
https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_14.html
ALIGN将等同于
(. + exp - 1) & ~(exp - 1)
如您所见,存在一个带有掩码 (exp-1) 的 & (AND) 仅当 exp 为 2^ 时才有效。
让我们来看这个例子:
.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
这里,最后的ALIGN(1024)将确保(.)光标(或下一个将使用的地址)与1024字节对齐。为了说明这一点,我使用了0xDD来填充链接器将引入的填充区域,以满足1024可整除的要求。
以下是结果:
如你所见,链接器只是在有用数据后面加了316个字节(0xDD)作为填充,以便使下一个光标对齐到1024。 .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