Хорошо, поэтому я посмотрел на это, и похоже, что происходит то, что ваш промежуточный шаг gcc
(с использованием -c
) вызывает проблему.Вот моя интерпретация того, что я вижу.
Когда вы компилируете как .o
с setup()
, gcc
просто обрабатывает это как нормальную функцию (так как вы не компилируете как .so
так что все равно)Затем ld
не видит _init()
или что-либо подобное DT_INIT
в динамическом разделе ELF и предполагает, что конструкторов нет.
Когда вы компилируете как .o
с _init()
, gcc
также рассматривает это как нормальную функцию.На самом деле, мне кажется, что объектные файлы идентичны , за исключением имен самих функций!Итак, еще раз, ld
смотрит на файл .o
, но на этот раз видит функцию _init()
, которую он знает, что ищет, и решает, что это конструктор, и соответственно создает запись DT_INIT
в новом .so
.
Наконец, если вы выполняете компиляцию и компоновку за один шаг, например:
gcc -Wall -shared -fPIC -o libsmlib.so smlib.c
Тогда происходит то, что gcc
видит и понимает __attribute__ ((constructor))
вконтекст создания общего объекта и соответственно создает запись DT_INIT
.
Краткая версия: используйте gcc
для компиляции и компоновки за один шаг.Вы можете использовать -Wl
(см. Справочную страницу) для передачи дополнительных параметров, таких как -soname
, если требуется, например, -Wl,-soname,libsmlib.so.1
.