最新要闻
- 斯坦福大学教授称地球上100%存在外星人 或将影响文明的发展
- 研究称近7成的年轻人一般会拖到0点后入睡 多数人为报复性熬夜
- 爱马仕因产品质量不合格 遭市场监管局罚款30.51万元
- 谷歌投资《瞬息全宇宙》幕后技术公司 将加速AI在影视创作领域的进展
- 海外知名种子网站RARBG宣布闭站 称众多因素导致其难以支持日常开销
- 中国徐工连续3年稳居全球前三 总销售额为该榜单有史以来最高数字
- 《变形金刚7》水墨武侠风海报发布 将于6月9日登陆内地院线
- 两名亚马逊员工从仓库盗取《塞尔达传说》实体游戏及周边 用于转卖获利
- 任天堂现已停止在俄罗斯的eShop游戏和软件销售 账户信息即将删除
- 经典奇幻动漫《JOJO的奇妙冒险》音乐剧即将推出 于东京帝国剧场开演
- 天天即时看!RTX 4070 618处境尴尬:比RTX 4060贵太多
- 第一稳了!比亚迪:5月新能源汽车销售24.02万辆 天天讯息
- 世界播报:辽宁突发龙卷风 行驶中的车辆被卷起:科普遇龙卷风如何自救
- 观众称花千元在演唱会上看柱子:主办方称事先不知情
- 女硕士诈骗千万元花三百万买游戏装备!获刑十三年
- 怎么冻结表格前三行前三列_怎么冻结表格前三行
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
C温故补缺(十七):动态链接(ELF,PIC,GOT,PLT)|视点
动态链接(PIC,GOT,PLT,ELF)
参考:51CTO
通过静态链接,可以生成一个可执行文件,这个可执行文件既可以是完全链接的也可以是部分链接的,对于部分链接的可执行文件,有些符号引用需要等到可执行文件加载时甚至是运行时才会进行符号解析和重定位。
【资料图】
动态链接与静态链接一样包括符号解析和重定位两个任务,静态链接和动态链接的区别之一就是符号解析和重定位的时机,动态链接分为加载时动态链接和运行时动态链接,本篇文章将拆分成3个部分阐述:
1.可执行文件的结构和加载过程。
2.加载时动态链接。
3.运行时动态链接。
可执行文件的结构和加载过程
可执行文件的结构:ELF
可执行文件的结构与可重定位目标文件的结构类似,都是采用ELF文件格式,不同的是它们包括的节有差异,另外可执行文件增加了程序头部表(program header table),如下图所示
如上图所示,对于可执行文件来说,ELF文件头中的程序入口地址字段不再为空,入口地址指向了第一条指令的虚拟内存地址,.init是一个函数,这个函数在程序加载时,做一些初始化的工作。
可执行文件中只有一部分内容能够加载到内存中,如上图所示,.init,.text,.rodata这几个节,程序头部表以及ELF文件头会加载到内存中代码段中,代码段的权限只读,.data,.bss这两个节加载到内存的数据段,数据段的权限是读和写,其它节不能加载到内存中,只起到辅助作用。可执行文件与可重定位目标文件相比较多出了一个程序头部表
可执行文件的加载
我们经常通过./prog 命令加载一个可执行文件,prog是可执行文件的名称,当执行这个命令时,操作系统会调用内核中的一个加载器(loader),通过加载器来运行可执行文件,另外在Linux中也可以采用execve函数来调用加载器。
加载器加载一个可执行文件时,会执行以下步骤:
- 创建一个进程上下文和进程虚拟地址空间,如下图为进程虚拟地址空间
建立可执行文件的内容(按照页大小)和虚拟地址空间页的映射关系(依据程序头部表),依据程序头部表可以得出,代码段总是从0x0000000000400000开始的,数据段则是从0x0000000000600e00开始的,代码段的大小为0x00000000000008ec,数据段的大小为0x0000000000000258。
将可执行文件的文件头信息加载到内存。
以上就是加载一个可执行文件的过程,可以看出加载的过程并没有把可执行文件中的代码和数据加载到内存,当CPU第一次调度进程时,加载器才会根据文件头中的程序入口地址,开始执行第一条指令,当执行这条指令时,发现指令不在内存中,发生了缺页中断,才会将虚拟页加载到内存中。
程序的入口地址往往指向_start函数,_start函数调用系统启动函数__libc_start_main,这个系统启动函数定义在libc.so中,它负责初始化执行环境,调用用户层提供的main函数,同时负责处理main函数的返回值,并在合适的时机交由内核处理。
加载时动态链接
静态链接是在执行链接命令时开始链接过程,通常链接的是静态库,另外静态库可以实现按需链接即用到了到哪个函数就链接哪个函数到可执行文件中。
不过静态库有以下几个弊端:
静态库的内容发生了变化,其它依赖静态库的程序需要重新编译。
静态链接时,将静态库的函数和数据复制到了可执行文件中,因此多个可执行文件就会有多份函数和数据,这个会耗费大量的磁盘空间,如果将这些可执行文件加载到内存则会耗费大量的内存。
因此,共享库就诞生了,它在内存中独一份,共享库是个共享目标文件,也是采用ELF文件格式,通常是以.so作为文件后缀,这里顺别提一下微软的共享库是DLL文件。
当可执行文件加载时,由动态链接器加载共享库到内存中,然后和可执行文件进行链接,因此这个过程叫做加载时动态链接。
可以通过gcc -shared -fpic -o allvector.so addvec.c multvec.c
命令生成一个共享库,对于-fpic表示生成位置无关的共享库,一般来说生成共享库必须有这个选项,后续会单独介绍。
生成了共享库后,可以通过gcc -o proglib mainlib.c ./allvector.so
命令生成一个可执行文件,当然这个命令并也需要执行静态链接,通过静态链接将一些需要静态链接的目标文件进行链接,链接后生成一个部分链接的可执行文件,当可执行文件加载时,通过动态链接器链接allvector.so这个共享库。
可执行文件加载时,有一个.interp节,这个节包含了动态链接器的文件路径,动态链接器也是一个共享库,操作系统负责加载和运行这个动态链接器,然后由这个动态链接器来负责加载共享库,动态链接器接下来共享库的链接过程。
以gcc -o proglib mainlib.c ./allvector.so
这个命令生成的可执行文件为例,加载可执行文件时,动态链接的过程大致如下:
加载共享库libc.so这个共享库中的数据和代码到内存段,并进行符号解析和重定位。
加载共享库allvector.so这个共享库中的数据和代码到内存段,并进行符号解析和重定位。
对proclib可执行文件中涉及到的未定义的符号引用进行解析和重定位。
运行时动态链接
除了在可执行文件加载时进行动态链接,也可以在应用程序运行过程中,加载和运行一个共享库,然后进行动态连接。
运行时动态连接有两个常见场景:
分发软件包,例如采用共享库来作为一个软件升级包,用户下载这个这个共享库后,替换了旧版本,应用程序运行时,会自动加载这个共享库并进行重新链接。
构建高性能的Web服务器,很多Web服务器接受客户端的请求生成动态的页面内容,早期的做法是创建一个子进程(fork),然后在这个子进程来生成动态的页面内容,这样的方式性能不是很好,不利于扩展,而高性能的Web服务器则是将每个动态生成页面内容的函数封装成一个共享库,当服务器接受到客户端请求时,会动态链接到合适的函数,然后调用它,这个函数只加载一次,便会缓存在内存中,下一次请求同一个函数时,就是直接获取这个函数指针即可,另外,如果函数发生变化时,不需要重启服务器,只需要重新加载这个共享库就可以了,另外Web服务器也可以动态增加一个新的函数,来满足新的业务需求。
位置无关代码
共享库的目的是多个程序共享一份库代码,那么多个程序是怎么共享一份库代码呢,一种方式是将一个共享库存储在内存的固定位置,然后程序动态链接时,将符号引用重定位到这个位置就可以了,然后这种方式也有不少弊端:
地址空间的使用率不高,例如一个共享库即使没有被使用,它也占用哪个空间,因为这个空间已经被分配出来了。
一个共享库的版本发生了变化后,占用的空间可能会扩大,这样很有可能需要选择一个新的内存段来存储这个共享库。
新的共享库需要新的内存段,随着时间的推移,会有大量大小不一的共享库,这就会造成很多不能使用的空闲内存。
每个系统,库在内存中的分配方式不同,这样就增加了管理难度。
为了解决上述的弊端,现代系统编译共享库代码,这个共享库代码是可以加载到内存的任意位置的,所有用到这个共享库代码的程序,通过gcc -shared -fpic -o allvector.so addvec.c multvec.c
的方式生成位置无关的代码,其中-fpic就表示生成位置无关的代码。
位置无关代码的实现原理是基于以下一个事实:
可执行文件的代码段中指令引用的数据变量的地址和函数的地址是相对固定的即位置无关的,如下图:
代码段和数据段的距离是固定的X
如上图所示,代码段的【指令n-1】引用到了数据段的【变量n】,当执行【指令n-1】时,(%rip)表示下一条指令即【指令n】的地址,【指令n】的地址与变量n的地址位置差是X,这个X是固定的,与内存无关的,因此执行【指令n-1】时,通过X[%rip]即指令n的地址+X总是能够获取正确的变量n的地址。
位置无关的代码基于上面所述的事实,可以分为两类:全局变量引用的位置无关和函数引用的位置无关,下面分别讨论:
全局变量引用的位置无关:
编译器为了实现全局变量引用的位置无关,引入了一个全局偏移量表(GOT),全局偏移量表为每个全局变量引用增加一个条目,每个条目占用8个字节,每个条目都有一个重定位条目,当可执行文件加载时,会根据重定位条目对全局变量进行重定位,将条目的内容设置为全局变量重定位后的地址,如下图所示
由上图和上述代码可以看出,addvec函数引用了全局变量addcnt,在addvec函数中执行指令mov 0x2008b9(%rip),%rax
时,0x2008b9是当前执行指令的下条指令和GOT[3]的距离,这个距离是固定的,与内存无关的,mov 0x2008b9(%rip),%rax
指令通过访问GOT[3]来间接获取addcnt的全局变量的地址,当addcnt全局变量的内存地址发生变化时,只需要将GOT[3]的内容进行调整,addvec的所有指令不需要进行调整,这就实现了全局变量引用的位置无关。
函数引用的位置无关:
编译器为了实现函数引用的位置无关,采用全局偏移量表GOT和过程链接表PLT共同来完成的,如下图所示:
由上图得知:
在代码段中,编译器创建了一个PLT表,PLT包括多个表项,每个表项包括几条指令,PPLT[0]和PLT[1]是内置的表项,PLT[0】用于调用动态链接器,然后重定位某个函数引用的地址,PLT[1]用于跳转到__libc_start_main函数执行初始化工作,这个函数调用了用户程序的main函数,从PLT[2]开始为函数引用的表项,有多少个函数引用就有多少个表项,例如PLT[2]为第一个函数引用的表项,PLT[3]为第三个函数引用的表项,以此类推。
在数据段中,编译器创建为了GOT表,GOT表包括多个表项,每个表项里存储一个地址,GOT[0]~GOT[3]是内置的表项,从GOT[4]开始,每个函数一个表项,例如GOT[4]是第一个函数引用的表项,GOT[5]为第二个函数引用的表项,编译器生成可执行文件时,GOT[4]中存储的地址总是指向了PLT[2]表项的第二条指令,GOT[5]中存储的地址总是指向了PLT[3]表项的第二条指令,因此类推。
以GOT[4]为例,GOT[4]为函数引用addvec的表项。
当一个目标文件第一次调用addvec时,经历了5个步骤:
执行指令call 0x4005c0。0x4005c0为PLT[2]表项的地址,这个地址是个相对地址,与内存无关的,生成可执行文件时,就已经确定了。
跳转到PLT[2]表项即0x4005c0地址处,开始执行PLT[2]表项的指令,PLT[2]表项的第一条指令就是跳转到GOT[4]指向的地址,这个地址在第一次调用时,刚好是PLT[2]表项的第二条指令地址。
跳转到PLT[2]表项的第二条指令后,将函数引用的编号这里是0x01入栈,然后跳转到了PLT[0]表项。
开始执行PLT[0]表项的指令,第一条指令是将重定位表的地址入栈,然后调用动态链接器。
动态链接器利用传入的重定位表和函数引用编号对函数进行重新定位,找到了函数引用对应的内存地址,然后更新到GOT[4]。
当一个目标文件第二次调用addvec函数时,经历了2个步骤:
call 0x4005c0。0x4005c0为函数引用的表项即PLT[2]的地址。
跳转到PLT[2]表项,开始执行PLT[2]表项的指令,PLT[2]表项的第一条指令就是跳转到GOT[4]指向的地址,由于GOT[4]刚好是函数引用的地址,直接调用函数了,后面的步骤就不需要了。
关键词:
-
C温故补缺(十七):动态链接(ELF,PIC,GOT,PLT)|视点
动态链接(PIC,GOT,PLT,ELF)参考:[51CTO](https: blog 51cto com u_15169172 3033961)通过静态链接,可
来源: C温故补缺(十七):动态链接(ELF,PIC,GOT,PLT)|视点
volatile与java内存模型_全球观热点
16)创建存储过程-今日热闻
斯坦福大学教授称地球上100%存在外星人 或将影响文明的发展
研究称近7成的年轻人一般会拖到0点后入睡 多数人为报复性熬夜
爱马仕因产品质量不合格 遭市场监管局罚款30.51万元
谷歌投资《瞬息全宇宙》幕后技术公司 将加速AI在影视创作领域的进展
海外知名种子网站RARBG宣布闭站 称众多因素导致其难以支持日常开销
中国徐工连续3年稳居全球前三 总销售额为该榜单有史以来最高数字
全球看热讯:每日机构分析:6月1日
《变形金刚7》水墨武侠风海报发布 将于6月9日登陆内地院线
两名亚马逊员工从仓库盗取《塞尔达传说》实体游戏及周边 用于转卖获利
任天堂现已停止在俄罗斯的eShop游戏和软件销售 账户信息即将删除
经典奇幻动漫《JOJO的奇妙冒险》音乐剧即将推出 于东京帝国剧场开演
天天即时看!RTX 4070 618处境尴尬:比RTX 4060贵太多
第一稳了!比亚迪:5月新能源汽车销售24.02万辆 天天讯息
世界播报:辽宁突发龙卷风 行驶中的车辆被卷起:科普遇龙卷风如何自救
观众称花千元在演唱会上看柱子:主办方称事先不知情
女硕士诈骗千万元花三百万买游戏装备!获刑十三年
饿了么太狠:面个高级Java,抖这多硬活、狠活(饿了么面试真题)
vue xlsx组件 导出的excel表头插入内容-世界观天下
怎么冻结表格前三行前三列_怎么冻结表格前三行
今日热议:一年4.3万人死于车祸!美国NHTSA宣布:所有新车都要安装自动刹车系统
百度网盘从苹果APP Store下架 原因揭晓:很快会恢复正常 焦点热闻
环球报道:河南一村庄修路挖出大石龟:名为“赑屃”、或有古墓
郭帆:在摸索如何用AI做《流浪地球3》 当前速递
媲美风扇散热!索泰展示新款迷你主机:主动散热模块首次应用
察右后旗农发行开展案防案件处置应急演练
Java学习问题记录
业务安全情报第16期 | 大促8成优惠券竟被“羊毛党”抢走!?
精选!DNS隧道流量分析
短讯!Redmi神秘新机入网:支持5G异网漫游
今日快讯:3年超长质保YYDS!魅族618开门红:魅族手机销额增速第一
黑美人鱼泪奔!《小美人鱼》海外也没人看 白人观众无视:收支平衡成笑谈
开放世界游戏《仙剑世界》首测定档6月17日:招募已开启
三色激光色彩更纯!Vidda C1S 4K投影仪图赏
当前热文:NixOS 23.05系统发布:
焦点速递!14-按键消抖
9秒被骗245万元?AI火了,骗子也来了! 每日热点
科创板收盘播报:科创50指数跌0.03% 新相微较发行价涨88.46%
人民币兑美元中间价报7.0965,调贬144个基点-焦点速讯
治愈癌症不再遥不可及 罗氏抗癌神药“起死回生”
环球今头条!女子输液被拔针扎进水桶:系摆拍 已行拘
最新资讯:人民文娱评《小美人鱼》争议:别乱给国内观众扣帽子
全球微资讯!AITO问界5月交付5629辆!华为: 和赛力斯一起造最好的车
当前时讯:中国徐工连续3年稳居全球前三 挖掘机四斗就能装满百吨级矿车
波司登云原生微服务治理探索 环球微资讯
搞事我们是认真的!TDengine 周边大礼包走起,数量有限先到先得
环球微速讯:【终极计算平台】上海道宁为您提供Wolfram技术,支持跨桌面、云、服务器和移动设备的强大工作流程
2023年湖北随州曾都区中小学教师公开招聘面试初步人选资格审查公告 全球资讯
雷军从长城挖来了明星高管
全球热议:还是西餐便宜?城市上班族吐槽吃不起中式快餐:一顿40+很正常
比亚迪的“常压油箱” 不会成为中国版“排放门”
憋回去的便便都去哪了?知道真相的人都再也不敢憋了
选用A级大青梅!溜溜梅经典系列大促:5件到手34.9元|热讯
MySQL视图
天天即时:[日志管理] 启动程序时,因报“log4j-slf4j-impl cannot be present with log4j-to-slf4j”错误而导
从“分离焦虑”到融入集体 看幼儿园“小托班”如何带娃
天天滚动:夏季这种穿搭更火,叫“上面开会、下面约会”,谁穿了都很洋气
美国芯片大厂德州仪器无底线降价:针对国内芯片公司 就是比国产便宜 当前热讯
襄阳一初中学生集体宣誓终生不买烟 做不抽烟新一代:网友点赞全国推广
环球观速讯丨Https加密原理:SSL/TLS四次握手过程(转载)
统信UOS系统开发笔记(二):国产统信UOS系统搭建Qt开发环境安装Qt5.12 世界观焦点
掌握嵌入式Linux编程1开始
linux 性能自我学习 ———— cpu 切换带来的性能损耗 [二] 世界热点
介绍.NET几种人脸识别组件
诺德基金张昳泓:市场板块分化明显,经济呈现弱复苏态势-环球速讯
现实版《速度与激情》 女司机误将拖车当上坡上演飞车特技
奶牛听着音乐按摩挤奶!认养一头牛纯牛奶大促:74.9元3箱 天天看热讯
入门即满配成标杆!岚图5月交付新车3003辆 同比大涨231%
集团破产重整 资产被轮番拍卖!众泰董事长辞职
天天热资讯!六一演出现场的最美妈妈团 一身旗袍扭腰跳舞太惊艳:网友直呼身材颜值绝
玖章算术NineData荣获信通院“生成式人工智能技术和应用优秀案例”奖|天天视讯
鹤壁市浚县卫贤镇尚村_貉子皮尚村最新价格|环球快资讯
阿里云AI新产品“通义听悟”重磅发布:快科技邀你免费用!
45元一杯"智商税"!酸奶刺客收割年轻人钱包 世界快讯
环球视讯!不愧为工作狂!马斯克深夜到访特斯拉上海超级工厂:查看新款Model 3
首发799元起 Redmi电竞显示器G27/G27Q开售:165Hz超高刷 全球快看
网红扎堆到麦地直播割麦 网友热议:很反感 流量噱头
2023新疆高考志愿投档规则
天天热点评!axi_crossbar IP使用说明
直播app源码技术开发知识:横竖屏功能的实现
编写Java代码时应该避免的6个坑
Linux实验文档
Python装饰器
全球热点评!国产GPU公司景嘉微募资42亿:研发高性能显卡 可用于大型游戏
积极拥抱生僻字!阿里普惠体推出3.0版本:免费商用-当前讯息
今日关注:为何坚持使用高压油箱?吉利研究院副院长:常压油箱不可能达标
音视频会议神器!阿里云通义听悟正式发布:轻松记录总结、实时翻译
2K-3K价位段无敌!Redmi K60斩获618首销双冠军|每日讯息
天天新消息丨淘宝开店多少钱能开直通车_淘宝开店多少钱
全球滚动:攻防世界_PWN_stack2
世界热头条丨MySQL表列数和行大小限制
天天观热点:为什么JS中0.1+0.2不等于0.3
美国会众议院通过债务上限法案 全球热点评
低到13.48万元起步 江西五十铃现款D-MAX年中大促_全球热点评
被人类幼崽萌化的瞬间:画面实在太可爱!祝愿大家六一快乐
访华后特斯拉股价大涨 马斯克重返世界首富宝座
播报:老外试驾法拉第未来FF 91被震撼:从未见过副驾驶有屏幕的车子
旧机福音 极限精简版Win10系统Tiny10更新:64位支持来了|全球百事通