动态链接器(十):重定位
ELF文件中有许多种类型的重定位条目,这些重定位条目指导动态链接器在加载或运行时解析符号地址,确保程序能够正确地引用动态库中的函数和变量。
本文主要介绍那些与动态链接有关的重定位条目(主要介绍Rela相关的,Rel相关的不作介绍,且主要针对64位CPU架构)
1 重定位条目的结构
ELF文件中重定位条目的结构如下:
64位ELF文件:
#[repr(C)]
pub struct Elf64_Rela {pub r_offset: u64,pub r_info: u64,pub r_addend: i64,
}
32位ELF文件:
#[repr(C)]
pub struct Elf32_Rela {pub r_offset: u32,pub r_info: u32,pub r_addend: i32,
}
1.1 r_offset
表示需要被修正的目标地址相对于所在动态库的基地址(后文中会使用base来表示基地址)的偏移量,通常指向GOT中的某个条目。
若动态链接器发现一个 R_X86_64_JUMP_SLOT 类型的重定位条目,r_offset 会指向 GOT 中某个需要填充函数地址的位置。
PS:动态库的基地址是指动态库被实际加载的内存起始地址。
1.2 r_info
这里面包含着两个信息:
-
重定位类型(低 32 位):表示当前重定位的类型。例如: R_X86_64_JUMP_SLOT:动态函数跳转(PLT 条目)。
-
符号索引(高 32 位):表示该重定位关联的符号在符号表(.dynsym)中的索引。若符号索引为 0(比如 R_*_RELATIVE类型的重定位条目中符号索引就是0),表示无需符号解析,直接使用基地址和 r_addend 计算。
1.3 r_addend
提供附加的偏移量,用于某些重定位类型的地址计算。动态链接器在计算最终地址时,会将符号值(符号地址)与 r_addend 相加,对于某些重定位类型(如 R_*_RELATIVE),r_addend 直接参与基地址偏移计算。
2 重定位的种类
本节中base表示动态库的基地址,addr表示符号的地址。你可以使用readelf -r来查看动态库中的重定位类型。
PS:本节中的重定位类型并不完整,还有一些与线程局部存储(tls)相关的重定位类型,我打算之后专门写一篇介绍ELF线程局部存储的文章,然后在那篇文章中介绍它们。
2.1 R_*_GLOB_DAT
用途:用于全局变量或函数的重定位。当可执行文件或共享库引用其他共享库中的全局变量时,动态链接器通过此条目将GOT(Global Offset Table)中的对应项更新为变量的实际地址。
处理方式:动态链接器直接将符号地址(addr)写入r_offset+base处,后续访问通过GOT间接寻址。
*(r_offset + base) = addr
示例:
-
x86_64: R_X86_64_GLOB_DAT
-
aarch64: R_AARCH64_GLOB_DAT
PS:不过不是所有指令集都有这个类型的重定位条目,比如riscv64和loongarch64就没有这个。
2.2 R_*_JUMP_SLOT
用途:用于函数调用的延迟绑定(Lazy Binding)。当程序调用共享库中的函数时,首次调用会触发动态链接器解析函数地址并更新GOT中的跳转槽。
处理:与该条目相关的详细内容可以看:
动态链接器(七):深入理解PLT和GOT_plt got-CSDN博客https://blog.csdn.net/justdoyaya/article/details/145717000?spm=1001.2014.3001.5501
延迟绑定时:*(r_offset + base) = *(r_offset + base) + base
非延迟绑定时:*(r_offset + base) = addr
示例:
-
x86_64: R_X86_64_JUMP_SLOT
-
riscv64: R_RISCV_JUMP_SLOT
2.3 R_*_RELATIVE
用途:处理地址无关代码(PIC)中的绝对地址重定位。共享库中可能包含需要基于加载地址(基地址)调整的绝对地址。
处理:动态链接器将重定位地址计算为 基地址 + 偏移量,无需符号查找。
*(r_offset + base) = base + r_addend
示例:
-
riscv64: R_RISCV_RELATIVE
-
x86_64: R_X86_64_RELATIVE
2.4 R_*_COPY
用途:处理可执行文件与共享库中重复定义的全局符号。当可执行文件定义了一个全局符号(如变量),而共享库也引用了同名符号时,动态链接器将共享库的引用指向可执行文件中的副本。
处理:动态链接器将符号从可执行文件拷贝到共享库的指定地址。
memcpy(base + r_offset, addr, addr_size)
PS:addr_size指的是符号的大小(比如符号是函数的话就是整个函数的大小)。这种类型的重定位很少见到,我到现在也就见到过几次。
2.5 R_*_IRELATIVE
用途:处理IFUNC(间接函数)的重定位。IFUNC允许在运行时选择最优的函数实现(如根据CPU特性选择memcpy版本)。
处理:动态链接器调用预定义的解析函数,获取实际函数地址并填充到GOT。
*(r_offset + base) = (base + addr)()
示例:
-
x86_64: R_X86_64_IRELATIVE
-
riscv64: R_RISCV_IRELATIVE
PS:这里的 (base + addr)()指的是将base+addr所指的地址当作一个不传任何参数的函数指针来使用。使用glibc的程序有时会有这种类型的重定位,使用musl的程序不会出现这种类型的重定位。
2.6 R_*_64
这种类型的重定位与R_*_GLOB_DAT功能类似,不过在处理时有所差别,它会在符号地址的基础上加上r_addend。
*(r_offset + base) = addr + r_addend
示例:
-
x86_64: R_X86_64_64
-
riscv64: R_RISCV_64
3 具体实现
本文所讲的这些重定位类型的处理方式在elf_loader中均有实现:
elf_loader:一个使用Rust编写的ELF加载器-CSDN博客https://blog.csdn.net/justdoyaya/article/details/145766162?spm=1001.2014.3001.5501具体实现可以看下面这个链接中的代码:
rust_elfloader/src/relocation.rs at main · weizhiao/rust_elfloaderhttps://github.com/weizhiao/rust_elfloader/blob/main/src/relocation.rs想了解不同指令集中的重定位类型可以看这里:
rust_elfloader/src/arch at main · weizhiao/rust_elfloaderhttps://github.com/weizhiao/rust_elfloader/tree/main/src/arch
相关文章:

