Linux plt表调用汇编代码分析

linux调用共享库中的函数时通过plt表和got表实现位置无关代码,过程中涉及到lazy binding,即在第一调用外部函数时解析被调用的函数地址并将地址写入到got表,后续调用则不需要解析函数地址,具体过程如下

1.c程序如下

#include <stdio.h>
#include <cstub.h>
#include <dlfcn.h>
extern void a();
int main()
{
        a();
        int i=1;
}

2.c程序文件如下

#include <stdio.h>

void a()
{
        void *b = printf;
        printf("hahahaha\n");
}

编译参数如下

gcc -g  1.c -I. -L. -la -ldl -z lazy
gcc -g -fPIC -shared 2.c -o liba.so

使用gdb调试a.out,在main上下断点,反汇编main函数如下

可以看出程序时通过0x401030这个地址来调用a函数,反编译0x401030如下

 0x401030这个地址反编译对应着plt表,jmpq *0x2fe2(%rip) 是 x86-64 架构中的一条跳转指令。我们来逐部分分析这条指令的含义:

  1. jmpq: 这是一个跳转指令,jmp 表示无条件跳转(jump),q 表示这是一个 64 位的跳转("quad" 的缩写)。

  2. 0x2fe2(%rip): 这里使用的是相对寻址模式,%rip 是指令指针寄存器(Instruction Pointer Register),它指向当前正在执行的指令的地址。0x2fe2 是一个偏移量,表示从当前指令的地址向前或向后偏移 0x2fe2 字节。也就是说,0x2fe2(%rip) 将计算出一个地址,这个地址是当前指令地址加上 0x2fe2。

  3. *0x2fe2(%rip): 星号(*)表示将这个计算出的地址作为跳转目标,而不是直接跳转到一个固定的地址。也就是说,指令会跳转到由 0x2fe2(%rip) 指向的地址。

  4. 使用x读取这个地址内容,发现对应应位置是got表内容,值未0x401036,对应着上图pushq这条汇编指令,即程序执行完plt表第一条jumq后紧接着执行pushq %0;jump 0x401020,0x401020保存了解析a函数地址的代码。

 执行r命令,并执行到int i=1这行代码,此时程序执行完a函数并输出,再次查看got表内容,可以发现got表对应的值改变为0x00007ffff7fcb105,反汇编a函数,可以看出a函数的地址也为0x00007ffff7fcb105,因此后续在调用a函数是,程序通过jmpq *0x2fe2(%rip) 这句指令跳转到a函数真实地址并执行a函数。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值