AArch64重定位前缀

时间:2016-07-25 14:30:00

标签: assembly relocation

我注意到ARM 64位程序集的GNU asm relocation syntax。那些像#:abs_g0_nc::pg_hi21:这样的内容是什么?他们在哪里解释?他们是否有一种模式,或者他们是否在旅途中弥补?我在哪里可以了解更多信息?

1 个答案:

答案 0 :(得分:9)

简介

ELF64定义了两种类型的重定位条目,称为 REL RELA

typedef struct
{
    Elf64_Addr r_offset;    /* Address of reference */
    Elf64_Xword r_info;     /* Symbol index and type of relocation */
} Elf64_Rel;

typedef struct
{
    Elf64_Addr r_offset;    /* Address of reference */
    Elf64_Xword r_info;     /* Symbol index and type of relocation */
    Elf64_Sxword r_addend;  /* Constant part of expression */
} Elf64_Rela;

每个重定位条目的范围是为加载器(静态或动态)提供四条信息:

  • 要修补的指令的虚拟地址或偏移量。
    这由r_offset提供。

  • 访问过的符号的运行时地址。
    这由r_info的较高部分给出。

  • 名为addend的自定义值
    该值最终作为表达式中的操作数,用于计算将被写入修补指令的值 RELA条目在r_addend中具有此值,REL条目从重定位站点提取它。

  • 重定位类型 这决定了用于计算修补指令的值的表达式类型。它编码在r_info的下半部分。

重新定位

在重定位阶段,加载程序遍历所有重定位条目,并使用r_offset下半部分选择的公式写入每个r_info指定的位置,以计算要存储的值来自 addend (RELA的r_addend)和符号地址(可从r_info的上半部分获得)。

实际上,写入部分已被简化,与其他架构相反,其中指令的直接字段通常与用于编码操作的字段完全分开,在ARM中,立即值与其他编码信息混合。登记/> 所以加载器应该知道什么样的指令正在尝试重新定位,如果它是一个指令 1 ,而不是让它反汇编重定位站点,那么它是汇编器设置重定位类型根据指示。

每个重定位符号只能重新定位一个或两个编码等效的指令 在特定情况下,重定位本身甚至会改变指令的类型。

根据所选的重定位类型,在重定位期间计算的值compute被隐式扩展为64位,有符号或无符号。

AArch64重新安置

作为具有固定指令大小的ARM RISC架构,将全宽(即64位)立即加载到寄存器中并非易事,因为没有指令可以具有全宽度立即字段。

AArch64中的重定位也必须解决这个问题,它实际上是一个双重问题:首先,找到程序员打算使用的真正价值(这是问题的纯粹重定位部分);第二,找到一种方法将它放入寄存器,因为没有指令有64位立即字段。

使用组重定位解决了第二个问题,组中的每个重定位类型用于计算64位值的16位部分,因此在一个重定位类型中只能有四个组(范围从 G0 G3 )。

