zoukankan      html  css  js  c++  java
  • 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
    ");
        return 0;
    }
    
    int main(){
        helloWorld();
        return 0;
    }

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

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

    所以第一条指令的效果是跳转到第二条指令,相当于是没有任何操作的。第二条指令是将一个数字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。

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

    参考资料:

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

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

  • 相关阅读:
    html5 geolocation配合百度地图api实现定位
    ES6 Symbol
    es2018(es9)前瞻
    Vue探索历程(一)
    数独游戏的难度等级分析及求解算法研究1——关于数独
    关于谋生的一些想法
    加密的pdf转换为jpg
    数独游戏的难度等级分析及求解算法研究2——数独难度等级
    NSString NSData char* NSInteger的转换
    根据文字多少自动设置UILabel的宽度高度
  • 原文地址:https://www.cnblogs.com/lanrenxinxin/p/5573018.html
Copyright © 2011-2022 走看看