在 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>
?
谢谢你的帮助!