前文(聊聊Linux动态链接中的PLT和GOT(2)——延迟重定位)提到所有动态库函数的plt指令最终都跳进公共plt执行,那么公共plt指令里面的地址是什么鬼?

把test可执行文的共公plt贴出来:

080482a0 :

80482a0: pushl 0x80496f0

80482a6: jmp *0x80496f4

...

第一句,pushl 0x80496f0,是将地址压到栈上,也即向最终调用的函数传递参数。

第二句,jmp *0x80496f4,这是跳到最终的函数去执行,不过猜猜就能想到,这是跳到能解析动态库函数地址的代码里面执行。

0x80496f4里面住着是何方圣呢?下面使用gdb调试器将它请出来:

$ gdb -q ./test

...

(gdb)x/xw 0x80496f4

0x80496f4 8>: 0x00000000

(gdb) b main

Breakpoint 1 at 0x80483f3

(gdb) r

Starting program: /home/ivan/test/test/test

Breakpoint 1, 0x80483f3 in main ()

(gdb) x/xw 0x80496f4

0x80496f4 8>: 0xf7ff06a0

从调试过程可以发现,0x80496f4属于GOT表中的一项,进程还没有运行时它的值是0x00000000,当进程运行起来后,它的值变成了0xf7ff06a0。如果做更进一步的调试会发现这个地址位于动态链接器内,对应的函数是_dl_runtime_resolve。

嗯,是不是想到了什么呢。所有动态库函数在第一次调用时,都是通过XXX@plt -> 公共@plt -> _dl_runtime_resolve调用关系做地址解析和重定位的。

谈到这里,其实还有谜底是没有解开的,以printf函数为例:

_dl_runtime_resolve是怎么知要查找printf函数的

_dl_runtime_resolve找到printf函数地址之后,它怎么知道回填到哪个GOT表项

到底_dl_runtime_resolve是什么时候被写到GOT表的

前2个问题,只需要一个信息就可以了知道,这个信息就在藏在在函数对应的xxx@plt表中,以printf@plt为例:

printf@plt>:

jmp *0x80496f8

push $0x00

jmp common@plt

第二条指令就是秘密所在,每个xxx@plt的第二条指令push的操作数都是不一样的,它就相当于函数的id,动态链接器通过它就可以知道是要解析哪个函数了。

真有这么神吗?这不是神,是编译链接器和动态链接器故意安排的巧合罢了。

使用readelf -r test命令可以查看test可执行文件中的重定位信息,其中.rel.plt这一段就大有秘密:

$ readelf -r test

....

Relocation section '.rel.plt' at offset 0x25c contains 3 entries:

Offset Info Type Sym.Value Sym. Name

080496f8 00000107 R_386_JUMP_SLOT 00000000 puts

080496fc 00000207 R_386_JUMP_SLOT 00000000 __gmon_start__

08049700 00000407 R_386_JUMP_SLOT 000000000 __libc_start_main

再看看各函数plt指令中的push操作数:

printf对应push 0x0

gmon_start对应push 0x8

__libc_start_main对应push 0x10

这3个push操作数刚好对应3个函数在.rel.plt段的偏移量。在_dl_runtime_resolve函数内,根据这个offset和.rel.plt段的信息,就知道要解析的函数。再看看.rel.plt最左边的offset字段,它就是GOT表项的地址,也即_dl_runtime_resolve做完符号解析之后,重定位回写的空间。

第三个问题:到底_dl_runtime_resolve是什么时候被写到GOT表的。

答案很简单,可执行文件在Linux内核通过exeve装载完成之后,不直接执行,而是先跳到动态链接器(ld-linux-XXX)执行。在ld-linux-XXX里将_dl_runtime_resolve地址写到GOT表项内。

事实上,不单单是预先写_dl_runtime_resolve地址到GOT表项中,在i386架构下,除了每个函数占用一个GOT表项外,GOT表项还保留了3个公共表项,也即got的前3项,分别保存:

got[0]: 本ELF动态段(.dynamic段)的装载地址

got[1]:本ELF的link_map数据结构描述符地址

got[2]:_dl_runtime_resolve函数的地址

动态链接器在加载完ELF之后,都会将这3地址写到GOT表的前3项。

其实上述公共的plt指令里面,还有一个操作数是没有分析的,其实它就是got[1](本ELF的link_map)地址,因为只有link_map结构,结合.rel.plt段的偏移量,才能真正找到该elf的.rel.plt表项。

有兴趣的读者可以使用gdb,在执行到main函数时,将GOT表的这3项数据看一下,验证一下。

好了,谈到这里是否对PLT和GOT机制有个更清晰认识了呢?最后一篇会使用图文结构将整个PLT/GOT机制串起来。

