ELF文件系列第四篇ELF文件静态结构中的字符串表和符号表

默认字符串表
这节描述默认字符串表。字符串表中包含有若干个以’null’结尾的字符串。在ELF文件中,这些字符串通常是符号的名字或者节的名字。当ELF文件的其它部分需要引用某个字符串时,只需要提供该字符串在字符串表中的序号即可。
字符串表中的第一个字符串(序号为 0)永远是”null”,它用于表示一个空的名字或者没有名字。所以,字符串表的第一个字节是’null’。字符串表也可以是空的,不含有任何字符串,这时,节头中的 sh_size 成员必须是 0。
一个目标文件中可能有多个字符串表,其中一个称为“节名字表(.shstrtab)”,它包含所有节的名字。每一个节头的 sh_name 成员应该是一个索引值,它指向节名字表中的一个位置,从这个位置开始到接下来第一个’null’字符为止的这个字符串,正是这个节的名字。
下图展示了一张长度为 25 字节的字符串表。
ELF文件系列第四篇ELF文件静态结构中的字符串表和符号表
文章图片

字符串表序号示例
序号
0
1
7
11
16
24
字符串
null
name
Variable
able
able
null
上面列表中左边一列中的引用全都是合法的。从这个示例中可以看出,既可以引用一个完整定义的字符串,即出现在两个’null’字符之间的整个串,也可以引用它的一部分。由于需要以’null’结尾,所以当引用一个子字符串时,一定是引用长串中靠后的那部分。
符号表
目标文件中的“符号表(symbol table)”所包含的信息用于定位和重定位程序中的符号定义和引用。目标文件的其它部分通过一个符号在这个表中的索引值来使用该符号。索引值从 0 开始计数,但值为 0 的表项(即第一项)并没有实际的意义,它表示未定义的符号。这里用常量 STN_UNDEF 来表示未定义的符号。
一个符号表项的格式定义如下:
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
符号的名字。但它并不是一个字符串,而是一个指向字符串表的索引值,在字符串表中对应位置上的字符串就是该符号名字的实际文本。如果此值为非 0,它代表符号名在字符串表中的索引值。如果此值为 0,那么此符号无名字。
st_value
符号的值。这个值其实没有固定的类型,它可能代表一个数值,也可以是一个地址,具体是什么要看上下文,这样的设计是为了在各种类型的文件中更有效地访问数据。
  • 在重定位文件中,如果一个符号对应的节的索引值是SHN_COMMON,st_value 值是这个节内容的字节对齐数。
  • 在重定位文件中,如果一个符号是已定义的,那么它的 st_value 值是该符号的起始地址在其所在节中的偏移量,而其所在的节的索引由st_shndx 给出。
  • 在可执行文件和共享库文件中,st_value 不再是一个节内的偏移量,而是一个虚拟地址,直接指向符号所在的内存位置。这种情况下,st_shndx就不再需要了。
st_size
符号的大小。各种符号的大小各不相同,比如一个对象的大小就是它实际占用的字节数。如果一个符号的大小为 0 或者大小未知,则这个值为 0。
st_info
符号的类型和属性。st_info 由一系列的比特位构成,标识了“符号绑定(symbol binding)”、“符号类型(symbol type)”和“符号信息(symbol infomation)”三种属性。下面几个宏分别用于读取这三种属性值。
#define ELF32_ST_BIND(i) ((i)>>4) #define ELF32_ST_TYPE(i) ((i)&0xf) #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))

符号绑定 (Symbol Binding):符号绑定属性由 ELF32_ST_BIND 指定。
名字

解释说明
STB_LOCAL
0
表明本符号是一个本地符号。它只出现在本文件中,在本文件外该符号无效。所以在不同的文件中可以定义相同的符号名,它们之间不会互相影响。
STB_GLOBAL
1
本符号是一个全局符号。当有多个文件被连接在一起时,在所有文件中该符号都是可见的。
STB_WEAK
2
类似于全局符号,但是相对于 STB_GLOBAL,它们的优先级更低。
STB_LOPROC/STB_HIPROC
13/15
为特殊处理器保留的属性区间。
在符号表中,不同属性的符号所在位置也有不同,STB_LOCAL排在前面,全局符号(STB_GLOBAL/STB_WEAK)排在后面。
符号类型 (Symbol Types) :符号类型属性由 ELF32_ST_TYPE 指定。
名字


STT_NOTYPE
0
本符号类型未指定。
STT_OBJECT
1
本符号是一个数据对象,比如变量、数组等。
STT_FUNC
2
本符号是一个函数,或者其它的可执行代码。当另外一个目标文件引用一个共享目标文件中的函数符号时,连接编辑器为被引用符号自动创建一个连接表项。
STT_SECTION
3
本符号与一个节相关联,用于重定位,通常具有 STB_LOCAL 属性。
STT_FILE
4
本符号是一个文件符号,它具有 STB_LOCAL 属性,它的节索引值是SHN_ABS。在符号表中如果存在本类符号的话,它会出现在所有STB_LOCAL 类符号的前部。
STT_LOPROC/STT_HIPROC
13/15
这一区间的符号类型为特殊处理器保留。
st_other: 本数据成员目前暂未使用,在目标文件中一律赋值为0。
st_shndx:任何一个符号表项的定义都与某一个“节”相联系,因为符号是为节而定义,在节中被引用。本数据成员即指明了相关联的节。本数据成员是一个索引值,它指向相关联的节在节头表中的索引。在重定位过程中,节的位置会改变,本数据成员的值也随之改变,继续指向节的新位置。当本数据成员指向下面三种特殊的节索引值时,本符号具有如下特别的意义:
  • SHN_ABS:符号的值是绝对的,具有常量性,在重定位过程中,此值不需要改变。
  • SHN_COMMON:本符号所关联的是一个还没有分配的公共节,本符号的值规定了其内容的字节对齐规则,与 sh_addralign 相似。也就是说,连接器会为本符号分配存储空间,而且其起始地址是向 st_value 对齐的。本符号的值指明了要分配的字节数。
  • SHN_UNDEF:表明本符号在当前目标文件中未定义,在连接过程中,连接器会找到此符号被定义的文件,并把这些文件连接在一起。本文件中对该符号的引用会被连接到实际的定义上去。
符号表首项
符号表的第一项,即索引值为 STN_UNDEF(0)的这项,其内容与其它项不同,见下表。
名字
st_name
st_value
st_size
st_info
st_other
st_shndx

0
【ELF文件系列第四篇ELF文件静态结构中的字符串表和符号表】0
0
0
0
SHN_UNDEF
意义
无效名字

无效大小
无效类型

无对应节

    推荐阅读