2014-02-05 5 views
3

При динамической связывании двоичного кода с библиотеками информация о перемещении используется для связывания переменных/функций различных объектов ELF. Однако DWARF не зависит от перемещения: как отладчик должен разрешать глобальные переменные?Расположение глобальных переменных с DWARF (и перемещением)

Скажем, у меня есть liba.so (ас), определяющего глобальную переменную (с помощью GNU/Linux с помощью GCC или Clang):

#include <stdio.h> 

int foo = 10; 

int test(void) { 
    printf("&foo=%p\n", &foo); 
} 

и программы б связаны с liba.so (РМЖ):

#include <stdio.h> 

extern int foo; 

int main(int argc, char** argv) { 
    test(); 
    printf("&foo=%p\n", &foo); 
    return 0; 
} 

Я ожидаю, что «Foo» будет инстанциирован в liba.so , но на самом деле это инстанциирован в обоих liba.so и б:

$ ./b 
&foo=0x600c68 # <- b .bss 
&foo=0x600c68 # <- b .bss 

Переменная Foo, который используется (как по б и lib.so) находится в .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 (данный экземпляр не используется, когда связан с программой б)

  • один раз в б (этот экземпляр используется экземпляр другого в б).

(я не понимаю, почему переменная инстанциирован в исполняемый файл.)

Существует только декларация в Ь (как и ожидалось) в информаций карликовых:

$ 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) 
[...] 

Этот адрес является местонахождение (unsued) в позиция foo в liba.so (.data).

  • В итоге я получаю 2 экземпляра глобальной переменной foo (в liba.so и один в b);
  • только первый вид с DWARF;
  • только один secone используется.

Как отладчик должен разрешить глобальную переменную foo?

ответ

1

Я действительно не понимаю, почему переменная инстанцируется в исполняемом файле.

Вы можете найти ответ here.

Как отладчик должен решить этот Foo глобальной переменной

отладчик читает таблицы символов (в дополнение к отлаживать информации), и fooделает получить определенные как в основной исполняемый файл b, а в liba.so:

nm b | grep foo 
0000000000600c68 B foo 
0

(я прочитал документ Oracle предоставленный @Emp . Loyed России)

Глобальная переменная reinstanciation делается для не ПОС код, чтобы разыменования переменной таким образом, не ПОС без заплат на не-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 

Для функций, ПРТ + PLT метод используется так же, как они используются в коде ПОС.

 Смежные вопросы

  • Нет связанных вопросов^_^