当动态地将二进制文件与库链接时,重新定位信息用于绑定不同ELF对象的变量/功能。但是,矮人不受搬迁的影响:调试器应该如何解决全局变量?
假设我有liba.so(A.C)定义一个全局变量(使用GCC或GCC或Clang使用GNU/Linux):
#include <stdio.h>
int foo = 10;
int test(void) {
printf("&foo=%pn", &foo);
}
和针对liba.so(B.C)链接的程序B:
#include <stdio.h>
extern int foo;
int main(int argc, char** argv) {
test();
printf("&foo=%pn", &foo);
return 0;
}
我希望" foo"将在liba中进行安装。但是实际上,它在liba.so和b:
中都构成$ ./b
&foo=0x600c68 # <- b .bss
&foo=0x600c68 # <- b .bss
使用(b和lib.so)使用的foo变量在B的.bss中而不是在liba.so:
[...]
0x0000000000600c68 - 0x0000000000600c70 is .bss
[...]
0x00007ffff7dda9c8 - 0x00007ffff7dda9d4 is .data in /home/foo/bar/liba.so
0x00007ffff7dda9d4 - 0x00007ffff7dda9d8 is .bss in /home/foo/bar/liba.so
foo变量是两次启动的:
一次在liba.so中(与程序b链接时未使用此实例)
在B中一次(在B中使用此实例)。
(我真的不明白为什么在可执行文件中启动该变量。)
矮人信息中只有B(预期)中的声明:
$ readelf -wi b
[...]
<1><ca>: Abbrev Number: 9 (DW_TAG_variable)
<cb> DW_AT_name : foo
<cf> DW_AT_decl_file : 1
<d0> DW_AT_decl_line : 3
<d1> DW_AT_type : <0x57>
<d5> DW_AT_external : 1
<d5> DW_AT_declaration : 1
[...]
,在liba.so中找到了一个位置:
$ readelf -wi liba.so
[...]
<1><90>: Abbrev Number: 5 (DW_TAG_variable)
<91> DW_AT_name : foo
<95> DW_AT_decl_file : 1
<96> DW_AT_decl_line : 3
<97> DW_AT_type : <0x57>
<9b> DW_AT_external : 1
<9b> DW_AT_location : 9 bloc d'octets: 3 d0 9 20 0 0 0 0 0 (DW_OP_addr: 2009d0)
[...]
此地址是liba.so(.data)中Foo(未添加)实例的位置。
- 我最终获得了2个foo Global变量的实例(在liba.so中,一个在b中);
- 只有第一个可以用矮人看到;
- 只有SECONE ONE。
调试器应该如何解析FOO全局变量?
我不太了解为什么该变量在可执行文件中进行启动。
您可以在这里找到答案。
调试器应该如何解析foo Global变量
debugger读取符号表(除了调试信息之外),并且 foo
dis 在主要可执行文件b
和 liba.so
:
nm b | grep foo
0000000000600c68 B foo
(我阅读了 @employed俄语提供的Oracle DOC。)
为非PIC代码完成了全局变量的恢复,以便以非PIC的方式放置变量,而无需修补非PIC代码:
- 该变量的副本已针对非PIC代码;
- 该变量已在可执行文件中安装;
- 副本重定位指令用于在动态链接时间上从源共享的objet复制数据;
- 未使用共享objet中的实例(完成重新定位后)。
复制重定位指令:
$readelf -r b
Relocation section '.rela.dyn' at offset 0x638 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000600c58 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000600ca8 001200000005 R_X86_64_COPY 0000000000600ca8 foo + 0
对于函数,got plt技术的使用方式与图片代码中的使用方式相同。