.symtab ELF符号表(转载)

news2024/9/29 13:32:29

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的扩展节中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1242435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探索网络模型与协议:从OSI到HTTPs的原理解析

一、OSI网络模型 OSI(Open Systems Interconnection)七层网络参考模型和TCP/IP四层模型都是用于理解和设计计算机网络的框架,但它们之间存在一些差异。 1、七层 vs 四层 OSI七层网络参考模型: 物理层(Physical Laye…

博士研究生不会编程,也没有使用过Python,是否很失败

首先,对于博士研究生来说,虽然在学习和科研的过程中会涉猎到大量的专业知识,但是同样也会错过很多知识,对于非计算机相关专业的博士研究生来说,没有使用过Python,或者说编程能力比较弱也是比较正常的情况&a…

Linux CentOS+宝塔面板工具结合内网穿透实现网站发布至公网可访问

使用Typecho搭建个人博客网站,并内网穿透实现公网访问 文章目录 使用Typecho搭建个人博客网站,并内网穿透实现公网访问前言1. 安装环境2. 下载Typecho3. 创建站点4. 访问Typecho5. 安装cpolar6. 远程访问Typecho7. 固定远程访问地址8. 配置typecho 前言 …

「快学Docker」监控和日志记录容器的健康和性能

「快学Docker」监控和日志记录容器的健康和性能 1. 容器健康状态监控2. 性能监控3. 日志记录几种采集架构图 4. 监控工具和平台cAdvisor(Container Advisor)PrometheusGrafana 5. 自动化运维 1. 容器健康状态监控 方法1:需要实时监测容器的运…

医学检验(LIS)源码,实现检验结果审核自动化、检验无纸化、双向通讯

医学检验(LIS)管理系统 随着全自动生化分析仪、全自动免疫分析仪和全自动血球计数器等仪器的使用,检验科的大多数项目实现了全自动化分析。全自动化分析引入后,组合化验增多,更好的满足了临床需要,也使检验科的工作量和检验数据成…

centos7中通过minikube安装Kubernetes

minikube是一款开源的Kubernetes集群管理器,它可以帮助您在本地计算机上轻松部署和管理Kubernetes集群。以下是minikube的安装和使用步骤: 安装Docker:如果您还没有安装Docker,可以从Docker官方网站上下载并安装适合您操作系统的…

YOLOv5改进: Inner-IoU基于辅助边框的IoU损失,高效结合 GIoU, DIoU, CIoU,SIoU 等 | 2023.11

💡💡💡本文独家改进:Inner-IoU引入尺度因子 ratio 控制辅助边框的尺度大小用于计算损失,并与现有的基于 IoU ( GIoU, DIoU, CIoU,SIoU )损失进行有效结合 推荐指数:5颗星 新颖指数:5颗星 💡💡💡Yolov5/Yolov7魔术师,独家首发创新(原创),适用于…

Android和iOS应用程序加固方法详解:混淆、加壳、数据加密、动态加载和数字签名实现

目录 Android和iOS应用程序加固方法详解:混淆、加壳、数据加密、动态加载和数字签名实现 APP 加固方式 iOS APP加固代码实现 打开要处理的IPA文件 设置签名使用的证书和描述文件 开始ios ipa重签名 APP 加固方式 iOSAPP 加固是优化 iOS安全性的一种方法&…

三十分钟学会Shell(下)

Shell 3.1 运算符 3.1.1 算数运算符 在Shell脚本中,算术运算符用于执行基本的数学运算。Shell支持多种算术运算符,包括加、减、乘、除等。以下是关于Shell算术运算符的一些方法以及相应的示例说明: 加法: a10 b20 c$((a b)) …

Android WorldWind加载shapefile格式文件形成三维效果

目录 1 前言2 实现思路3 绘制Polygons4 读取shapefile文件5 加载立体模型6 问题1 前言 在项目中有时会加载shapefile格式的数据,要形成三维立体效果。但是查看worldwind NASA官网,在worldwind android的使用教程中并没用加载shapefile格式的教程,然后源码中也没有开发加载s…

windows事件查看器日志

Windows 事件查看器(Event Viewer)是 Windows 操作系统提供的一个内置工具,它用于管理和查看系统、应用程序和安全事件日志。在 Windows 系统中,各种活动和错误都会被记录到事件日志中,包括系统启动、应用程序崩溃、安…

永久免费!N个excel表一键合并成一个表(excel表格合并技巧)

您是否还在用手工复制粘贴来将多个EXCEL或表的数据合并到一个表里?那就太麻烦,效率太低了,用金鸣表格文字识别的“表格合并”功能,可免费将N个excel文件或N个excel表一键合并到一个表里面,而且这个功能永久免费&#x…

栈回溯--在栈里挑出返回地址

GNU Arm Embedded Toolchain project files : GNU Arm Embedded Toolchain arm-none-eabi-addr2line -e F103_Moduel.axf -a -f 08000350 08001d94 0800260c 汇编中: ;HardFault_Handler ; PROC ; EXPORT HardFault_Handler …

PTA-用天平找小球

三个球A、B、C,大小形状相同且其中有一个球与其他球重量不同。要求找出这个不一样的球。 输入格式: 输入在一行中给出3个正整数,顺序对应球A、B、C的重量。 输出格式: 在一行中输出唯一的那个不一样的球。 输入样例&#xff…

Docker部署Vue+Springboot项目

一、部署Springboot项目 1.1先将本地的java项目打成jar包。 再右上角进行maven操作。 1.2将jar包上传到服务器当中。 先再目录/home 下创建一个文件夹(classRoom)用于存放后端打镜像时需要的文件。 如果是服务器的话可以直接将文件拖拽到想要转移的地方…

设计师不能忽视的几个宝藏图标设计工具

在这个快速变化的时代,设计师对创新和实用工具的需求越来越大。这就要求我们及时跟上潮流,不断探索和尝试最新、最有价值的图标设计工具。只有这样,我们才能在竞争激烈的设计市场中脱颖而出。以下是我们精心挑选的2024年值得一试的图标设计工…

2015年1月12日 Go生态洞察:Go语言中错误也是值

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

ios打包,证书获取

HBuilderX 打包ios界面: Bundle ID(AppID): 又称应用ID,是每一个ios应用的唯一标识,就像一个人的身份证号码; 每开发一个新应用,首先都需要先去创建一个Bundle ID Bundle ID 格式: 一般为&…

Android Studio记录一个错误:Execution failed for task ‘:app:lintVitalRelease‘.

Android出现Execution failed for task :app:lintVitalRelease.> Lint found fatal errors while assembling a release target. Execution failed for task :app:lintVitalRelease解决方法 Execution failed for task ‘:app:lintVitalRelease’ build project 可以正常执…

LeeCode前端算法基础100题(3)- N皇后

一、问题详情: 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n 皇后…