ZHCADC4A September 2011 – March 2014
重定位类型在两个表中进行了说明。表 13-5 提供了重定位类型的数值,并汇总了重定位值的计算。此表之后描述了重定位类型及其使用示例。表 13-6 描述了每种类型的确切计算,包括重定位字段的提取和插入、溢出检查以及任何缩放或其他调整。
表 13-5 中使用了以下表示法。
S | 与重定位关联的符号的值,由重定位条目的 r_info 字段中包含的符号表索引指定。 |
A | 用于计算可重定位字段的值的加数。对于 ELF32_rel 重定位,A 根据表 13-6 编码到可重定位字段中。对于 Elf32_Rela 重定位,A 由重定位条目的 r_addend 字段提供。 |
PC | 包含字段的容器的地址。 |
FP(x) | 包含地址 x 处指令的取指数据包的地址;即:FP(x) := x & 0xFFFFFFE0。 |
P | 被重定位的指令的取指数据包地址;即:P := FP(PC)。 |
B | 当前加载模块的数据段的基址。此位置由符号 _ _C6000_DSBT_BASE 标记,在执行程序时是 DP 寄存器的值。 |
GOT(S) | 重定位相关符号 (S) 的全局偏移表 (GOT) 条目的地址。 |
TBR(x) | x 相对于线程局部存储 (TLS) 块基址的偏移量。有关线程局部存储的详细信息,请参阅Chapter7。 |
TPR(x) | x 相对于线程指针 (TP) 的偏移量。 |
TLS(x) | x 的 TLS 描述符,其中包含 x 的模块 ID 和 TBR 偏移量。 |
TLSMOD(x) | 定义 x 的模块的 TLS 模块标识符。 |
名称 | 值 | 运算 | 约束条件 |
---|---|---|---|
R_C6000_NONE | 0 | ||
R_C6000_ABS32 | 1 | S + A | |
R_C6000_ABS16 | 2 | S + A | |
R_C6000_ABS8 | 3 | S + A | |
R_C6000_PCR_S21 | 4 | S + A – P | |
R_C6000_PCR_S12 | 5 | S + A – P | |
R_C6000_PCR_S10 | 6 | S + A – P | |
R_C6000_PCR_S7 | 7 | S + A – P | |
R_C6000_ABS_S16 | 8 | S + A | |
R_C6000_ABS_L16 | 9 | S + A | |
R_C6000_ABS_H16 | 10 | S + A | 仅限 Rela |
R_C6000_SBR_U15_B | 11 | S + A – B | |
R_C6000_SBR_U15_H | 12 | S + A – B | |
R_C6000_SBR_U15_W | 13 | S + A – B | |
R_C6000_SBR_S16 | 14 | S + A – B | |
R_C6000_SBR_L16_B | 15 | S + A – B | |
R_C6000_SBR_L16_H | 16 | S + A – B | |
R_C6000_SBR_L16_W | 17 | S + A – B | |
R_C6000_SBR_H16_B | 18 | S + A – B | 仅限 Rela |
R_C6000_SBR_H16_H | 19 | S + A – B | 仅限 Rela |
R_C6000_SBR_H16_W | 20 | S + A – B | 仅限 Rela |
R_C6000_SBR_GOT_U15_W | 21 | GOT(S) + A – B | |
R_C6000_SBR_GOT_L16_W | 22 | GOT(S) + A – B | |
R_C6000_SBR_GOT_H16_W | 23 | GOT(S) + A – B | 仅限 Rela |
R_C6000_DSBT_INDEX | 24 | 此静态链路单元的 DSBT 索引 | |
R_C6000_PREL31 | 25 | S + A – PC | |
R_C6000_COPY | 26 | 被抢占符号的加载时副本 | 仅限 ET_EXEC |
R_C6000_JUMP_SLOT | 27 | S + A | ET_EXEC/ET_DYN |
R_C6000_EHTYPE | 28 | S + A - B | |
R_C6000_PCR_H16 | 29 | S - FP(P - A) | 仅限 Rela |
R_C6000_PCR_L16 | 30 | S - FP(P - A) | 仅限 Rela |
保留 | 31 | ||
保留 | 32 | ||
R_C6000_TBR_U15_B | 33 | TBR(S) | 仅限静态 |
R_C6000_TBR_U15_H | 34 | TBR(S) | 仅限静态 |
R_C6000_TBR_U15_W | 35 | TBR(S) | 仅限静态 |
R_C6000_TBR_U15_D | 36 | TBR(S) | 仅限静态 |
R_C6000_TPR_S16 | 37 | TBR(S) | |
R_C6000_TPR_U15_B | 38 | TPR(S) | |
R_C6000_TPR_U15_H | 39 | TPR(S) | |
R_C6000_TPR_U15_W | 40 | TPR(S) | |
R_C6000_TPR_U15_D | 41 | TPR(S) | |
R_C6000_TPR_U32_B | 42 | TPR(S) | 仅限动态 |
R_C6000_TPR_U32_H | 43 | TPR(S) | 仅限动态 |
R_C6000_TPR_U32_W | 44 | TPR(S) | 仅限动态 |
R_C6000_TPR_U32_D | 45 | TPR(S) | 仅限动态 |
R_C6000_SBR_GOT_U15_W_TLSMOD | 46 | GOT(TLSMOD(S)) + A – B | 仅限静态 |
R_C6000_SBR_GOT_U15_W_TBR | 47 | GOT(TBR(S)) + A - B | 仅限静态 |
R_C6000_SBR_GOT_U15_W_TPR_B | 48 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_U15_W_TPR_H | 49 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_U15_W_TPR_W | 50 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_U15_W_TPR_D | 51 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_L16_W_TLSMOD | 52 | GOT(TLSMOD(S)) + A - B | 仅限静态 |
R_C6000_SBR_GOT_L16_W_TBR | 53 | GOT(TBR(S)) + A - B | 仅限静态 |
R_C6000_SBR_GOT_L16_W_TPR_B | 54 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_L16_W_TPR_H | 55 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_L16_W_TPR_W | 56 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_L16_W_TPR_D | 57 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_H16_W_TLSMOD | 58 | GOT(TLSMOD(S)) + A - B | 仅限静态 |
R_C6000_SBR_GOT_H16_W_TBR | 59 | GOT(TBR(S)) + A - B | 仅限静态 |
R_C6000_SBR_GOT_H16_W_TPR_B | 60 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_H16_W_TPR_H | 61 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_H16_W_TPR_W | 62 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_SBR_GOT_H16_W_TPR_D | 63 | GOT(TPR(S))+A-B | 仅限静态 |
R_C6000_TLSMOD | 64 | TLSMOD(S) | 仅限动态 |
R_C6000_TBR_U32 | 65 | TBR(S) | 仅限动态 |
R_C6000_ALIGN | 253 | 无 | 仅限 ET_REL |
R_C6000_FPHEAD | 254 | 无 | 仅限 ET_REL |
R_C6000_NOCMP | 255 | 无 | 仅限 ET_REL |
R_none 重定位不执行任何运算。它用于创建一个段对另一段的引用,以确保如果引用段链接进来,被引用的段也会链接进来。
R_C6000_ABS8/16/32 重定位直接将符号的重定位地址编码为 8 位、16 位或 32 位字段,这些字段通常用于初始化数据,而非指令。字段的符号未指定;也就是说,这些字段既可用于有符号值,也可用于无符号值。
.field X,32 ; R_C6000_ABS32
.field X,16 ; R_C6000_ABS16
.field X,8 ; R_C6000_ABS8
PCR 重定位对有符号的 PC 相对分支位移进行编码。这些位移缩放为 32 位(字)单元。位移是相对于源指令的取指数据包计算的。
B func ; R_C6000_PCR_S21
CALLP func,B3 ; R_C6000_PCR_S21
BNOP func ; R_C6000_PCR_S12
BPOS func,A10 ; R_C6000_PCR_S10
BDEC func,A1 ; R_C6000_PCR_S10
ADDKPC func,B3,4 ; R_C6000_PCR_S7
名称中包含 L16 的重定位对 32 位地址或偏移量的低 16 位进行编码。包含 H16 的重定位对高 16 位进行编码,并且始终为 Rela。包含 S16 的重定位对有符号的 16 位值(通常不是地址的一部分)进行编码。包含 U15 的重定位对无符号的 15 位 DP 相对位移进行编码。
MVHL sym,A0 ; R_C6000_ABS_L16
MVKH sym,A0 ; R_C6000_ABS_H16
MVK const16,A0 ; R_C6000_ABS_S16 sign extend const16 into A0
MVKLH const16,A0 ; R_C6000_ABS_L16 move const16 into A0[16:31]
PCR_L16 和 PCR_H16 重定位分别对目标地址与参考 PC(“基础 PC”)的取指数据包地址之间的 PC 相对偏移量的低位和高位进行编码。从当前指令的取指数据包到基础 PC 的偏移量编码到加数字段中;即 A := (P-base)。重定位随后计算 S-FP(P-A),得出 S 与 FP(base) 之间的偏移量。这些重定位用于使用 PC 相对寻址来寻址不同段中的对象,如节 5.1所述。
MVK $PCR_OFFSET(sym,base),A0 ; R_C6000_PCR_L16
MVKH $PCR_OFFSET(sym,base),A0 ; R_C6000_PCR_H16
SBR_U15 重定位对 15 位无符号 DP 相对偏移量进行编码,以实现 near DP 数据寻址。重定位根据访问宽度进行缩放:32 位字 (_W)、16 位半字 (_H) 或字节 (_B)。
LDB *+DP(sym),A1 ; R_C6000_SBR_U15_B
ADDAB DP,sym,A2 ; R_C6000_SBR_U15_B
LDH *+DP(sym),A1 ; R_C6000_SBR_U15_H
ADDAH DP,sym,A2 ; R_C6000_SBR_U15_H
LDW *+DP(sym),A1 ; R_C6000_SBR_U15_W
ADDAW DP,sym,A2 ; R_C6000_SBR_U15_W
其他 SBR 重定位用于对 32 位 DP 相对偏移量的高位和低位部分进行编码,以实现 far DP 相对寻址。在以下示例中:
MVK (sym - $bss),A0 ; R_C6000_SBR_S16
MVKL $DPR_byte(sym),A0 ; R_C6000_SBR_L16_B
MVKH $DPR_byte(sym),A0 ; R_C6000_SBR_H16_B
MVKL $DPR_hword(sym),A0 ; R_C6000_SBR_L16_H
MVKH $DPR_hword(sym),A0 ; R_C6000_SBR_H16_H
MVKL $DPR_word(sym),A0 ; R_C6000_SBR_L16_W
MVKH $DPR_word(sym),A0 ; R_C6000_SBR_H16_W
SBR_GOT 重定位对应于与 SBR 重定位相同的指令和编码,但引用的是被引用符号(而非符号本身)的 DP 相对 GOT 地址。通常,GOT 通过 near DP 相对寻址访问,因此使用 R_C6000_DBR_GOT_U15_W。当 GOT 为 far 时,偏移量通过包含其他两个重定位的 MVKL/MVKH 生成(请参阅节 6.6)。在以下示例中,
LDW *+DP[GOT(sym)],A0 ; R_C6000_SBR_GOT_U15_W
MVKL $DPR_GOT(sym), A0 ; R_C6000_SBR_GOT_L16_W
MVKH $DPR_GOT(sym), A0 ; R_C6000_SBR_GOT_H16_W
R_C6000_DSBT_INDEX 将索引编码到当前加载模块的数据段基表中。它仅存在于使用 DSBT 模型实现位置无关性的文件中。请参阅节 6.7。
LDW *+DP($DSBT_INDEX(__C6000_DSBT_BASE)),DP ; R_C6000_DSBT_INDEX
R_C6000_COPY 用于标记可执行文件中定义的重复符号,该可执行文件抢占库定义,符合节 15.9中所述的“作为自有导入”约定。加载此可执行文件时,动态加载器必须将库定义中的任何初始值复制到可执行文件的初始值。此重定位类型仅存在于可执行文件 (ET_EXEC) 的动态重定位表中。
R_6000_JUMP_SLOT 用于标记引用导入函数且仅从 PLT 条目引用的 GOT 条目,因此应遵循节 15.6所述的延迟绑定。R_C6000_JUMP_SLOT 重定位仅发生在可执行文件和共享对象中,并且仅在动态重定位表的 DT_JMPREL 段中。
R_C6000_PREL31 用于对异常处理表中的代码地址进行编码。R_C6000_EHTYPE 用于对异常处理表中的 typeinfo 地址进行编码。请参阅节 11.2。
值为 33 到 65 的重定位用于线程局部存储 (TLS)。这些重定位包括 R_C6000_TBR_*、R_C6000_TPR_*、R_C6000_SBR_GOT_*_W_T*、R_C6000_TLSMOD 和 R_C6000_TBR_U32 重定位。有关线程局部存储的详细信息,请参阅Chapter7。节 7.5提供了使用这些 TLS 重定位的示例。
R_C6000_ALIGN 和 R_C6000_FPHEAD 用作 C64+ 压缩器的标记。它们在 ABI 下无效。将可重定位文件 (ET_REL) 组合到其他可重定位文件的下游工具(例如部分链接)应保留这些文件,或使用 R_C6000_NOCMP 标记它们所在的段。
R_C6000_NOCMP 将段标记为不可压缩。