gpt4 book ai didi

assembly - AArch64 重定位前缀

转载 作者:行者123 更新时间:2023-12-04 10:35:37 25 4
gpt4 key购买 nike

我注意到一个 GNU asm relocation syntax用于 ARM 64 位汇编。那些碎片是什么#:abs_g0_nc::pg_hi21: ?他们在哪里解释?他们是否有某种模式或他们是在旅途中编造的?我在哪里可以学到更多?

最佳答案

介绍

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 下半部分选择的公式从加数( r_addend 用于 RELA)和符号地址(可从 r_info 的上半部分获得)计算要存储的值。

    实际上写部分已经被简化,与其他架构相反,指令的立即数字段通常与用于编码操作的字节完全分开,在 ARM 中,立即数与其他编码信息混合。
    所以加载器应该知道什么样的指令试图重定位,如果它根本是一条指令1,但不是让它反汇编重定位的位置,而是根据指令设置重定位类型的汇编程序。

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

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

    AArch64 搬迁

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

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

    第二个问题是通过使用组重定位来解决的,组中的每个重定位类型都用于计算 64 位值的 16 位部分,因此一个组中只能有四种重定位类型(从 G0 到 G3)。

    这种切片为 16 位适合 movk (移动保持), movz (移动归零)和 movn (逻辑上否定)。
    其他说明,如 b , bl , adrp , adr等等,有一个特别适合他们的搬迁类型。

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

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

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

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

    搬迁运算符(operator)

    首先,一些引用:
  • 描述 ELF64 格式的重定位类型的 ARM 文档是 here , 第 4.6 节
  • 一个测试 AArch64 汇编文件,大概包含所有可用于 GAS 的重定位操作符是 here here

  • 公约

    遵循 ARM 文档约定,我们有:

    S is the runtime address of the symbol being relocated.
    A is the addend for the relocation.
    P is the address of the relocation site (derived from r_offset).
    X is the result of a relocation operation, before any masking or bit-selection operation is applied.
    Page(expr) is the page address of the expression expr, defined as expr & ~0xFFF, i.e. expr with the lower 12 bits cleared. GOT is the address of the Global Offset Table.
    GDAT(S+A) represents a 64-bit entry in the GOT for address S+A. The entry will be relocated at run time with relocation R_AARCH64_GLOB_DAT(S+A).
    G(expr) is the address of the GOT entry for the expression expr.
    Delta(S) resolves to the difference between the static link address of S and the execution address of S. If S is the null symbol (ELF symbol index 0), resolves to the difference between the static link address of P and the execution address of P.
    Indirect(expr) represents the result of calling expr as a function.
    [msb:lsb] is a bit-mask operation representing the selection of bits in a value, bounds are inclusive.



    运营商

    重定位名称缺少前缀 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 位值,则在值本身中指定了符号 if sully 。
    它们始终仅用于设置最高部分,因为符号仅在此处相关。
    他们总是检查有符号值的溢出是否使值的意义变小。
    这些重定位将指令的类型更改为 movnmovz基于值的符号,该符号有效地扩展了值。

    集团搬迁,也可

    PC 相关的 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 )。

    这些重定位的 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 测试用例和解释可用于 AArch64 兼容 ELF 的重定位类型的 ARM 文档重建的。

    这些表并未显示 ARM 文档中存在的所有重定位,因为它们中的大多数是补充版本,由汇编程序自动选取。

    带有示例的部分会很棒,但我没有 ARM GAS。
    将来,我可能会扩展此答案以包含程序集列表和重定位转储的示例。

    关于assembly - AArch64 重定位前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38570495/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com