【链接、装载与库】动态链接中的延迟绑定(PLT)

动态链接过程延迟绑定的实现(PLT) 动态链接比静态链接要慢1%~5%,根据动态链接中PIC(与地址无关代码)的原理PIC,可以知道造成该情况的原因如下: 1.动态链接下对于全局和静态数据的访问都要进行复杂的GOT(全局偏移表)定位,然后间接寻址;对于模块间的调用也要先定位GOT,然后再进行跳转 2.动态链接的链接工作是在运行时完成,即程序开始运行时,动态链接器都要进行一次链接工作,而链接工作需要复杂的重定位等工作,减慢了启动速度 阅读详情

系列文章

【链接、装载与库】程序的编译过程
【链接、装载与库】动态链接相关结构
【链接、装载与库】动态链接初体验

前言

动态链接是在运行时将各个模块的代码进行整合,静态链接是在编译时对各个模块的代码进行整合。
而运行时整合使得动态链接相对消耗了一些性能,为了减小这点带来的影响,动态链接中引入了延迟绑定(PLT),其基本思想是当函数第一次被用到时才进行绑定(符号查找、重定位等),如果没有用到则不进行绑定,接下来通过一个示例对延迟绑定进行分析。

正文

首先创建5个文件liba.c、liba.h、libb.c、libb.h、main.c。
内容分别为:
liba.c

int funca(int i)
{
	return i + 1;
}

liba.h

#ifndef LIBA_H
#define LIBA_H

int funca(int i);

#endif

libb.c

int funcb(int i)
{
	return i + 2;
}

libb.h

#ifndef LIBB_H
#define LIBB_H

int funcb(int i);

#endif

main.c

#include <stdio.h>
#include "liba.h"
#include "libb.h"

int main()
{
	int a;
	int b;
	a = funca(1);
	b = funcb(1);

	printf("a is %d,  b is %d\n", a, b);
}

输入如下指令分别生成liba.so、libb.so两个动态共享对象:
gcc -fPIC -shared -o liba.so liba.c
gcc -fPIC -shared -o libb.so libb.c
然后输入如下指令对main.c进行编译输出可执行文件main:
gcc -o main main.c ./liba.so ./libb.so
此时文件夹中的内容如下:
在这里插入图片描述
运行可执行文件main得到如下结果:
在这里插入图片描述
接下来对可执行文件main进行分析。
输入如下指令得到main的反汇编代码:
objdump -S main
其中main函数部分内容如下:
在这里插入图片描述
可以看到
调用funca函数部分代码为callq 660 <funca@plt>
调用funcb函数部分代码为callq 680 <funcb@plt>
调用printf函数部分代码为callq 670 <printf@plt>
找到反汇编代码中0x660、0x670、0x680部分的代码,内容如下:
在这里插入图片描述
以funcb为例,可以看到调转到0x680地址后执行的代码为去0x200fd0地址取出一个数值,将其赋值给PC指针继续执行。
要想查看0x200fd0地址处的内容,输入如下指令,得到main的二进制形式:
objdump -s main
找到我们想要的内容如下:
在这里插入图片描述
这部分叫做全局偏移表(GOT)
可以看到0x200fd0地址处的内容为86060000 00000000进行大小端转换之后就是0x686,而0x686处的代码则是:
在这里插入图片描述
也就是压栈一个数值2,然后执行0x650处的代码,0x650处代码如下:
在这里插入图片描述
可以看到这部分执行的代码为压栈GOT表第二项数据,跳转到GOT表第三项存储的函数地址开始执行。
GOT表的内容如下:

序号地址含义
第一项0x200fa8.dynamic段地址
第二项0x200fb0Module ID (模块编号)
第三项0x200fb8_dl_runtime_resolve()
第四项0x200fc0funca函数
第五项0x200fc8printf函数
第六项0x200fd0funcb函数

调用_dl_runtime_resolve函数用于把funcb的真实地址填写到GOT中,整个过程如下:
在这里插入图片描述
这是第一次调用funcb函数的时候,之后再调用funcb函数时,由于GOT表已经写入了funcb函数的真实地址,所以执行过程如下:
在这里插入图片描述
这样就实现了第一次调用funcb函数时完成了动态链接,之后就可以直接调用的效果。

