Oracle® Solaris 11.2 链接程序和库指南

退出打印视图

更新时间: 2014 年 7 月
 
 

重定位节

重定位是连接符号引用与符号定义的过程。例如,程序调用函数时,关联的调用指令必须在执行时将控制权转移到正确的目标地址。可重定位文件必须包含说明如何修改其节内容的信息。通过此信息,可执行文件和共享目标文件可包含进程的程序映像的正确信息。重定位项即是这些数据。

重定位项可具有以下结构。请参见 sys/elf.h

typedef struct {
        Elf32_Addr      r_offset;
        Elf32_Word      r_info;
} Elf32_Rel;

typedef struct {
        Elf32_Addr      r_offset;
        Elf32_Word      r_info;
        Elf32_Sword     r_addend;
} Elf32_Rela;

typedef struct {
        Elf64_Addr      r_offset;
        Elf64_Xword     r_info;
} Elf64_Rel;

typedef struct {
        Elf64_Addr      r_offset;
        Elf64_Xword     r_info;
        Elf64_Sxword    r_addend;
} Elf64_Rela;
r_offset

此成员指定应用重定位操作的位置。不同的目标文件对于此成员的解释会稍有不同。

对于可重定位文件,该值表示节偏移。重定位节说明如何修改文件中的其他节。重定位偏移会在第二节中指定一个存储单元。

对于可执行文件或共享目标文件,该值表示受重定位影响的存储单元的虚拟地址。此信息使重定位项对于运行时链接程序更为有用。

虽然为了使相关程序可以更有效地访问,不同目标文件的成员的解释会发生变化,但重定位类型的含义保持相同。

r_info

此成员指定必须对其进行重定位的符号表索引以及要应用的重定位类型。例如,调用指令的重定位项包含所调用的函数的符号表索引。如果索引是未定义的符号索引 STN_UNDEF,则重定位将使用零作为符号值。

重定位类型特定于处理器。重定位项的重定位类型或符号表索引是将 ELF32_R_TYPEELF32_R_SYM 分别应用于项的 r_info 成员所得的结果。

#define ELF32_R_SYM(info)             ((info)>>8)
#define ELF32_R_TYPE(info)            ((unsigned char)(info))
#define ELF32_R_INFO(sym, type)       (((sym)<<8)+(unsigned char)(type))

#define ELF64_R_SYM(info)             ((info)>>32)
#define ELF64_R_TYPE(info)            ((Elf64_Word)(info))
#define ELF64_R_INFO(sym, type)       (((Elf64_Xword)(sym)<<32)+ \
                                          (Elf64_Xword)(type))

对于 64 位 SPARC Elf64_Rela 结构,r_info 字段可进一步细分为 8 位类型标识符和 24 位类型相关数据字段。对于现有的重定位类型,数据字段为零。但是,新的重定位类型可能会使用数据位。

#define ELF64_R_TYPE_DATA(info)       (((Elf64_Xword)(info)<<32)>>40)
#define ELF64_R_TYPE_ID(info)         (((Elf64_Xword)(info)<<56)>>56)
#define ELF64_R_TYPE_INFO(data, type) (((Elf64_Xword)(data)<<8)+ \
                                          (Elf64_Xword)(type))
r_addend

此成员指定常量加数,用于计算将存储在可重定位字段中的值。

Rela 项包含显式加数。类型为 Rel 的项存储要修改的位置中的隐式加数。在所有情况下,加数和计算所得的结果使用相同的字节顺序。加数值的重定位项类型和解释由特定于平台的 ABI 定义。

SPARC

32 位 SPARC 使用 Elf32_Rela 重定位项。64 位 SPARC 使用 Elf64_Rela 重定位项。要重定位的字段的先前值被添加到 r_addend 成员中,用作重定位加数。

32 位 x86

32 位 x86 使用 Elf32_Rel 重定位项。要重定位的字段包含该加数。

64 位 x86

64 位 x86 使用 Elf64_Rela 重定位项。r_addend 成员用作重定位加数。忽略要重定位的字段的先前值。

重定位节可以引用其他两个节:符号表(由 sh_link 节头项标识)和要修改的节(由 sh_info 节头项标识)。中指定了这些关系。如果可重定位目标文件中存在重定位节,则需要 sh_info 项,但对于可执行文件和共享目标文件,该项是可选的。重定位偏移满足执行重定位的要求。

在所有情况下,r_offset 值都会指定受影响存储单元的第一个字节的偏移或虚拟地址。重定位类型可指定要更改的位以及计算这些位的值的方法。