动态链接器(十):重定位
ELF文件中有许多种类型的重定位条目,这些重定位条目指导动态链接器在加载或运行时解析符号地址,确保程序能够正确地引用动态库中的函数和变量。 本文主要介绍那些与动态链接有关的重定位条目(主要介绍Rela相关的,Rel相关的不作介…...

EGO-Planner的无人机视觉选择(yolov5和yolov8)
EGO-Planner的无人机视觉选择(yolov5和yolov8) 效果 yolov5检测效果 yolov8检测效果 一、YOLOv8 vs YOLOv5:关键差异解析 1. 训练效率:为何YOLOv8更快? 架构轻量化 YOLOv8采用C2f模块(Cross Stage Partia…...

IO标准函数和时间函数
1、将当前的时间写入到time. txt的文件中,如果ctrlc退出之后,在再次执行支持断点续写 1.2022-04-26 19:10:20 2.2022-04-26 19:10:21 3.2022-04-26 19:10:22 //按下ctrlc停止,再次执行程序 4.2022-04-26 20:00:00 5.2022-04-26 20:00:0…...

为AI聊天工具添加一个知识系统 之133 详细设计之74通用编程语言 之4 架构及其核心
本篇继续讨论 通用编程语言。 说明:本阶段的所有讨论都是围绕这一主题展开的,但前面的讨论分成了三个大部分(后面列出了这一段的讨论题目的归属关系)-区别distinguish(各别): 文化和习俗。知识…...
【零基础到精通Java合集】第二十三集:G1收集器深度解析
课程标题:G1收集器深度解析——面向大内存与低延迟的现代垃圾回收器(15分钟) 目标:掌握G1核心设计思想、运行机制与调优策略,理解其如何平衡吞吐量与低延迟 0-1分钟:课程引入与G1设计目标 以“城市交通智能调度”类比G1核心思想:将堆内存划分为多个区域(Region),动…...

似然函数与极大似然估计
前言 本文隶属于专栏《机器学习数学通关指南》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见《机器学习数学通关指南》 正文 📚 1. 似然函数&a…...
QSFP(Quad Small Form-factor Pluggable)详解
1. QSFP的定义 QSFP(Quad Small Form-factor Pluggable)是一种四通道热插拔光模块/电模块,专为高速网络传输设计。其名称中的“Quad”表示模块集成4个独立通道,每个通道支持1Gbps至10Gbps速率(总带宽可达40Gbps&#…...

WDM_OTN_基础知识_波分系统基本构成-无源器件
在波分系统中通常将发光,对光进行放大以及产生光电转换的器件称之为有源器件,例如光放,激光器,与此相反,将那些不发光,不对光进行放大,也不产生光电转换的器件称之为无源器件,波分系统中的无源器…...

【音视频】ffmpeg音视频处理基本流程
一、ffmpeg音视频处理基本流程 首先先看两条命令 ffmpeg -i 1.mp4 -acodec copy -vcodec libx264 -s 1280x720 2.flv ffmpeg -i 1.mp4 -acodec copy -vcodec libx265 -s 1280x720 3.mkv-i :表示输入源,这里是1.mp4,是当前路径下的视频文件-acodec copy…...

【网络编程】之TCP实现客户端远程控制服务器端及断线重连
【网络编程】之TCP实现客户端远程控制服务器端及断线重连 TCP网络通信实现客户端简单远程控制主机基本功能演示通信过程代码实现服务器模块执行命令模块popen系列函数 客户端模块服务器主程序 windows作为客户端与服务器通信#pragma comment介绍 客户端使用状态机断线重连代码实…...

云原生容器编排:构建智能弹性应用的自动化引擎
引言:重构应用部署范式 Google Borg系统管理着超2500万容器实例,每日处理200亿个任务。阿里巴巴双十一使用Kubernetes实现300万Pod秒级弹性,资源利用率达65%。CNCF 2023报告显示全球Kubernetes生产采用率突破92%,CRI-O容器启动速…...
centos虚拟机安装
以下是一个详细的 VMware CentOS 虚拟机安装教程,结合了最新的信息和步骤: 一、准备工作 1. 下载 VMware 软件 访问 VMware 官方网站:VMware Workstation 官网。点击“现在安装”并下载适合您操作系统的 VMware Workstation。 2. 下载 Ce…...

社会力模型:Social force model for pedestrian dynamics
Social Force Model——社会力模型-CSDN博客 简介: 时间:1995 期刊:《Physical Review E》 作者:Dirk Helbing and Peter Molnar 摘要: 提出一种描述行人运动的“社会力模型”。认为行人的运动可看作是受到一系列…...

机器学习数学通关指南
✨ 写在前面 💡 在代码的世界里沉浸了十余载,我一直自诩逻辑思维敏捷,编程能力不俗。然而,当我初次接触 DeepSeek-R1 并领略其清晰、系统的思考过程时,我不禁为之震撼。那一刻,我深刻意识到:在A…...

【Mac】2025-MacOS系统下常用的开发环境配置
早期版本的一个环境搭建参考 1、brew Mac自带终端运行: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" Installation successful!成功后运行三行命令后更新环境(xxx是mac的username&a…...
# C# 中堆(Heap)与栈(Stack)的区别
在 C# 中,堆和栈是两种不同的内存分配机制,它们在存储位置、生命周期、性能和用途上存在显著差异。理解堆和栈的区别对于优化代码性能和内存管理至关重要。 1. 栈(Stack) 1.1 定义 栈是一种后进先出(LIFO࿰…...
ubuntu离线安装nvidia-container-runtime
参考文章 ubuntu系统docker20.4版本安装nvidia-container-runtime3.11.0-1版本(离线安装nvidia-docker) - jokerMM - 博客园 https://zhuanlan.zhihu.com/p/15194336245 一、软件地址 Index of /nvidia-docker/libnvidia-container/stable/ 从上述地地址——进入对应系统—…...

用Python+Flask打造可视化武侠人物关系图生成器:从零到一的实战全记录
用PythonFlask打造可视化武侠人物关系图生成器:从零到一的实战全记录 一、缘起:一个程序小白的奇妙探索之旅 作为一个接触Python仅13天的编程萌新,我曾以为开发一个完整的应用是遥不可及的事情。但在DeepSeek的帮助下,我竟用短短…...
学习笔记-DeepSeek在开源第四天发布DualPipe和EPLB两项技术
在AI模型训练的进程中,优化并行策略对于提升训练效率和资源利用率至关重要。DeepSeek在开源周第四天发布的DualPipe和EPLB两项技术,为V3/R1训练场景下的并行优化提供了创新解决方案。 DualPipe:双向管道并行算法 技术原理: Dua…...

C++入门基础知识1
今天,我们正式来学习C,由于C是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。熟悉C语言之后,对C学习有一定的帮助。 现在我们这篇主要是: 1. 补充C语言语法…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
算法250609 高精度
加法 #include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> using namespace std; char input1[205]; char input2[205]; int main(){while(scanf("%s%s",input1,input2)!EOF){int a[205]…...
PostgreSQL 与 SQL 基础:为 Fast API 打下数据基础
在构建任何动态、数据驱动的Web API时,一个稳定高效的数据存储方案是不可或缺的。对于使用Python FastAPI的开发者来说,深入理解关系型数据库的工作原理、掌握SQL这门与数据库“对话”的语言,以及学会如何在Python中操作数据库,是…...
el-amap-bezier-curve运用及线弧度设置
文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...