在调用_dl_runtime_resolve时要压入funcb函数的符号下标。
所谓的符号下标是.rela.plt段中的下标,输入如下指令:
readelf -a main
找到.rela.plt段的内容如下:
在这里插入图片描述
第一列表示函数在GOT表中的地址,最后一列表示函数的符号名。
_dl_runtime_resolve获取符号下标之后,就可以通过符号名去别的模块查找函数地址,找到之后将函数地址填写到第一列存储的GOT表地址中,也就完成了动态链接。

浅析ELF中的GOT与PLT 一、ELF简介 现在PC平台流行的可执行文件格式主要是Windows 下的PE(portable Executable) 和Linux的ELF(Excutable Linkable Format)。   编译器编译源代码后生成的文件叫做目标文件,从目标文件的结构上讲, 它是已经编译后的可执行文件格式,只是还没有链接的过程,其中可能有些符号或有些地址还没有被调整。其实它本身就 阅读详情

相关推荐

【Linux学习笔记】Linux动态共享对象(动态链接库)装载过程

之前开发项目时,曾遇到一个问题:模块中用到的某so文件与模块某源码文件中存在同名函数(在链接器linker来看,是同名符号)时,so文件中同名函数被“覆盖”,从而导致模块启动时崩溃。当时曾专门做过实验,得到了避免出问题的一些小技巧(参见之前的某篇笔记),但其实对引发问题的底层原因并特别不清楚(当时由于这类问题对应的术语及其英文关键词一无所知,导致google不出干货)。最近,阅读《程序员的自我修养

slvher的专栏 3109

ELF文件中的各个节区

ELF节区信息概述: 节区名 节区说明 备注 .rodata1 和rodata类似,只存放只读数据 .comment 存放编译器版本信息,如字符串 "GCC:(GNU)4.2.0" .debug 存放调试信息 .shstrtab ..

ashimida 8708

20220601超简单百度地图街景图片爬取+绿视率计算

真的不难咯。

weixin_39676904的博客 1万+

动态链接1 程序员的自我修养第七章笔记

0. 序 预计这篇文章会很长,折腾了挺长时间才差不多捋清楚,主要书上一些地方和现在的实现有一点出入。 1. 概览 与动态链接有关系的节大概有这样一些,.interp, .dynamic, .gnu.hash, .rela.dyn, .rela.plt, .plt, .plt.got, .got, .got.plt。其中.rela.dyn和.rela.plt也可能替换为.rel.dyn, .rel.plt,取决于具体重定位类型的选择。 其中.interp, .dynamic提供动态链接的一些初始信息。 .gn

passenger12234的博客 934

LLMOps的崛起:如何利用Langfuse和Opik构建高效的模型监控与评估体系

本文探讨了LLMOps的崛起,详细介绍了如何利用Langfuse和Opik构建高效的模型监控与评估体系。通过开源工具Langfuse的全景监控方案和Opik的三层评估体系,帮助AI工程团队实现大语言模型的全生命周期管理,提升模型性能和迭代效率。文章还提供了实战技巧和工具链集成方案,助力企业优化AI应用。

ll5678的博客 680

阿里云百炼平台创建智能体-上传文档

阿里云百炼智能体-上传文档文件

weixin_43930851的博客 1356

PLT延迟绑定技术

动态链接的链接工作在运行时完成,即程序开始执行时,动态链接器要先进行一次链接工作。 由于程序模块之间包含了大量的函数引用,所以在程序开始执行之前,动态链接会耗费不少时间用于解决模块之间的函数引用的符号查找以及重定位。 由于程序的局部性原理,在一个程序的运行的过程中,往往不是所有的函数都能用到,相反在大量的符号中,只有少部分会用到,所以如果在程序一开始的时候就把所有的函数都链接好然而最后又没有用到,这很明显是一种浪费,所以就出现的延迟绑定的概念。 基本思想就是:函数不是程序运行之前就全部进行链接工作,而是在用

、moddemod 980

IP-Guard安全网关实例

企业相关情况: 1.OA系统,主要为日常工作使用,该系统IP为192.168.1.2,端口为8080; 2.文件共享服务器,用于存放日常工作资料和文档,该文件共享服务器的IP为192.168.1.1,其中\\192.168.1.1\private 目录中的存放着公司重要文档,不能随意外传; 3.安全网关已采用串联的方式联入网络,IP为192.168.2.6,所有机器访问OA系统和文件共享服务...

IP-Guard专栏 707

4. 深入窥探动态链接

