C-带有矮人(和搬迁)的全局变量的位置

  • 本文关键字:全局变量 位置 c elf dwarf
  • 更新时间 :
  • 英文 :


当动态地将二进制文件与库链接时,重新定位信息用于绑定不同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 在主要可执行文件bliba.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技术的使用方式与图片代码中的使用方式相同。

最新更新