Ваша общая библиотека, созданная с отладочной информацией, ссылается на неопределенный внешний
переменная, как в примере, который я собираюсь построить:
foo.cpp
namespace bar {
extern int undefined;
};
int foo()
{
return bar::undefined;
}
Я помещаю неопределенный символ в пространство имен, чтобы получить случай, когда он
переименовано в компоновщик, так как вы говорите о C ++.
Компиляция и ссылка с отладочной информацией:
$ g++ -shared -g -fPIC -o libfoo.so foo.cpp
Вот оно в таблице символов библиотеки, raw:
$ nm --undefined-only libfoo.so | grep undefined
U _ZN3bar9undefinedE
и расколотый:
$ nm -C --undefined-only libfoo.so | grep undefined
U bar::undefined
Теперь, если мы сбросим отладочную информацию, мы увидим это:
$ readelf --debug-dump=info libfoo.so
Contents of the .debug_info section:
Compilation Unit @ offset 0x0:
Length: 0x6d (32-bit)
Version: 4
Abbrev Offset: 0x0
Pointer Size: 8
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
<c> DW_AT_producer : (indirect string, offset: 0x0): GNU C++14 7.3.0 -mtune=generic -march=x86-64 -g -fPIC -fstack-protector-strong
<10> DW_AT_language : 4 (C++)
<11> DW_AT_name : (indirect string, offset: 0x8f): foo.cpp
<15> DW_AT_comp_dir : (indirect string, offset: 0x74): /home/imk/develop/so/scrap
<19> DW_AT_low_pc : 0x5ba
<21> DW_AT_high_pc : 0xf
<29> DW_AT_stmt_list : 0x0
<1><2d>: Abbrev Number: 2 (DW_TAG_namespace)
<2e> DW_AT_name : bar
<32> DW_AT_decl_file : 1
<33> DW_AT_decl_line : 1
<34> DW_AT_sibling : <0x48>
<2><38>: Abbrev Number: 3 (DW_TAG_variable)
<39> DW_AT_name : (indirect string, offset: 0x6a): undefined
<3d> DW_AT_decl_file : 1
<3e> DW_AT_decl_line : 2
<3f> DW_AT_linkage_name: (indirect string, offset: 0x57): _ZN3bar9undefinedE
<43> DW_AT_type : <0x48>
<47> DW_AT_external : 1
<47> DW_AT_declaration : 1
<2><47>: Abbrev Number: 0
<1><48>: Abbrev Number: 4 (DW_TAG_base_type)
<49> DW_AT_byte_size : 4
<4a> DW_AT_encoding : 5 (signed)
<4b> DW_AT_name : int
<1><4f>: Abbrev Number: 5 (DW_TAG_subprogram)
<50> DW_AT_external : 1
<50> DW_AT_name : foo
<54> DW_AT_decl_file : 1
<55> DW_AT_decl_line : 5
<56> DW_AT_linkage_name: (indirect string, offset: 0x4f): _Z3foov
<5a> DW_AT_type : <0x48>
<5e> DW_AT_low_pc : 0x5ba
<66> DW_AT_high_pc : 0xf
<6e> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)
<70> DW_AT_GNU_all_call_sites: 1
<1><70>: Abbrev Number: 0
, в котором наш символ _ZN3bar9undefinedE
описывается записью <2>
в
первый (и единственный) модуль компиляции, который был скомпилирован для libfoo.so
. Это
название связи дается записью:
<3f> DW_AT_linkage_name: (indirect string, offset: 0x57): _ZN3bar9undefinedE
Итак, чтобы получить имя исходного файла (ов), в котором bar::undefined
ссылаемся, мы хотим: -
Извлечение из отладочной информации всех блоков строк, таких как:
...Compilation Unit...
...
...
..._ZN3bar9undefinedE...
Затем из их извлеките все блоки, например:
...DW_TAG_compile_unit...
...
...DW_AT_comp_dir...
Затем из этих блоков выведите последние две строки. Вот один из способов - очень вероятно
не самый опытный способ - сделать это:
$ readelf --debug-dump=info libfoo.so | awk '/Compilation Unit/, /_ZN3bar9undefinedE/' | awk '/DW_TAG_compile_unit/,/DW_AT_comp_dir/' | grep -B1 'DW_AT_comp_dir'
<11> DW_AT_name : (indirect string, offset: 0x8f): foo.cpp
<15> DW_AT_comp_dir : (indirect string, offset: 0x74): /home/imk/develop/so/scrap
Мы получаем 1 попадание (конечно, поскольку был скомпилирован только один исходный файл), говорящее нам, что _ZN3bar9undefinedE
,
a.k.a bar::undefined
, на который есть ссылка в foo.cpp
, который был скомпилирован в build-directory /home/imk/develop/so/scrap
.