在动态链接方式实现以前,普遍采用静态链接的方式来生成可执行文件。如果一个程序使用了外部的库函数,那么整个库都会被直接编译到可执行文件中。ELF 支持动态链接,这在处理共享库的时候就会非常高效。当一个程序被加载进内存时,动态链接器会把需要的共享库加载并绑定到该进程的地址空间中。随后在调用某个函数时,对该函数地址进行解析,以达到对该函数调用的目的。(1)简介: 过程连接表,在程序中以 .plt 节表示,该表处于代码段,每一个表项表示了一个与要重定位的函数相关的若干条指令,每个表项长度为 16 个字节,存储的是

谢谢大家的关注 895

ICM20948 DMP代码详解(54)

ICM20948 DMP代码详解(54)

phmatthaus的专栏 424

MATLAB使用贝叶斯网络bnt工具箱:使用手册详解

MATLAB使用贝叶斯bnt网络工具箱:使用手册详解

WW、forever的博客 2676

聊一聊Linux动态链接和GOT、PLT

共享动态库是现代系统的一个重要组成部分,大家肯定都不陌生,但是通常对背后的一些细节上的实现机制了解得不够深入。当然,网上有很多关于这方面的文章。希望这篇文章能够以一种与其他文章不同的角度呈现,可以对你产生一点启发。关于动态链接与静态链接,看到过这么与一个比方:如果我的文章引用了别人的一部分文字,在我发布文章的时候把别人的段落复制到我的文章里面就属于静态连接,而做一个超链接让你们自己去看就属于动态链接。

lcmsir的博客 638

NLTK中WordNet与同义词处理

通过本教程,学习了如何使用NLTK中的WordNet进行自然语言处理任务。首先介绍了WordNet的基本概念及其在NLTK中的集成使用,接着讲解了如何查找同义词、反义词等词汇关系,并结合实际应用演示了语义相似性计算。这些技能在文本分析、情感分析、信息检索等场景中有广泛应用,可以帮助开发者构建更智能的自然语言处理系统。掌握这些基本操作后,可以进一步探索WordNet的其他高级功能,结合其他NLTK工具进行更复杂的语言分析。

Mr数据杨 472

《程序员的自我修养:链接、装载与库》读书笔记:静态链接、动态链接

静态链接、动态链接,目标文件的内容

阿正的梦工坊 1470

风电功率预测项目技术白皮书:短期、超短期、中长期全尺度算法详解与工程落地

聚焦风电功率预测的时间尺度与算法:短期(0~72h)以XGBoost/LightGBM/CatBoost及深度学习为主,超短期(0~4h)采用ARMA+LSTM,中长期用LightGBM等,并涵盖概率预测、多气象源融合、AI大模型+物理模型混合策略、极端天气应对及工程运维要点。

算法工程师 325

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【Linux库制作与原理进阶】从 ELF 装载到延迟绑定:搞懂动态库、GOT 与 PLT

本文围绕 ELF 装载与动态链接展开,讲清 Program Header Table 如何指导 Segment 映射,动态库如何进入进程地址空间,以及 PIC、GOT、PLT 分别解决什么问题。通过首次调用与后续调用的对比,进一步理解符号解析、地址重定位和延迟绑定的完整过程。

2402_87731470的博客 4104

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

《链接装载与库》第七章——动态链接

将程序的模块互相分割开,不让它们静态地链接在一起;即不对那些组成程序的目标文件进行链接,等到程序运行时再链接。有如Program1和Program2两个程序,并假定保留了Program1.o、Program2.o和Lib.o三个文件。当我们需要运行Program1这个程序时,系统首先加载 Program1.o,而系统发现Program1.o中用到了Lib.o,即Program1.o依赖于Lib.o,此时系统加载Lib.o,并将其加载至内存。所有需要的目标文件加载完毕后,若依赖关系满足,即所有的依赖文件都在磁

yelvens的博客 6610

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

程序的动态链接(3):延迟绑定

概述 动态链接将链接工作由编译时推迟到了运行时,在每次程序运行时,动态链接器都要寻找并加载依赖的动态库,然后进行符号查找和重定位工作,这导致动态链接的程序在加载时会带来一些额外的开销。为了提升程序的加载速度,编译系统使用了一种称为延迟绑定(Lazy Binding)的技术。 延迟绑定实现 使用延迟绑定是基于这样一个前提:在动态链接下,程序加载的模块中包含了大量的函数调用,因此动态链接器会耗费很多的时间用于解决模块之间的函数引用的符号查找以及重定位,而实际上只有很少的一部分符号会被立刻访问。延迟绑定通过将函数

Aspiresky的专栏 3380

Linux x86_64 程序动态链接之GOT 和 PLT

