Linux动态链接库函数加载之GOT与Lazy Binding

本文详细介绍了Linux系统中,动态链接库如何利用GOT(全局偏移量表)和Lazy Binding进行函数加载。通过Glibc的"syscall"函数为例,展示了在位置无关代码PIC中,动态链接器如何在运行时确定函数地址,涉及过程链接表PLT、GOT表的使用,以及Lazy Binding的工作原理。
摘要由CSDN通过智能技术生成

Linux在运行与位置无关PIC(Position IndependentCode)的用户态程序并加载动态链接库时,函数符号的解析过程将涉及到全局偏移量表GOT(Global Offset Table)Lazy Binding("懒绑定")

 

在位置无关代码PIC中一般不能包含动态链接库中符号的绝对地址。当运行某个调用动态库函数符号的用户态程序时,用户态程序在编译链接阶段并不知晓该符号的具体位置,只有等到运行阶段,动态加载器将所需要的共享库加载到内存后,才最终确定符号的地址。而在编译阶段所有与位置无关的函数调用都将被保存到ELF文件的过程链接表PLT(Procedure Linkage Table)中。

 

现在通过GDB调试演示Glibc动态链接库中"syscall"函数的动态解析过程。源代码如下:

     1  /* syscall_test.cpp-- GOT and Lazy Binding mechanism debugging */
     …
    16  /* Sandbox needs to be configured with policy by init_sandbox.
    17   * New syscall 400 are reserved to config policy, then switch filter on!
    18   * but funcode=20 is specially reserved to directly ret -1 for debugging.
    19   */
    20  
    21  int init_sandbox()
    22  {
    …       /*policy configuration details ignored*/
    51  }
    52  
    53  int main()
    54  {
    55      init_sandbox();
    56      // here ignore the ret value check for init_sandbox
    57      // try to see if (400,20) return -1 or not
    58      int x = syscall(400,20);
    59      cout << "syscall(400,20)" << x << endl;
    …
    65      return 0;
    66  }

首先,反汇编包用户态程序,基本工具为readelf和objdump:

在编译阶段生成的ELF文件中,用于获取实际syscall地址的syscall@plt函数代码只有寥寥3条指令,事实上过程链接表PLT中的每个子函数都只有3条指令。

 

现在来分析syscall@plt:第1条指令”jmpq *0x20228a(%rip)”会跳转至GOT表中的某个位置。如果此时syscall是第一次被调用,那么GOT表中相应位置保存的是0x00400e06,即第2条指令的位置;如果syccall函数地址之前已经被解析完成,那么GOT表中相应位置保存的便是函数的实际地址,此时syscall@plt的第2,3条指令便不会被执行。这种机制就是所谓的Lazy Binding,即当且仅当动态库中函数符号第一次被调用时才去解析函数的实际位置,然后交由相应过程链接表PLT中的第2,3条指令完成函数实际地址的解析工作。也就是说,动态链接库中的函数符号只有在第一次被

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值