0

在 Stack 上回答另一个问题时,我自己也遇到了一个问题。在 shared.c 中使用以下代码:

#include "stdio.h"

int glob_var = 0;

void shared_func(){
    printf("Hello World!");
    glob_var = 3;
}

编译:

gcc -shared -fPIC shared.c -oshared.so

如果我用 反汇编代码objdump -D shared.so,我会得到以下信息shared_func

0000000000001119 <shared_func>:
    1119:   f3 0f 1e fa             endbr64 
    111d:   55                      push   %rbp
    111e:   48 89 e5                mov    %rsp,%rbp
    1121:   48 8d 3d d8 0e 00 00    lea    0xed8(%rip),%rdi        # 2000 <_fini+0xebc>
    1128:   b8 00 00 00 00          mov    $0x0,%eax
    112d:   e8 1e ff ff ff          callq  1050 <printf@plt>
    1132:   48 8b 05 9f 2e 00 00    mov    0x2e9f(%rip),%rax        # 3fd8 <glob_var@@Base-0x54>
    1139:   c7 00 03 00 00 00       movl   $0x3,(%rax)
    113f:   90                      nop
    1140:   5d                      pop    %rbp
    1141:   c3                      retq

使用readelf -S shared.so,我得到(对于 GOT):

[22] .got              PROGBITS         0000000000003fd8  00002fd8
     0000000000000028  0000000000000008  WA       0     0     8

如果我错了,请纠正我,但是,看看这个,访问的重定位glob_var似乎是通过 GOT。正如我在一些网站上所读到的,这是由于 x86-64 机器代码的限制,其中 RIP 相对寻址被限制为 32 位偏移量。这个解释让我不太满意,因为由于全局变量在同一个共享对象中,所以保证在自己的数据段中可以找到。因此可以使用 RIP 相对寻址来访问全局变量而不会出现问题。

glob_var如果已声明GOT 重定位,我会理解,extern但在这种情况下,它是在同一个共享对象中定义的。为什么 gcc 需要通过 GOT 进行重定位?是因为它无法检测到全局变量是在同一个共享对象中定义的吗?

相关: 为什么在使用 GOT 引用的共享对象中定义非静态全局变量?

以上是11岁,没有回答我的问题,因为那里似乎没有合适的答案。

奖励:<glob_var@@Base-0x54>反汇编是什么意思shared_func?为什么不是<glob_var@GOT>

谢谢你的帮助!

4

0 回答 0