Linux x86_64 程序动态链接之 GOT 和 PLT延时绑定技术,以及给出了一个demo。

小立仔 1671

【读书笔记】【程序员的自我修养 -- 链接、装载与库(二)】进程虚拟地址空间、装载与动态链接、GOT、全局符号表、共享库的组织、DLL、C++与动态链接

进程虚拟地址空间、装载与动态链接、GOT、全局符号表、共享库的组织、DLL、C++与动态链接

多丰富下自己呀 6461

程序员的自我修养—链接、装载与库 笔记

程序员的自我修养—链接、装载与库 笔记目标文件静态链接编译和链接过程动态链接装载过程函数调用过程系统调用过程堆栈 目标文件 静态链接 编译和链接 过程 动态链接 装载 过程 函数调用过程 系统调用过程 堆栈 ...

Yang_137476932的博客 3793

【链接装载与库】动态链接(下)

动态链接的确有很多优势,比静态链接要灵活得多,但它是以牺牲一部分性能为代价的。主要原因是动态链接下对于全局和静态的数据访问都要进行复杂的GOT定位,然后间接寻址;对于模块间的调用也要先定位GOT, 然后再进行间接跳转,另外一个原因是动态链接的链接工作在运行时完成,即程序开始执行时,动态链接器都要进行一次链接工作。我们将在这一节介绍优化动态链接性能的一些方法。在动态链接下,程序模块之间包含了大量的函数引用,会耗费不少时间用于解决模块之间的函数引用的符号查找以及重定位。

qq_60755751的博客 332

程序员的自我修养--链接、装载与库笔记:动态链接

1. 为什么要动态链接 静态链接诸多缺点,比如浪费内存和磁盘空间、模块更新困难等。 内存和磁盘空间:静态链接的方式对于计算机内存和磁盘的空间浪费非常严重,特别是在多进程操作系统情况下。 程序开发和发布:空间浪费是静态链接的一个问题,另一个问题是静态链接对程序的更新、部署和发布也会带来很多麻烦。一旦程序中有任何模块更新,整个程序就要重新链接、发布给用户。如果程序都使用静态链接,那么通过网络来更...

网络资源是无限的 3297

装载与动态链接——动态链接(二)

文章目录为什么要动态链接地址无关代码延迟绑定动态链接步骤与实现动态连接器自举装载共享对象重定位和初始化显式运行时链接 前文速递: 静态链接——编译和链接(一) 静态链接——目标文件(二) 静态链接——静态链接(三) 装载与动态链接——装载与进程(一) 本文主要是《程序员的自我修养》一书的内容摘要和梳理,如有需要并且没有被本文涵盖的内容,建议读者自行观看原书。 前面主要写了文章来介绍书中对程序的静态链接的相关内容,接下来系列开启对动态链接的学习。 为什么要动态链接 静态链接可以使程序开发者可以独立地开发和测试

Chris_zhangrx的博客 810

一篇长文带你深析Linux动态链接的全过程

引言:最近受到了一位老师的启发(我不是CS专业的,我去找了信院里的操作系统的老师),又给我本狭隘的视野开拓了一些目光所及之处,交流了两个小时,倍感遗憾怎么没有早点认识这个老师,也倍感欣慰终于遇到了这种老师。 这篇文章可能有点晦涩难懂,我希望你有以下的前置基础知识(基础即可,我会尽量说清): 操作系统(最好看过CSAPP) AT&T语法的汇编语言(Intel汇编也可以,但是可能有些地方不同得去查询指令集开发手册了) 对C和C++有一定的掌握 对Linux操作熟练,对Linux内核和系统有一定的了解

遇事不决,问春风 4482

动态链接介绍

模块间的访问比模块内部稍微麻烦一点,因为模块间的数据访问目标地址要等到装载时才决定,我们前面提到要使得代码地址无关,基本的思想就是把跟地址相关的部分放到数据段里面,很明显,这些其他模块的全局变量的地址是跟模块装载地址有关的。如此循环直到所有依赖的共享对象都被装载进来为止,当然链接器可以有不同的装载顺序,如果我们把依赖关系看作一个图的话,那么这个装载过程就是一个图的遍历过程,链接器可能会使用深度优先或者广度优先或者其他的顺序来遍历整个图,这取决于链接器,比较常见的算法一般都是广度优先的。

biu801的博客 1339
上一篇: 【链接、装载与库】程序的编译过程
下一篇: 【LwIP源码学习1】LwIP网络接口管理
inputA
博客等级 码龄7年 297粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值