LINUX.ORG.RU

Как дебажить работу линкера?

 


0

1

Вот например у меня есть .a файл, в котором .rel.init_array содержит важный вызов конструктора (проверил с помощью readelf)

Когда я с этим .a файлом собираю запускаемый бинарник то почему-то именно этого важного вызова нет в .init_array, хотя всякие остальные из других файлов добавляются как и положено

Как без пошагового запуска в дебаггере линкера понять что за фигня происходит? Да, линкером является clang



Последнее исправление: ahdenchik (всего исправлений: 2)

либо ты не влинковал таки свой файл, либо линкеру показалось, что этот код не нужен вообще. и он его выкинул.

https://stackoverflow.com/questions/17710024/clang-removing-dead-code-during-static-linking-gcc-equivalent-of-wl-gc-sect

https://discourse.llvm.org/t/linker-stripping/29539

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 2)
Ответ на: комментарий от alysnix

Влинковал, потому что другие символы из этой библиотеки успешно используются (эта библиотека - известная picolibc)

А вот насчёт решил что не нужен гипотеза интересная. Но, как минимум у меня есть другие файлы (.o), которые тоже используют .rel.init_array, помещают туда нигде более не упомянутые символы, и с ними всё работает

Сейчас попробую как-то запретить выкидывать всё лишнее на последнем этапе

ahdenchik
() автор топика

Да, линкером является clang

Нет, clang не является линкером. Он запускает линкер, указанный в опции -fuse-ld=..., или использует значение по умолчанию, заданное при конфигурации (обычно ld.bfd)

annulen ★★★★★
()
Ответ на: комментарий от annulen

Увидеть значение по умолчанию можно в выводе clang -###

annulen ★★★★★
()

Как без пошагового запуска в дебаггере линкера понять что за фигня происходит?

У линкера есть множество опций, о которых написано в мане. См. ман к используемому линкеру, например, man ld. Например, может пригодиться опция --trace-symbol=....

annulen ★★★★★
()
Ответ на: комментарий от annulen

Да, я в курсе, для краткости написал так. Штатный LLVM-ный используется в моём случае

Вот такой вот код:

__attribute__((constructor))
static void posix_init(void)
{
    __bufio_lock_init(&__stdout.xfile.cfile.file);
}

Он должен попадать в .init_array, и он, таки, попадает:

> eadelf -a build123/subprojects/picolibc/newlib/libc.a
[...]
Раздел перемещения '.rel.init_array' at offset 0xde0 contains 1 entry:
 Смещение   Инфо    Тип             Знач.симв  Имя симв.
00000000  00000326 R_ARM_TARGET1     00000001   posix_init

Попробовал на всякий случай добавить __attribute__((used)) ему - ничего не изменилось

ahdenchik
() автор топика
Ответ на: комментарий от ahdenchik

Штатный LLVM-ный используется в моём случае

lld? Тогда есть смысл посмотреть, что будет с ld.bfd

annulen ★★★★★
()
Ответ на: комментарий от ahdenchik

Читай не .a целиком а отдельные .o из него. .a это просто архив с объектными файлами, для линкера они все сами по себе и выкиывает он каждый отдельно.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Читал в первую очередь - оно там где надо есть

Если и выкидывается то на последнем этапе, когда уже всё в кучу собирается

ahdenchik
() автор топика
Ответ на: комментарий от ahdenchik

Начни с главного - расскажи людям, что у тебя за платформа, и приведи минимально воспроизводимый пример.

LamerOk ★★★★★
()

А конструктор заглушка? Или в нём что-то есть? А данные то инициализированы в работе программы этим конструктором? Вызывается он один и только один раз? Вызови пару раз в разных местах, если он ничего не делает то пусть что-то сделает. Мне кажется он просто статически вшивает тело конструктора так как больше просто нет мест в коде где он мог бы быть вызван, ну и нафиг тогда он нужен, воть и выкинуло =) Ну это я предполагаю. Мысли в слух

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

А конструктор заглушка? Или в нём что-то есть?

Нет, выше я показал его даже (вообще их там 3 штуки в той директории)

А данные то инициализированы в работе программы этим конструктором? Вызывается он один и только один раз? Вызови пару раз в разных местах, если он ничего не делает то пусть что-то сделает. Мне кажется он просто статически вшивает тело конструктора так как больше просто нет мест в коде где он мог бы быть вызван

Место в коде есть - специальная секция .init_array. Это место проходит загрузчик (Сишных программ, например). Конкретно в моём случае он вызывается при сбросе контроллера отсюда. Другие конструкторы из других модулей (штук 50 их!) линкуются и вызываются нормально.

Программа полностью грузится и отрабатывает, но при попытке напечатать результат оказывается что всё что должно инититься в picolibc проиничено не было, потоки STDOUT и прочие равны NULL и всё - кирдык

ahdenchik
() автор топика
Ответ на: комментарий от LamerOk

Не, это как раз не главное

Это форк языка D для запуска на всяких разных платформах. Испытываю это на контроллерах. Сначала это ARM Cortex-M, потом будет RISC-V ESP32. Собственно, MVP более-менее работает, кроме этого вот инита picolibc.

Года 3 назад это работало, но потом что-то сломалось. Найти что работало и сломалось бисекцией уже не получится - версии компиляторов уехали далеко вперёд

Кода там ворох, причёсывать ради одной этой проблемы пока не считаю целесообразным. Когда заработает обязательно опубликую.

ahdenchik
() автор топика
Ответ на: комментарий от ahdenchik

Не, это как раз не главное

Когда тебе старшие говорят, что «главное» - их надо слушаться. У тебя ёмбеддед со своим специфическим тулчейном. Если баг в компоновщике, то он конкретно в компоновщике под эту платформу и даже, возможно, в конкретных версиях.

причёсывать ради одной этой проблемы

На __attribute__((constructor)) примерно вся libc и libstdc++ держится. Если это для тебя «одна проблема», то ок.

LamerOk ★★★★★
()
Ответ на: комментарий от annulen

Например, может пригодиться опция –trace-symbol=….

Этот способ оказался самым действенным - сразу всё прояснилось

Проблема типовая, оказывается, и часто случается как раз при статической компиляции с .init_array

Суть: как уже тут выше отмечали, линковка .o файла из .a происходит не просто так, а только когда что-то из этого .o было заюзано или же принудительно указан линкеру символ, объектный файл или ключ --whole-archive.

Поэтому, если у нас такой вот конструктор или, например, функция, которая внутри себя регистрирует где-то в наружной системе другой символ, то возникает эта проблема.

В моём случае достаточно оказалось заюзать символы из объектника и проблема вылечилась

ahdenchik
() автор топика
Последнее исправление: ahdenchik (всего исправлений: 1)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.