У меня есть файл .o
, скомпилированный из проекта C , который ссылается на функцию с именем init_static_pools
. Я использую objdump -t
, чтобы показать информацию о его символах:
00000000 UND 00000000 init_static_pools
Согласно этому потоку , UND просто говорит: " Мне нужен кто-то еще, чтобы предоставить мне эту функцию ".
Поэтому я связал этот файл .o
с файлом .elf
,который содержит определение init_static_pools
. objdump -t
показывает, что символ действительно в этом файле:
00004dcf g F .text 00000048 init_static_pools
В соответствии с этим потоком флаги g
и F
означают, что это глобальная функция . Я думаю, это означает, что эта функция может быть статически связана .
Я попытался связать файл .o
и .elf
с командной строкой ниже:
/ usr / bin / c ++ -m32 -rdynamic unittest1.o -o unittest1 target.elf lib / libgtest.a lib / libgtest_main.a -lpthread
Я получил ошибку ниже:
unittest1.cc :(. Text + 0x2d): неопределенная ссылка на `init_static_pools '
Функциятолько в файле .so, почему он не может быть связан?
Может ли это быть связано с различными механизмами разрешения символов между динамической и статической связью? Потому что я использую objdump -f
и вижу, что target.elf
является динамическим объектом. Как показано ниже:
target.elf: формат файла elf32-i386
архитектура: i386, флаги 0x00000150:
HAS_SYMS, DYNAMIC , D_PAGED
начальный адрес 0x00001144
ADD 1 - 9:17 AM 11/6/2019
На основании комментария @ EmployedRussian , Я пробовал readelf
.
Для target.elf
он содержит только 1 строку, говоря:
486: 00004dcf 72 FUNC GLOBAL DEFAULT 13 init_static_pools
Для unittest1.o
он содержит 2 строки:
0000002d 0000fb04 R_386_PLT32 00000000 init_static_pools
и
251: 00000000 0 NOTYPE GLOBAL DEFAULT UND init_static_pools
А для завершения их заголовки:
target.elf
:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x1144
Start of program headers: 52 (bytes into file)
Start of section headers: 246936 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 9
Size of section headers: 40 (bytes)
Number of section headers: 43
Section header string table index: 42
unittest1.o
:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 36988 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 262
Section header string table index: 261
Пока что я не могу пока определить причину сбоя связи. К счастью, я только что нашел series на компоновщике Ian Lance Taylor . Надеюсь, что это может просветить меня. Но это займет некоторое время.
ADD 2 - 10:33 AM 11/6/2019
Основываясь на ответе @ EmployedRussian, я попробовал следующие команды:
nm target.elf | grep init_static_pools
nm -D target.elf | grep init_static_pools
Как и подозревал @EmployedRussian, вторая командная строка не имеет вывода. Это означает, что target.elf не экспортирует init_static_pools в свою таблицу динамических символов, и это делает символ непригодным для ссылки из-за пределов target.elf.
Ниже приведены некоторые связанные флагик связыванию target.elf
:
-Wl,-T zephyr/linker.cmd (this is quite long, but it seems to be mostly layout info)
-Wl,-Map=target_prebuilt.map
-Wl,--whole-archive
-Wl,--gc-sections
-Wl,--build-id=none
-Wl,--sort-common=descending
-Wl,--sort-section=alignment
-ldl
-lm
Или я должен также проверить флаги компиляции?
И я нашел - export-all-symbols , - export-dynamic , - gc-keep-export опции, я их пробую.
Кажется, --export-all-symbols
игнорируется. Я предполагаю, что это предназначено для DLL.
Я положил --export-dynamic
и --gc-keep-exported
вместе, и сборка может пройти. Но nm -D
все еще показывает следующее сообщение:
target.elf: без символов
ADD 3 - 11:16 11/6/2019
Статья о динамической таблице символов (.dynsym) и таблице символов (.symtab). https://blogs.oracle.com/solaris/inside-elf-symbol-tables-v2
Некоторая цитата:
Фактически, во времена, предшествующие разделяемым библиотекам и динамическим связям, ни одна из них не была необходима во время выполнения. Был один, неразмещаемыйтаблица символов (разумно названная "symtab"). Когда в систему было добавлено динамическое связывание, первоначальные разработчики столкнулись с выбором: сделать выделенную symtab или предоставить вторую меньшую выделяемую копию. Символы, необходимые во время выполнения, представляют собой небольшое подмножество от общего числа, поэтому вторая таблица символов экономит виртуальную память в процессе выполнения. Это важное соображение. Следовательно, вторая таблица символов была изобретена для динамического связывания и, следовательно, названа "dynsym".
Итак, я думаю, что .dynsym
предназначен для динамического связывания во время выполнения . Но я думаю, что ожидаю, что мои unittest1.o
и target.elf
будут статически связаны во время сборки .
Так что это подводит меня к следующему вопросу: Могу ли я статически ссылаться на файл .ELF
? В Windows я обычно статически связываюсь с файлом .lib
, а не с .DLL
файл. Файл .ELF
здесь больше похож на .DLL
. И, кстати, мой процесс сборки также генерирует файл libtarget.a
. Стоит ли использовать его вместо target.elf
?
К сожалению, я пробовал nm -t
и readelf -s
на libtarget.a
, ни один из них не показывает существования init_static_pools
.
BTWЕсли вы знаете что-то о моей проблеме, не стесняйтесь, напишите намек. Спасибо!