首页 > 解决方案 > GDB 在 PLT 部分显示错误的跳转地址

问题描述

我编写了以下示例来掌握 PLT/GOT 部分。

共享库libshar代码:

shared.h

int sum(int a, int b);

shared.c

#include "shared.h"

int sum(int a, int b){
    return a + b;
}

可执行bin_shared代码:

#include <stdio.h>
#include "shared.h"

int main(void){
    printf("Starting the programm... \n");
    int s = sum(1, 2); //<=== I expected the dynamic linker would be called here
    int s2 = sum(2, 3);
    printf("s = %d, s2 = %d\n", s, s2);
}

所以我编译并将共享库与可执行文件链接起来,并编写了以下 gdb-script 以进入动态链接器代码。我希望它在第一次调用sum.

set pagination off

file build/bin_shared
b main
commands
    layout asm
    info proc mappings
end
r

我遇到了两个问题:

I.main函数入口的断点被击中时已经映射info proc mappings显示libshar.so

0x7ffff7bd3000     0x7ffff7bd4000     0x1000        0x0 /home/me/c/build/libshar.so
0x7ffff7bd4000     0x7ffff7dd3000   0x1ff000     0x1000 /home/me/c/build/libshar.so
0x7ffff7dd3000     0x7ffff7dd4000     0x1000        0x0 /home/me/c/build/libshar.so
0x7ffff7dd4000     0x7ffff7dd5000     0x1000     0x1000 /home/me/c/build/libshar.so

sum尚未调用共享库函数。为什么它已经迫不及待地加载了?

二、第一次进入sum@plt时,我看到以下asm:

0x555555554690 <sum@plt>   jmp    QWORD PTR [rip+0x200932]        # 0x555555754fc8

正如预期的那样,这是指向 GOT 的指针:

(gdb) disassemble 0x555555754fc8
Dump of assembler code for function _GLOBAL_OFFSET_TABLE_:

但问题是此时单步指令会gdb直接进入

0x7ffff7bd3580 <sum>            lea    eax,[rdi+rsi*1]   

这意味着指向 GOT 的指针已经被实际的函数指针覆盖,但 gdb 仍然显示 GOT 指针。这是为什么?

jmp我在to地址中提取了原始内存,GOT希望找到被覆盖的地址,但它看起来不像:

(gdb) x/2xg 0x555555554690
0x555555554690 <sum@plt>:       0x01680020093225ff      0xffffffd0e9000000

标签: clinuxassemblygdbshared-libraries

解决方案


为什么它已经迫不及待地加载了?

因为动态加载器是您直接链接mmap所有共享库。

如果您希望按需加载共享库,则必须使用dlopen而不是将二进制文件与libshar.so.

指向 GOT 的指针已经被实际的函数指针覆盖,但 gdb 仍然显示 GOT 指针。这是为什么?

两种可能原因之一:

  1. 您已LD_BIND_NOW在环境中设置或
  2. 您的二进制文件已链接到-Wl,-z,now(这可能是较新的 Linux 发行版上的默认值)。

您可以通过以下方式检查上述 2 是否为真:

readelf -d bin_shared | grep FLAGS

对于-z now二进制文件,您会看到:

  0x000000000000001e (FLAGS)              BIND_NOW

推荐阅读