这个切成16位的符合movk(移动保持),movz(移动归零)和movn(逻辑上移动否定)。
其他说明(例如bbladrpadr等具有特别适合他们的重定位类型。

每当引用符号的给定指令只有一个明确的可能的重定位类型时,汇编器就可以生成相应的条目,而不需要程序员明确地指定它。

组重定位不适合此类别,它们的存在是为了让程序员具有一定的灵活性,因此通常是明确说明的。 在组中,重定位类型可以指定汇编程序是否必须执行溢出检查 G0 重定位,用于加载值的低16位,除非明确禁止,否则检查该值是否适合16位(有符号或无符号,具体取决于所使用的特定类型)。 对于 G1 也是如此,加载位31-16检查值是否适合32位 因此, G3 总是不检查,因为每个值都适合64位。

最后,重定位可用于将整数值加载到寄存器中。 实际上,符号的地址只不过是一个任意的整数常量 请注意,r_addend是64位宽。

1 如果r_offset指向数据部分中的某个站点,则计算出的值将在指定位置写为64位字。

重定位运算符

首先,一些参考文献:

  • 描述ELF64格式重定位类型的ARM文档是here,第4.6节

  • 测试AArch64程序集文件,可能包含GAS可用的所有重定位运算符here

约定

遵循ARM文档约定我们有:

  

S是要重新定位的符号的运行时地址   A是   加入搬迁。
  P是重定位站点的地址   (源自r_offset)。
  X是搬迁的结果   在应用任何屏蔽或位选择操作之前的操作   Page(expr)是表达式expr的页面地址,定义为   expr & ~0xFFF,即清除了低12位的expr。   GOT是   Global Offset Table的地址   GDAT(S+A)表示地址S + A的GOT中的64位条目。该   条目将在迁移时在运行时重新定位   R_AARCH64_GLOB_DAT(S + A)。
  G(expr)是GOT的地址   表达式expr的条目   Delta(S)解决了差异   在S的静态链接地址和执行地址之间   S。如果S是空符号(ELF符号索引0),则解析为   P的静态链接地址与执行之间的差异   地址P
  Indirect(expr)表示调用的结果   expr作为一项功能。
  [msb:lsb]是一个位掩码操作   表示值中位的选择,边界是包容性的。

为了紧凑,重定位名称缺少前缀R_AARCH64_

| X |≤2^ 16 的表达意图为 -2 ^16≤X< 2 ^ 16 注意右边严格的不平等 这是滥用符号,由格式化表格的约束调用。

群组重新定位

Operator    | Relocation name | Operation | Inst | Immediate | Check
------------+-----------------+-----------+------+-----------+----------
:abs_g0:    | MOVW_UABS_G0    | S + A     | movz | X[15:0]   | 0≤X≤2^16
------------+-----------------+-----------+------+-----------+----------
:abs_g0_nc: | MOVW_UABS_G0_NC | S + A     | movk | X[15:0]   | 
------------+-----------------+-----------+------+-----------+----------
:abs_g1:    | MOVW_UABS_G1    | S + A     | movz | X[31:16]  | 0≤X≤2^32
------------+-----------------+-----------+------+-----------+----------
:abs_g1_nc: | MOVW_UABS_G1_NC | S + A     | movk | X[31:16]  | 
------------+-----------------+-----------+------+-----------+----------
:abs_g2:    | MOVW_UABS_G2    | S + A     | movz | X[47:32]  | 0≤X≤2^48
------------+-----------------+-----------+------+-----------+----------
:abs_g2_nc: | MOVW_UABS_G2_NC | S + A     | movk | X[47:32]  | 
------------+-----------------+-----------+------+-----------+----------
:abs_g3:    | MOVW_UABS_G3    | S + A     | movk | X[64:48]  | 
            |                 |           | movz |           |
------------+-----------------+-----------+------+-----------+----------
:abs_g0_s:  | MOVW_SABS_G0    | S + A     | movz | X[15:0]   | |X|≤2^16
            |                 |           | movn |           |
------------+-----------------+-----------+------+-----------+----------
:abs_g1_s:  | MOVW_SABS_G1    | S + A     | movz | X[31:16]  | |X|≤2^32
            |                 |           | movn |           |
------------+-----------------+-----------+------+-----------+----------
:abs_g2_s:  | MOVW_SABS_G2    | S + A     | movz | X[47:32]  | |X|≤2^48
            |                 |           | movn |           |
------------+-----------------+-----------+------+-----------+----------

在表格中显示 ABS 版本,汇编程序可以拾取 PREL (PC亲属)或 GOTOFF (GOT亲属)版本取决于引用的符号和输出格式的类型。

此重定位运算符的典型用法是

Unsigned 64 bits                      Signed 64 bits   
movz    x1,#:abs_g3:u64               movz  x1,#:abs_g3_s:u64
movk    x1,#:abs_g2_nc:u64            movk  x1,#:abs_g2_nc:u64
movk    x1,#:abs_g1_nc:u64            movk  x1,#:abs_g1_nc:u64
movk    x1,#:abs_g0_nc:u64            movk  x1,#:abs_g0_nc:u64

通常使用一个检查操作符,即设置最高部分的操作符 这就是检查版本仅重定位movz的原因,而非检查版本重新定位movk(部分设置了寄存器)。
G3 重定位,因为它本质上没有检查,因为没有值可以超过64位。

签名版本以_s结尾,他们总是在检查 没有 G3 版本,因为如果使用64位值,则在值本身中指定了符号。
它们总是仅用于设置最高部分,因为符号仅在那里相关 它们总是在签名值中检查溢出,使值意义更小。
这些重定位会根据值的符号将指令类型更改为movnmovz,这有效符号会扩展该值。

也可以进行团体搬迁

PC-relative,19,21,33位地址

Operator    | Relocation name | Operation | Inst | Immediate | Check
------------+-----------------+-----------+------+-----------+----------
[implicit]  | LD_PREL_LO19    | S + A - P | ldr  | X[20:2]   | |X|≤2^20
------------+-----------------+-----------+------+-----------+----------
[implicit]  | LD_PREL_LO21    | S + A - P | adr  | X[20:0]   | |X|≤2^20
------------+-----------------+-----------+------+-----------+----------
[implicit]  | LD_PREL_LO21    | S + A - P | adr  | X[20:0]   | |X|≤2^20
------------+-----------------+-----------+------+-----------+----------
:pg_hi21:   | ADR_PREL_PG     | Page(S+A) | adrp | X[31:12]  | |X|≤2^32
            | _HI21           | - Page(P) |      |           |
------------+-----------------+-----------+------+-----------+----------
:pg_hi21_nc:| ADR_PREL_PG     | Page(S+A) | adrp | X[31:12]  | 
            | _HI21_NC        | - Page(P) |      |           |
------------+-----------------+-----------+------+-----------+----------
:lo12:      | ADD_ABS_LO12_NC | S + A     | add  | X[11:0]   | 
------------+-----------------+-----------+------+-----------+----------
:lo12:      | LDST8_ABS_LO12  | S + A     | ld   | X[11:0]   | 
            | _NC             |           | st   |           |
------------+-----------------+-----------+------+-----------+----------
:lo12:      | LDST16_ABS_LO12 | S + A     | ld   | X[11:1]   | 
            | _NC             |           | st   |           |
------------+-----------------+-----------+------+-----------+----------
:lo12:      | LDST32_ABS_LO12 | S + A     | ld   | X[11:2]   | 
            | _NC             |           | st   |           |
------------+-----------------+-----------+------+-----------+----------
:lo12:      | LDST64_ABS_LO12 | S + A     | prfm | X[11:3]   | 
            | _NC             |           |      |           |
------------+-----------------+-----------+------+-----------+----------
:lo12:      | LDST128_ABS     | S + A     | ?    | X[11:4]   | 
            | _LO12_NC        |           |      |           |

:lo12:更改含义取决于指令处理的数据大小(例如ldrb使用LDST8_ABS_LO12_NCldrh使用LDST16_ABS_LO12_NC。< / p>

这些重定位的GOT相对版本也存在,汇编器将拾取正确的版本。

控制流量重定位

Operator    | Relocation name | Operation | Inst | Immediate | Check
------------+-----------------+-----------+------+-----------+----------
[implicit]  | TSTBR14         | S + A - P | tbz  | X[15:2]   | |X|≤2^15
            |                 |           | tbnz |           |  
------------+-----------------+-----------+------+-----------+----------
[implicit]  | CONDBR19        | S + A - P | b.*  | X[20:2]   | |X|≤2^20
------------+-----------------+-----------+------+-----------+----------
[implicit]  | JUMP26          | S + A - P | b    | X[27:2]   | |X|≤2^27
------------+-----------------+-----------+------+-----------+----------
[implicit]  | CALL26          | S + A - P | bl   | X[27:2]   | |X|≤2^27
------------+-----------------+-----------+------+-----------+----------

后记

我无法找到官方文件 上表是根据GAS测试用例和ARM文档重建的,该文档解释了符合AArch64标准的ELF可用的重定位类型。

表格没有显示ARM文档中存在的所有重定位,因为大多数都是互补版本,由汇编程序自动获取。

带有示例的部分会很棒,但我没有ARM GAS 将来我可以扩展这个答案,包括汇编列表和重定位转储的例子。