got & plt

got plt类似与Windows PE文件中IAT(Import Address Table)。

要使的代码地址无关,基本思想就是把与地址相关的部分放到数据段里面。

ELF的做法是在数据段里面建立一个指向这些变量的指针数组,称为全局偏移表(Global Offset Table,GOT),当代码需要引用该全局变量时,可以通过GOT中相对应的项间接引用。

GOT本身是放在数据段,所以可以在模块加载时被修改。延迟绑定,基本思想就是当函数第一次被用到时才进行绑定

一段非常简单的代码:

#include <stdio.h>
#include <stdlib.h>

int helloWorld(){
    printf("HelloWorld\n");
    return 0;
}

int main(){
    helloWorld();
    return 0;
}

第一条指令是通过GOT间接跳转的指令。如果连接器在初始化阶段已经初始化该项,并且将puts()的地址填充入该项,那么这个跳转指令的结果就是我们所期望的,跳转到puts(),实现函数正确调用。

但是为了实现延迟绑定,链接器在初始化阶段并没有将puts()的地址填入该项,而是将下一条指令的地址填入到[email protected]项中。

所以第一条指令的效果是跳转到第二条指令,相当于是没有任何操作的。第二条指令是将一个数字n压入堆栈,这个数字是puts()的符号引用在重定位表".rel.plt"中的下标。

接着又是一条push指令将模块ID压入到堆栈,然后跳转到0xf7ff04f0执行,那么这个地址是什么地址?答案是_dl_runtime_resolve,下文会给出解释。

ELF将GOT拆分为两个表,".got"和".got.plt"。其中".got"用来保存全局变量引用的地址,“.got.plt”用来保存函数引用的地址,对于外部函数的引用全部放在".got.plt"中。

通过上面两幅图可以看出:R_386_GLOB_DAT是位于.got段的,R_386_JUMP_SLOT位于.got.plt 段。

".got.plt"前三项是有特殊意义的。

第一项保存的是“.dynamic”段的地址;

第二项保存的是本模块的ID,也就是之前看到的push进的那个值;

第三项保存的是_dl_runtime_resolve()函数的地址,之前跳转的地址0xf7ff04f0。

之后就是地址,可以看到都是指向.plt段中,在链接时,.plt段通常和代码段等一起合并成一个可读可执行的Segment。

可以看到[email protected]的地址0x80482f6位于.plt 中。而且puts在got表项中存放的地址0x080482f6就是[email protected]第二条指令的地址。

参考资料:

《程序员的自我修养》动态链接

《深入理解计算机系统》第七章,链接

时间: 2024-10-07 09:26:01

got & plt的相关文章

python之plt画图之格式化颜色和线形

import matplotlib.pyplot as plt 在ipython中输入 plt.plot? The following format string characters are accepted to control the line style or marker: ================    =============================== character           description ================    ===

基于Android的ELF PLT/GOT符号重定向过程及ELF Hook实现

转自:http://blog.csdn.net/l173864930/article/details/40507359 引言 写这篇技术文的原因,主要有两个: 其一是发现网上大部分描述PLT/GOT符号重定向过程的文章都是针对x86的,比如<Redirecting functions in shared ELF libraries>就写得非常不错.虽然其过程跟ARM非常类似,但由于CPU体系不同,指令实现差异非常大: 其二是网上大部分关于ELF文件格式的介绍,都是基于链接视图(Linking

如何将图纸转换为PDF、JPG、PNG、plt、DWF、DWFx、XPS等格式文件

分类:CAD批量打图精灵 内容提要:本文讲解如何将多张图纸换换为单个PDF:如何将将图纸转换为图片格式文件. 如果您要将多张图纸转换为单个PDF则需要用到pdfFactory虚拟打印机,在“基本打印设置”标签下,打印机选“pdfFactory Pro”,勾选“打印到文件”复选框,保存方式选择“多个图纸到单个文件(夹)”. 有多张图纸,若要将单张图纸里的多张图转换为单个PDF,按上面设置,不同点在于保存方式选择“单个图纸到单个文件(夹)”. 如要将图纸打印单个为单个PDF,请选择“DWG To P

Linux动态链接之GOT与PLT

转载于:http://www.cnblogs.com/xingyun/archive/2011/12/10/2283149.html 我们知道函数名就是一个内存地址,这个地址指向函数的入口.调用函数就是压入参数,保存返回地址,然后跳转到函数名指向的代码.问题是,如果函数在共享库中,共享库加载的地址本身就不确定,函数地址也就不确定了,那如何调用共享库中的函数呢?这就是本文要回答的. 我们先来看一小段代码(test.c): #include <stdio.h>void hello_world(vo

PLT文件 和 DXF文件

PLT: CAM/CAD类似软件处理的图像文件的文件格式 DXF: AutoCAD(Drawing Interchange Format或者Drawing Exchange Format) 绘图交换文件. DXF 是Autodesk公司开发的用于AutoCAD与其它软件之间进行CAD数据交换的CAD数据文件格式. DXF是一种开放的矢量数据格式,可以分为两类:ASCII格式和二进制格式:ASCII具有可读性好,但占有空间较大: 二进制格式占有空间小.读取速度快.由于Autocad现在是最流行的c

elf文件中的.plt .rel.dyn .rel.plt .got .got.plt的关系

.plt的作用是一个跳板,保存了某个符号在重定位表中的偏移量(用来第一次查找某个符号)和对应的.got.plt的对应的地址 .rel.dyn保存了.got段的开始地址,未证明 .rel.plt保存了重定位表的信息 .got据说是保存了elf文件本身的各个符号的偏移量,即不要动态链接,未证明 .got.plt保存了重定位地址. 比如printf是一个重定位符号,需要连接该符号时过程是这样: main函数call  .plt段中的一个地址,这里的第一句话就是调转到.got.plt中的保存的print

理解got和plt

共享库是现代操作系统的一个重要组成部分,但是我们对它背后的实现知之甚少.当然,很多文档从各个角度对动态库进行过介绍.希望我的这边文章能给对动态库的理解带来一种新的理解. 让我们以此开始--在elf格式中,重定位记录是一些允许我们稍后填写的二进制信息--链接阶段由编译工具填充或者在运行时刻由动态连接器填写.一个二进制的重定位记录从本质上说就是"确定符号X的值,然后把这个值放入二进制文件中的偏移量为Y的地方"--每一个重定向记录都有个特定的类型,这个类型在ABI文档中定义,用来准确的描述在

Android漫游记(3)---重定位之GOT &amp; PLT &amp; R_ARM_JUMP_SLOT

Android系统的动态链接工具是/system/bin/linker(一般的Linux系统是ld.so),虽然名字不同,但是基本的动态链接过程是类似的.需要注意的一点是,Linux一般是Lazy,即所谓的"懒"加载方式,但是Android系统有点区别,是非Lazy方式,即所有的重定位操作,在进程首次执行以前已经全部完成.这大概也是Android应用首次启动比较慢的原因之一吧! 关于Android系统的PLT和GOT可以写上一篇高考作为,在这里就不提概念性的东西了,网上有一篇博文:ht

plt.spy()函数

spy()以图片的方式表示系数矩阵 Demo import matplotlib.pyplot as plt import numpy as np a = np.array([[0,4,5,6,7], [5,0,6,6,0], [0,4,5,0,7], [1,4,0,6,3], [1,0,5,2,1]]) plt.spy(a) plt.show()