通过GDB调试理解GOT/PLT

来源:互联网 发布:unity3d water 编辑:程序博客网 时间:2024/06/08 19:43

本文转载自
通过GDB调试理解GOT/PLT
Position Independent Code (PIC) in shared libraries
GOT(Global Offset Table):全局偏移表用于记录在ELF文件中所用到的共享库中符号的绝对地址。在程序刚开始运行时GOT表项是空的,当符号第一次被调用时会动态解析符号的绝对地址然后转去执行,并将被解析符号的绝对地址记录在GOT中,第二次调用同一符号时,由于GOT中已经记录了其绝对地址,直接转去执行即可,不用重新解析。
PLT(Procedure Linkage Table):过程链接表的作用是将位置无关的符号转移到绝对地址。当一个外部符号被调用时,PLT去引用GOT中的其符号对应的绝对地址,然后转入并执行。
GOT位于.got.plt section中,PLT位于.plt section中。下面给出一示例程序。

#include <stdio.h>#include <stdlib.h>int main(int argc, char* argv[]){    if(argc < 2)    {        printf("argv[1] required!\n");        exit(0);    }    printf("You input: ");    printf(argv[1]);    printf("Down\n");    return 0;}

编译该程序。

gcc -o format format.c

然后我们通过readelf命令来查看format程序的section信息,并检查GOT。
这里写图片描述
这里写图片描述
.rel.dyn记录了加载时需要重定位的变量,.rel.plt记录的是需要重定位的函数。接下来,我们使用gdb来对程序进行调试,观察程序在调用printf函数时GOT的变化情况。因为程序逻辑需要输入参数,设置好参数后,在主函数处下断点,然后运行,单步调试来到printf函数调用的地方。
这里写图片描述
0x80484ab处的指令为call 0x8048330 <printf@plt>,然后查看一下 0x8048330处的代码。
这里写图片描述
可以看到流程会跳转到ds:0x804a00c处,而0x804a00c是printf重定位偏移(查看上面GOT信息图),接着看一下后面的流程都做了什么。
这里写图片描述
这里写图片描述
根据上面的流程分析进行单步调试,当动态解析(_dl_runtime_resolve)完成后,流程会直接跳转到printf函数主体。上面我们说过,当第一次调用符号时会动态解析其绝对地址并写到GOT中,下次调用的时候就不用再次解析了,我们来看看这个时候原先0x804a00c处的指向情况。
这里写图片描述
其所指向的地址正好为第一次解析后得到的printf函数的入口地址。两次调用的流程如下。
这里写图片描述
这里写图片描述

1 0
原创粉丝点击