linux got分析,聊聊Linux动态链接中的PLT和GOT(3)——公共GOT表项相关推荐

  1. 聊聊Linux动态链接中的PLT和GOT(3)——公共GOT表项

    前文(聊聊Linux动态链接中的PLT和GOT(2)--延迟重定位)提到所有动态库函数的plt指令最终都跳进公共plt执行,那么公共plt指令里面的地址是什么鬼? 把test可执行文的共公plt贴出来 ...

  2. 聊聊Linux动态链接中的PLT和GOT(1)——何谓PLT与GOT

    在介绍PLT和GOT出场之前,先以一个简单的例子引入两个主角,各位请看以下代码: #include <stdio.h>void print_banner() {printf("W ...

  3. linux 统计_聊聊 Linux 的内存统计

    写在前面 本文主要分析 Linux 系统内存统计的一些指标以及进程角度内存使用监控的一些方法. 开始阅读这篇文章前,请先简单阅读下面的几篇文章. <进程眼中的线性地址空间> <线程眼 ...

  4. linux内核分析期末,Linux内核分析作业

    Linux内核分析课程期末大作业 一.程序的主要设计思路及实现方式 在Linux内核中,存在一个全局变量:init_task.该变量即是Linux第一个启动的用户空间进程init对应的task_str ...

  5. linux修改http版本信息,动态库中的soname中版本号的修改

    soname(简单共享名,Short for shared object name),在linux下使用动态库时,经常会发现明明编译时指定的是libA.so,可是程序运行时或通过ldd查看依赖却是li ...

  6. linux make指定目标平台,CMake on Linux:目标平台不支持动态链接

    我很简单 CMakeLists.txt CMAKE_MINIMUM_REQUIRED(VERSION 2.8) FIND_PACKAGE(VTK REQUIRED) PROJECT(test CXX) ...

  7. linux kdump 分析工具,Ubuntu 15.10中的Kdump工具实战

    Step 1: 安装kdump and crash工具 sudo apt-get install linux-crashdump Step 2: 安装kernel的符号文件 可以先用apt-cache ...

  8. Linux命令行下载OneDrive分享链接中的文件

    我所知的某个游戏分享站喜欢用OneDrive来分享游戏,用OneDrive很好,抵制百度网盘我强烈支持,但是OneDrive国内有时候抽风比较厉害,而在国外OneDrive下载几乎能跑满带宽,我G口的 ...

  9. linux内核分析 轮换,Linux 内核源代码情状分析 chap2 存储管理 (6) - 页面的定期换出...

    1. 目的 Linux 内核通过定期检查并且预先将若干页面换出, 实现减轻系统在缺页异常时候所产生的负担. 虽然, 无法避免需要临时寻找可以换出的页面, 但是, 可以减少这种事件发生的概率.Linux ...

最新文章

  1. Vue开发跨端应用(二)修改electron demo
  2. css div 边缘渐变,围绕div的CSS3渐变边框
  3. 精准营销的核心思维何在?
  4. 激光SLAM学习--多种类激光雷达介绍(单线、多线)
  5. 一周学习总结PPT-学会VLOOKUP函数,1分钟搞定数据汇总
  6. 使用 node.js 进行服务器端 JavaScript 编程
  7. 深入JVM系列(二)之GC机制、收集器与GC调优
  8. 【Machine Learning】监督学习、非监督学习及强化学习对比
  9. Mac远程服务器文件上传rz和sz的安装使用
  10. 成都市交委与摩拜科技联手 助推智慧城市建设
  11. MSDN 精简版 1.6
  12. mouseenter和mouseleave跟mouseover和mouseout
  13. 色谱计算机常用英文,色谱术语的常用中英文对照
  14. AspUpload组件的方法中文说明
  15. DOORS vs DNG
  16. object mapping for [details] tried to parse field [details] as object, but found concrete value
  17. java datetime转int_java日期int和String互转
  18. 密码的显示与隐藏php,el-input 标签中密码的显示和隐藏功能的实例代码
  19. 上汽招聘项目管理PMO(地点:上海,薪酬面议)
  20. 7-5 宿舍谁最高? (20 分)

热门文章

  1. __try,__except,__finally,__leave异常模型机
  2. OpenCV 中的图像处理 004_平滑图像
  3. Linux 平台 C/C++ 代码中设置线程名
  4. 假笨说-谨防JDK8重复类定义造成的内存泄漏
  5. Redis的内存淘汰策略问题
  6. 快手于冰:跟最优秀的人一起追求极致
  7. 大牛书单 | 搜索大牛都读什么书?
  8. PMP之项目整合管理
  9. Openstack 与VMware 不同CPU迁移原理
  10. Raft 一致性算法论文译文