ILD

ELF:String table、Symbol table与Relocation
作者:Herbert Yuan 邮箱:yuanjp89@163.com
发布时间:2017-6-17 站点:Inside Linux Development

前面介绍了section header table,通过这个表可以找到所有section的内容。这些内容根据section type和section name解释。同一个section type可能有多个section,因此section name也是section的识别之一,一些special sections的名字已经预定义好了,根据名字即可确定section的用途。

1 String table

在ELF中,字符串用来表示符号名和section name,这些字符串存储在字符串表section中。

c语言中的字符串常量存储在.rodata中,并不存储在字符串表中。

通常,有两个字符串表.shstrtab和.strtab,前者存储section name,后者存储符号名。前者的索引存储在ELF header中的e_shstrndx字段中。后者是通过section名字(.strtab)确定。

字符串在字符串表中是以null-terminated存储的。其它地方通过字符串在字符串表中的offset来引用字符串。字符串在字符串表中一个接一个存储。

\0

.

t

e

x

t

\0

.

d

a

t

a

\0








如上,".text"在字符串表中的offset为1。在section header table中,.text section条目的sh_name值为1。

第一个字符串的索引为0,为空字符串,根据上下文,0索引表示没有名字或者一个空名字。

空字符串表是允许的,在section header中,sh_size为0,空字符串表的非0索引是非法的。

字符串表的最后一个字节必须是'\0'。

索引子字符串是允许的。如上,如果索引为2,那字符串就是"text"。

字符串没有被其它地方引用也是允许的。

2 Symbol table

符号表包括但不限于c语言中的符号,文件名等也可以存储在符号表中。符号表中的每个符号条目有固定的大小,用下述结构体表示。

1
2
3
4
5
6
7
8
typedef struct {
    Elf32_Word     st_name;
    Elf32_Addr     st_value;
    Elf32_Word     st_size;
    unsigned char     st_info;
    unsigned char     st_other;
    Elf32_Half     st_shndx;
} Elf32_Sym;

st_name,符号的名字,存储的是名字在符号字符串表中的索引。

st_value,相关符号的值,这个值不是c语言中变量的值,变量的值是存储在数据段中的。根据上下文,这个值表示绝对值、地址等。

st_size,这个表示符号的大小,对于c语言中的变量,表示的是存储大小,如int变量,这个值就是sizeof(int)。0表示没有大小或者未知大小。

st_info,指定符号的类型和绑定属性。高4位存储绑定属性,低4位存储类型。

st_other,当前未定义,应当为0。

st_shndx,存储section header index,有些index有特殊的含义,可能并不在section header table中。

符号表的第一个条目(index 0)被保留,所有字符段为0

2.1 Symbol binding

存储在st_info的高4位,相关类型如下:

Name

Value

STB_LOCAL

0

STB_GOBAL

1

STB_WEAK

2

STB_LOPROC

13

STB_HIPROC

15

STB_LOCAL,本地符号,在目标文件之外不可见,多个文件可以有同名的本地符号,互不干扰。

STB_GLOBAL,全局符号,对所有要结合的目标文件可见,一个文件定义的全局符号满足其他文件对全局符号未定义的引用。

STB_WEAK,弱符号,类似全局符号,但是他们的定义有低的优先级。

在符号表中,LOCAL符号排在最前面。

在c语言中,static修饰的符号为LOCAL符号。全局变量、函数为GLOBAL符号,

2.2 Symbol type

存储在st_info的低4位,相关类型如下:

Name

Value

STT_NOTYPE

0

STT_OBJECT

1

STT_FUNC

2

STT_SECTION

3

STT_FILE

4

STT_LOPROC

13

STT_HIPROC

15

STT_NOTYPE,符号类型未指定。

STT_OBJECT,数据对象,如变量数组等。

STT_FUNC,函数或其他可执行代码。

STT_SECTION,符号和section相关,主要用于重定向,具有LOCAL绑定。

STT_FILE,通常就是文件名,具有LOCAL绑定,section索引为ABS,在其它LOCAL符号之前。

2.3 Symbol section index

存储在st_shndx中,如果符号存储在一个section中,则为这个section的索引。如,全局函数存储在.text中,则函数名符号的sh_ndx的值为.text的section index。

有些符号的section index有特殊的section index,表示特殊的含义,如下:

SHN_ABS,符号有绝对值,不受重定向改变。目前还只看到FILE类型有ABS索引。

SHN_COMMON,符号label了一个未分配的公共块,由链接器负责分配,最典型的的是弱定义符号的section index为COMMON,弱定义符号最终由链接器负责选择一个定义。st_value值给出对齐要求。

SHN_UNDEF,未定义符号,由链接器从其它目标文件选择一个定义。从readelf的结果来看,未定义符号的类型为NOTYPE。

2.4 Symbol value

根据不同的目标文件类型,有些许不同的解释。

在可重定向文件中,SHN_CONNON索引的符号,给出了对齐要求。

可重定向文件中,如果st_shndx指向了一个存在的section,则给出了符号在section中的偏移。也就是说st_value给出了符号在内存中的位置。

在可执行文件和共享目标文件中,st_value是一个虚拟地址。这样做是为了使这些符号对动态链接器更有用,将section偏移替换为虚拟地址。

3 Relocation

重定向是将符号引用和符号定义关联的过程。由于目标文件可能包含外部引用,而共享库可能加载到不同的地址,重定向是必须的。有两种不同类型的重定向,分别用如下结构体表示。

1
2
3
4
5
6
7
8
9
10
typedef struct elf32_rel {
  Elf32_Addr  r_offset;
  Elf32_Word  r_info;
} Elf32_Rel;
 
typedef struct elf32_rela{
  Elf32_Addr  r_offset;
  Elf32_Word  r_info;
  Elf32_Sword r_addend;
} Elf32_Rela;

r_offset,给出重定向操作的位置。在可重定向目标文件中,r_offset存储section offset。在可执行文件和共享目标文件中,r_offset存储一个虚拟地址。

r_info,低8位给出重定向类型,由于重定向要修改机器指令,所以重定向的类型是和处理器架构相关的。高24位给出符号表索引,表示重定向的符号。

r_addend,指定一个常量,这个常量加到重定向的计算中。

重定向section引用两个其它section:符号表section和要修改的section。这两个section是通过section header中的sh_info和sh_link成员指定的。

Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.