Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 具有DWARF的全局变量的位置(和重定位)_C_Elf_Dwarf - Fatal编程技术网

C 具有DWARF的全局变量的位置(和重定位)

C 具有DWARF的全局变量的位置(和重定位),c,elf,dwarf,C,Elf,Dwarf,将二进制文件与库动态链接时,重定位信息用于绑定不同ELF对象的变量/函数。然而,DWARF不受重新定位的影响:调试器应该如何解析全局变量 假设liba.so(a.c)定义了一个全局变量(使用GNU/Linux和GCC或Clang): foo变量实例化两次: 一旦进入liba.so(与程序b链接时不使用此实例) 在b中使用一次(此实例用于b中其他实例的实例) (我真的不明白为什么变量会在可执行文件中实例化。) 在DWARF信息中,b中只有一个声明(如预期的那样): $ readelf -wi

将二进制文件与库动态链接时,重定位信息用于绑定不同ELF对象的变量/函数。然而,DWARF不受重新定位的影响:调试器应该如何解析全局变量

假设liba.so(a.c)定义了一个全局变量(使用GNU/Linux和GCC或Clang):

foo变量实例化两次:

  • 一旦进入liba.so(与程序b链接时不使用此实例)

  • 在b中使用一次(此实例用于b中其他实例的实例)

(我真的不明白为什么变量会在可执行文件中实例化。)

在DWARF信息中,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
[...]
$readelf-wi b
[...]
:Abbrev编号:9(DW_标记_变量)
DW_AT_名称:foo
DW_AT_decl_文件:1
德克卢线的德瓦卢:3
DW_AT_类型:
DW_在_外部:1
DW_AT_声明:1
[...]
在liba中找到了一个位置。因此:

[...]
0x0000000000600c68 - 0x0000000000600c70 is .bss
[...]
0x00007ffff7dda9c8 - 0x00007ffff7dda9d4 is .data in /home/foo/bar/liba.so
0x00007ffff7dda9d4 - 0x00007ffff7dda9d8 is .bss in  /home/foo/bar/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)
[...]
$readelf-wi liba.so
[...]
:Abbrev编号:5(DW_标记_变量)
DW_AT_名称:foo
DW_AT_decl_文件:1
德克卢线的德瓦卢:3
DW_AT_类型:
DW_在_外部:1
地点:9个八位组:3 d0 9 20 0 0 0(地址:2009d0)
[...]
此地址是liba.so(.data)中foo的(未命名)实例的位置

  • 最后我得到了foo全局变量的两个实例(liba.so中的on和b中的一个)
  • 只有第一个能被矮人看到
  • 只使用secone
调试器应该如何解析foo全局变量

我真的不明白为什么变量会在可执行文件中实例化

你可以找到答案

调试器应该如何解析foo全局变量

调试器读取符号表(除调试信息外),
foo
确实在主可执行文件
b
liba中定义。因此

nm b | grep foo
0000000000600c68 B foo
(我阅读了@Employed俄语提供的Oracle文档。)

对非PIC代码执行全局变量重新实例化,以便在不修补非PIC代码的情况下以非PIC方式取消对变量的引用:

  • 非PIC代码复制变量
  • 变量在可执行文件中实例化
  • 复制重定位指令用于在动态链接时从源共享对象复制数据
  • 不使用共享对象中的实例(在重新定位复制完成后)
复印搬迁说明:

$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技术的使用方式与PIC代码中的使用方式相同

$ 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)
[...]
nm b | grep foo
0000000000600c68 B foo
$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