静态链接与动态链接过程

静态链接

静态链接三个步骤:

  • 布局(将相同节合并,如 text 节,data 节,原本以0地址为参考的地址现在要变到相对全局的位置)
  • 符号解析(查其它文件以填写未定义的符号的地址)
  • 重定位(将代码中函数调用/变量地址确定下来,由相对地址变绝对地址)

对于静态库中的模块,只链接抽取用到的符号

动态链接

gcc -Og -fPIC a.c -o a.so // PIC 位置无关代码

动态链接步骤:

  1. 生成可执行文件
    • 在 .bss 节分配动态库中的全局变量(包括.data和.bss中的变量),并将 .got 中表项指向那个变量,运行时才将其初始值从动态库复制过来
    • 在 .plt 中分配动态库中函数的函数入口表项,表项值在运行时才填写
  2. 装载程序
    • 根据 .interp 节存的动态库路径名找到动态库数据和代码,映射到进程内存空间
    • .data .bss 节中变量初始值从动态库复制过来(到 .bss 节对应变量上),装载变量的 got 表项
    • 当第一次调用一个动态函数时,跳转到plt表,表项指向got表中对应项的地址,这时这个地址指向的还是之前plt表表项的下一行,这一行做的是把函数对应的标号压栈,然后下一行跳至plt表的统一入口,执行跳转至got表的统一入口,这个入口处做的是根据标号把got表项地址改为重定向的地址。以后再调用函数时,进入plt表项,跳入got表项时就是函数的入口地址了。
      • 第一次:plt项->got项->plt项的下一行(取标号)->plt统一入口->got统一入口->修改got表项并进入函数入口
      • 以后:plt项->got项->函数入口

补充:

  • .got (全局偏移表)节存有一个间接引用变量的表,每个表项是一个变量或函数入口的地址,这些地址初始是0,当加载程序时才指向进程中分配的变量的地址,当调用函数时才指向进程中函数入口地址。

  • .data .bss 节(初始化与未初始化0变量节)存的是变量初始值,进程在 .bss 节为变量分配空间时,相应 got 表项将指向这些变量

  • .text 代码中使用的变量地址为 .so 文件中用这个变量的指令地址到 .got 中相应表项的相对地址,加载时会重计算

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值