ELF的layout调整
汇编文件经过汇编的编码后生成二进制目标文件,将所需要的二进制目标文件链接生成最终的二进制可执行文件。
最简单链接的命令如下:
使用默认的链接脚本,不链接任何的库以及开始函数。链接器的使用请参考: https://lld.llvm.org/。
汇编文件中的段如何影响最终生成二进制内容的排布¶
从上面的讨论,同一个汇编文件中,同一个段中的内容在最终生成的二进制(后文中都用二进制表示二进制可执行文件)中是空间连续的。同一个汇编文件中不同名的段,以及不同汇编文件中的段的排布,由链接顺序和链接脚本确定的。
同个汇编文件中不同名的段:
- 当没有在链接脚本中指定段的位置,将按照段名的字典序排列
- 当在链接脚本中指定特定文件的特定段的顺序,指定的部分按照链接脚本指定的顺序排布
不同汇编文件中的段:
- 不在链接脚本中指定特定文件的特定段的顺序时(当前默认的链接脚本),不同汇编文件中段在二进制中的排布顺序遵从链接顺序。在链接命令中,一个文件被写在另一个文件的前面,在二进制中将被放在前面的位置
- 在链接脚本中指定特定文件的特定段的顺序,指定的部分按照链接脚本指定的顺序排布
因此对灵犀指令集来说,当前支持的一体块和分离块对于二进制的排布需求是不一样的: - 对于一体块来说,没有额外的块头和块体的排布操作 - 对于分离块来说,想要改变块头和微指令内容在二进制中的排布,需要: 1. 根据需要在汇编文件中进行段的区分。 2. 根据需要更改链接脚本对段进行排布。
下面介绍三种分离块形态下的二进制排布的方案。
方案一(ELF排布): 整个二进制中的块头在一片连续的区域,微指令在另一片连续的区域¶
- 在所有汇编文件中,将块头放在A段, 将微指令放在B段。
- 在链接脚本中,将A段放在输出段A-OUT中,将B段放在输出段B-OUT中。
特征:同文件的不同段不连续,不同文件的同名段连续,按照链接脚本排布。块头间相距最小,块头微指令间相距最大。
方案二(.o排布): 同一个汇编文件中的块头和微指令在一片连续的区域,另一个汇编文件中的块头和微指令在另一片连续的区域¶
- 在汇编文件中,将块头放在A段,将微指令放在B段。
- 在链接脚本中,按照同一个汇编文件中的A,B段按顺序放在同一个输出段AB-OUT中。
特征:同文件的不同段连续,不同文件间按照链接顺序排布。文件内部块头相距较小,块头微指令间相距较小。
方案三(函数排布): 同一个函数的块头和微指令在一片连续的区域,另一个函数的块头和微指令在另一片连续的区域¶
- 将函数A的块头放在A段,函数A的微指令放在A.body段。 将函数B的块头放在B段,函数B的微指令放在B.body段。其他函数按照同样的规则以此类推。
- 在链接脚本中,按照A, A.body, B,B.body的顺序将段放在同一个输出段AB-OUT中。
特征:同文件的不同段按照链接脚本中的顺序排布,不同文件间按照链接顺序排布。块头微指令相距最小。
不同方案间的比较如下表所示:
| 方案 | 文件间块头距离 | 文件内块头距离 | 函数内块头距离 | 块头微指令间距离 |
|---|---|---|---|---|
| 方案一 | 最小 | 最小 | 相等 | 最大 |
| 方案二 | 最大 | 最小 | 相等 | 小于方案一,大于方案三 |
| 方案三 | 大于方案一,小于方案二 | 最大 | 相等 | 最小 |
链接脚本的语法不在本文中做具体的解释。请参考 https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html
Function Alignment¶
灵犀指令集架构定义了块头和块体,为支持在链接阶段以方案三函数或方案二文件级别交替排布块头和块体,汇编需要保证每个函数的起始是8byte对齐。需要在每个块头前加上‘.align 3’对齐指令。
块头:
微指令: