.symtab ELF符号表(转载)

2023-11-23 19:28
文章标签 elf 转载 符号表 symtab

本文主要是介绍.symtab ELF符号表(转载),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 符号表(symbol table)介绍

ELF文件中的“符号表(symbol table)”包含的是程序中的符号信息 – 这些符号代表的或许是定义(例如定义全局变量时使用的变量名,或者定义函数时使用的函数名),或许代表的是引用(例如使用关键字extern声明的变量或函数时使用的符号名称)。当代表的是定义时,在链接阶段链接器需要为它们重定位;当代表的是引用时,在链接阶段链接器需要在其他编译模块定位到该符号的定义。

符号表其实是所有符号信息的集合统称,即符号表是所有符号信息一起组成的一个数组,所以一个符号表索引(symbol table index) 对应该数组中的一个(符号表)表项。

其中,索引值0有双重含义:一般情况下代表的意思是指代符号表的第一个表项,然而一个未定义符号却也使用STN_UNDEF(数值为0)来指定其节头表索引值。

它在Section Headers中有独立的节:
在这里插入图片描述

2. 符号表表项的数据结构

/* Symbol table entry.  */typedef struct
{Elf32_Word    st_name;                /* Symbol name (string tbl index) */Elf32_Addr    st_value;               /* Symbol value */Elf32_Word    st_size;                /* Symbol size */unsigned char st_info;                /* Symbol type and binding */unsigned char st_other;               /* Symbol visibility */Elf32_Section st_shndx;               /* Section index */
} Elf32_Sym;typedef struct
{Elf64_Word    st_name;                /* Symbol name (string tbl index) */unsigned char st_info;                /* Symbol type and binding */unsigned char st_other;               /* Symbol visibility */Elf64_Section st_shndx;               /* Section index */Elf64_Addr    st_value;               /* Symbol value */Elf64_Xword   st_size;                /* Symbol size */
} Elf64_Sym;

如下为readelf解出来的文本信息(展示理解),与表项存储数据类型不一定一致,请注意!!!
在这里插入图片描述

2.1 st_name 符号名称(对应name)

st_name成员其实不是一个字符串,而是一个数值,代表的是目标文件中 字符串表 中的一个索引值, 那里才真正存储着该符号的名称对应的字符串。如果st_name成员数值不为0,则代表该符号有符号名称。否则,说明该符号没有名称。
**注意:**在C程序中的 具有外部链接属性的符号 的名称 和 最后生成的目标文件中的符号表中的符号名称 是相同的,这点与C++不同。

2.2 st_value 符号数值(对应Value)

st_value成员给出了相应的符号值。这个符号值具体是什么意思,是要依据上下文的(主要依据不同的符号属性和不同的目标文件),也许是个绝对值,也许是个地址值,等等。

2.2 Symbol Values

在不同的目标文件中,对成员st_value的意义解释也是不同的。
(1)在可重定位文件中,若符号的st_shndx等于SHN_COMMON,则st_value的值代表的是该符号的对齐字节数。
(2)在可重定位文件中,若一个符号是已定义的,那么st_value的值代表的是该符号其所在的节中的偏移量 – 当然了,这个节是由st_shndx指定的。
(3)在可执行文件和共行库中,一个已定义符号的st_value的值不再是一个节偏移量,而是一个虚拟地址,因为动态链接器需要知道符号的内存地址。 – 因为虚拟地址是与节无关的,所以这种情况下,我们不需要关心st_shndx的值。
综合以上三点可知,在不同的目标文件中st_value的值代表的含义不同。这样设计是有原因的:在静态链接阶段,链接器需要的是符号在文件中的位置信息,而在程序运行时,动态链接器需要的是却符号在内存中的位置信息。

2.3 st_size 符号大小(对应Size)

很多类型的符号都是有大小属性的。例如,一个数据对象的大小指的是它实际在目标文件中占的字节数。st_size成员如果是0的话,说明这个符号在目标文件中不占用任何字节数(例如common symbols)或者当前是未知大小的(例如undefined symbols)。

2.4 st_info 符号的类型 和 绑定属性(对应两项 Bind和Type)

成员st_info指定了符号的类型(低四位)和绑定属性(高四位)。不同的符号类型/符号绑定属性以及意义将在下文列出。下面的宏分别展现了如何操作成员st_info。通过st_info得到类型和绑定属性,以及如何通过类型和绑定属性而得到st_info。
在这里插入图片描述

2.4.1 Symbol Binding

一个符号的绑定属性决定了该符号在链接阶段的可见性以及链接时的处理方式。

例如全局符号和本地符号的链接可见性是不同的,而当出现同名的全局符号和弱符号时,链接器会做出相应的处理(这点可参考下文对全局符号和弱符号不同点的描述)。
在这里插入图片描述
注:
对于 static 类型的成员,其 bind 信息必然是 STB_LOCAL,函数的 type 是 STT_FUNC,变量的 type 是 STT_OBJECT
对于本文件引用的外部符号,该符号通常是 GLOBALSTT_NOTYPE,并且该符号所处于的节区的下标为特殊的 SHN_UNDEF,表明该符号是一个外部符号。

2.4.1.1 STB_LOCAL 本地符号

当一个符号的绑定属性是STB_LOCAL时,则表明该符号的链接属性是internal的,对其他目标文件来说是不可见的,即不可访问。所以不同的目标文件中的本地符号可以同名,它们彼此不会干扰对方。

2.4.1.2 STB_GLOBAL 全局符号

当一个符号的绑定属性是STB_GLOBAL时,则表明该符号的链接属性是external的,对其他目标文件来说是可见的,即可以访问。

2.4.1.3 STB_WEAK 弱符号

当一个符号的绑定属性是STB_WEAK时,则表明该符号是个弱符号,它和全局符号有类似的地方,即链接属性也是external的。但是链接器处理弱符号的优先级相对全局符号要低,即当全局符号和弱符号同名时,链接器最后使用全局符号而忽略弱符号。
全局符号和弱符号的区别主要在两个方面。
当链接器链接若干可重定位文件时,它是不允许具有STB_GLOBAL属性的符号以相同名字进行重复定义的。而如果一个已定义的全局符号存在,则即便另一个具有相同名字的弱符号存在也不会引起错误。链接器将认可全局符号的定义而忽略弱符号的定义。与此类似的,如果一个符号被放在COMMON块(就是说这个符号的st_shndx成员的值为SHN_COMMON),则一个同名的弱符号也不会引起错误。链接器同样认可放在COMMON块符号的定义而忽略其他的弱符号。


STB_GLOBAL > SHN_COMMON > STB_WEAK

在链接静态库的情况下:
(1)当链接器遇到一个未定义的全局符号(global symbol)时,链接器会去提取静态库,试图找到这个符号定义。在静态库中,这个符号可以是全局符号,也可以是弱符号。
(2)当链接器遇到一个未定义的弱符号(weak symbols)时,链接器是不会去提取静态库的,而是直接将该弱符号的值赋为0。(可以参考文章《Fun with weak symbols》。试验结果发现:如果引用了静态库中的非弱符号,那么即使链接器遇到了一个未定义的弱符号,依然会去静态库中解析符号)
注意: 弱符号在上述规则之外地方的行为是实现相关的。弱符号主要用于系统软件中,不推荐在应用程序中使用弱符号,因为在运行时,弱符号很容易被覆盖掉。

在符号表中,不同绑定属性的符号所在位置是不同的 – 所有的本地符号都被安放在符号表的前头,紧接着的才是全局符号和弱符号。前文提到过,一个符号表节对应的节头表项的节头表成员sh_info中的数值代表的是第一个绑定属性为非STB_LOCAL的符号的符号表索引值(即最后一个绑定属性为STB_LOCAL符号的符号表索引值加1)。

2.4.1.4 STB_LOOS through STB_HIOS

此包含范围内的值是为操作系统特定的语义保留的。

2.4.1.5 STB_LOPROC through STB_HIPROC

此包含范围内的值是为处理器特定的语义保留的。如果指定了含义,则处理器补充说明。

2.4.2 Symbol Types

一个符号的类型为该符号关联的实体进行分类。
在这里插入图片描述

2.4.2.1 STT_NOTYPE

当符号类型是STT_NOTYPE时,表明该符号未指定类型或者当前还不知道该符号的类型。

2.4.2.2 STT_OBJECT

当符号类型是STT_OBJECT时,表明该符号关联的实体是个数据对象,例如一个变量,数组等。

2.4.2.3 STT_FUNC

当符号类型是STT_FUNC时,表明该符号关联的实体是个函数或者其他的可执行代码。

2.4.2.4 STT_SECTION

当符号类型是STT_SECTION时,表明该符号关联的实体是个节。一般符号表中的一个符号是这个类型时,主要是用于重定位的目的,并且其绑定属性一般情况下是STB_LOCAL。

2.4.2.5 STT_FILE

通常情况下,当一个符号的类型是STT_FILE时,这个符号的名称就是该目标文件相关联的源文件的名称。这种类型的符号的绑定属性是STB_LOCAL的,与它相关的节的节头表索引值为SHN_ABS,并且如果在符号表中存在此种符号的话,那么其位置排在本地符号(STB_LOCAL)的前头。

2.4.2.6 STT_COMMON

当符号类型是STT_COMMON时,表明该符号是个公用块数据对象,并且这个公用块在目标文件中实际是未被分配空间的。

2.4.2.7 STT_TLS

当符号的类型是STT_TLS时,表明该符号对应变量存储在线程局部存储内。

2.5 st_other 符号的可见性(对应Vis)

st_other成员目前指定符号的可见性属性。不同的可见性属性值以及意义将在文章后续给出。下面的宏分别展示了在32位和64位机器上如何操作st_other。除了低两位,其余的位都为0并且没有意义。

2.5.1 Symbol Visibility

尽管我们可以在编译阶段(通过在source code中或者编译器选项指定符号的可见性)和静态链接阶段(通过export list文件)指定符号的可见性属性,但其实可见性属性控制的是一个符号在运行时的解析行为。
在这里插入图片描述

2.5.1.1 STV_DEFAULT

当符号的可见性是STV_DEFAULT时,那么该符号的可见性由符号的绑定属性决定。这类情况下,(可执行文件和共享库中的)全局符号和弱符号默认是外部可访问的,本地符号默认外部是无法被访问的。但是,可见性是STV_DEFAULT的全局符号和弱符号是可被覆盖的。什么意思?举个最典型的例子,共享库中的可见性值为STV_DEFAULTD的全局符号和弱符号是可被可执行文件中的同名符号覆盖的。

注意:一个具体的实现可能会限制对外可访问的全局符号和弱符号的数量。

2.5.1.2 STV_PROTECTED

当符号的可见性是STV_PROTECTED时,它是外部可见的,这点跟可见性是STV_DEFAULT的一样,但不同的是它是不可覆盖的。这样的符号在共享库中比较常见。不可覆盖意味着如果是在该符号所在的共享库中访问这个符号,那么就一定是访问的这个符号,尽管可执行文件中也会存在同样名字的符号也不会被覆盖掉。
规定绑定属性为STB_LOCAL的符号的可见性不可以是STV_PROTECTED。

2.5.1.3 STV_HIDDEN

当符号的可见性是STV_HIDDEN时,证明该符号是外部无法访问的。这个属性主要用来控制共享库对外接口的数量。需要注意的是,一个可见性为STV_HIDDEN的数据对象,如果能获取到该符号的地址,那么依然是可以访问或者修改该数据对象的。

在可重定位文件中,如果一个符号的可见性是STV_HIDDEN的话,那么在链接生成可执行文件或者共享库的过程中,该符号要么被删除,要么绑定属性变成STB_LOCAL。

2.6 st_shndx 符号(关联的节)的节头表索引值(对应Ndx)

每一个符号表项所代表的特定符号信息都是和一个特定的 “节” 相关联的,st_shndx成员代表的就是这个特定“节”的节头表索引(比如一个定义的全局变量global,那么符号global的属性st_shndx值应该就是.data节所对应的节头表索引;定义的函数foo,那么符号foo的属性st_shndx值应该就是.text节所对应的节头表索引)。部分符号的节头表索引会有特殊的含义。

如果这个成员的值是SHN_XINDEX时,证明该符号关联的节的节头表索引值过大,超出了st_shndx所能代表的最大数值。那么真正的节头表索引值存储在一个类型为SHT_SYMTAB_SHNDX的扩展节中。

这篇关于.symtab ELF符号表(转载)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/420195

相关文章

提问的智慧(转载)

此文让我受益良多。值得一读,大家如果也觉得不错就一起来推~~~   ---------------------------------      在黑客世界里,当提出一个技术问题时,你能得到怎样的回答?这取决于挖出答案的难度,同样取决于你提问的方法。本指南旨在帮助你提高发问技巧,以获取你最想要的答案。       首先你必须明白,黑客们只偏爱艰巨的任务,或者能激发他们

Struts2常用标签总结--转载

Struts2常用标签总结 一 介绍 1.Struts2的作用 Struts2标签库提供了主题、模板支持,极大地简化了视图页面的编写,而且,struts2的主题、模板都提供了很好的扩展性。实现了更好的代码复用。Struts2允许在页面中使用自定义组件,这完全能满足项目中页面显示复杂,多变的需求。 Struts2的标签库有一个巨大的改进之处,struts2标签库的标签不依赖于

【转载】ACM感悟

今天看了一篇我们学校前辈的ACM的感悟,觉得写的十分有道理,这里转载,文章还会不断的改进和更新。 原文链接:http://www.cnblogs.com/Chierush/p/3760870.html?ADUIN=1339764596&ADSESSION=1401536826&ADTAG=CLIENT.QQ.5329_.0&ADPUBNO=26349 声明:本文是写给弱校ACM新手的一点

SylixOS x86平台C++符号表

1.C++跨平台问题说明     在x86平台下编译C++工程过程后,运行编译好的C++共享库时出现符号表__atomic_fetch_sub_4找不到的问题,如图 1.1所示。

使用pyelftools把elf文件转换成s19文件

要使用pyelftools将ELF文件转换成S19文件格式,你需要首先安装pyelftools库,然后编写一个脚本来读取ELF文件,提取其中的代码和数据部分,并按照S19文件的格式生成对应的记录。 以下是一个简单的Python脚本示例,它演示了如何使用pyelftools将ELF文件转换为S19文件: import elftoolsfrom elftools.elf.elffile impo

转载 SPI的比喻理解

SPI 传输是一个虚拟的移位寄存器方式。 你这么理解就可以: 主机和从机之间有一条 16 格的传送带。主机一格一格拨动它转动(相当于发送时钟)。 如果是主机发送,它就把一个个的东西放在传送带上,转动 8 次,就传到从机一侧了。这时,从机可以从传送带上将东西取下。如果从机没有取东西,这些东西再转 8 次又回到主机一侧。 如果是主机接收,从机就要把 8 个东西一次放上传送带。当主机转动 8 次,东西就

转载:从小白鼠试毒问题-海明码

问题提出: 有1000瓶水,其中有一瓶有毒,小白鼠只要尝一点带毒的水24小时后就会死亡,至少要多少只小白鼠才能在24小时时鉴别出哪瓶水有毒? 问题分析: 需要多少只小白鼠?这个很容易想到是10只(二进制),但是如何鉴别哪一瓶水有毒?(即如何安排小白鼠?)原贴如下:https://blog.csdn.net/mengtnt/article/details/8477747 海明码计算: 转载

[转载]20本经典云计算书籍和内容简介

云计算 : 深刻改变未来 内容简介 · · · · · · 本书概述了云计算的起源、发展以及商业模式,介绍了云计算的关键技术、典型应用以及开源软件和社区。 云计算既是机遇也是挑战,中国科技何去何从?需要从国家层面重视云计算,在教育、普及、重点研发、示范工程等诸多领域对其进行统筹规划,从而推动云计算在中国的发展,并最终使云计算造福百姓,惠及国民经济,推动科

日系编曲:吉他贝斯识谱 吉他六线谱常见符号表 贝斯谱图例

认识吉他贝斯谱 吉他和贝斯谱是记录音乐的一种方式,对于学习和演奏这两种乐器的人来说非常重要。以下是对吉他和贝斯谱的认识: 一、吉他谱 六线谱: 这是最常见的吉他谱记谱方式。六线谱由六条平行的线组成,代表吉他的六根弦,从下往上依次是吉他的最细弦(1 弦)到最粗弦(6 弦)。 线上的数字表示手指应按在该弦的品格位置。例如,数字 “3” 表示在该弦的第 3 品格处按弦。 同时,六线

将自己的工程开源到GitHub---转载记录保存

1.1 工程中创建Module   最开始你可能自己写了个工程,感觉不错,进行了一定的封装和优化,想留作开发下一个App时用或者给别人用。但是每次复制粘贴代码显得繁琐,还要处理一堆的package name和import错误。于是你想着把它改造成独立的工程,每次整个工程复制进去,设置引用就可以了。这就要使用Android Studio的module了。以前,你的工程只有一个Module,就是(M