LINUX.ORG.RU

Вопрос по линковке


0

0

Стоит задача собрать бинарник, в который был бы включен код из некой библиотеки (например libhello.a), который будет вызываться через dlopen.

Таким образом линкер не включит его в бинарник, так как ни один симбол из libhello.a нигде не используется.

Речь идет о таком случае:
gcc -o test ./test.o ./libhello.a

Если же использовать:
gcc -o test ./test.o ./libhello.o, то все пучком

Вопрос: как все-таки заставить его включить код из libhello.a в конечный бинарник. Опция линкеру -export-dynamic не помогла. Опция -static не подходит, из-за того, что я не хочу линковать все статически (например в линковке участвуют либы X-ов).


Заранее спасибо. :))


Опять 5*5... Нельзя так делать. Ведь libhello.a наверняка без -fPIC собрана!

Antichrist
()

2Antichrist: Конечно без -fPIC. А зачем. Я ж его линкую не в шаред библиотеку, а в бинарник. То есть я его хочу статически залинковать. А dlopen может открывать бинарник (сам себя) таким же макаром если передать ему вместо пути к библиотеке NULL. Все это нужно для следующего. Есть библиотека libhello. В зависимости от опций переданных в configure она потом компилится с -fPIC и линкуется как libhello.so или компилится и линуется как статическая. В первом случае программа работает с ней как плугином через dlopen и dlsym, а во втором точно также, но симболы ищет в своих нутрях. таким образом стиль работы менять не нужно. Достаточно передать вместо пути к библиотеке NULL.

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

Вот я и спрашиваю как заставить линковщик включить в бинарник все симболы, даже если они не используются

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

А указать все файлы, которые есть в libhello, вместо нее самой?

nobody ★★
()

Это выход :)) не круто. Гораздо приятнее указать один, а не следить за 20 объектниками.

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

Это называется "через жопу". Ведь точно так же можно заприкрыть dlopen() всякими #ifdef-ами, и точно так же через autoconf-овый скрипт их включать. А то еще и непортабельно получится, совсем какашечно...

Antichrist
()

Согласен, что через жопу. Но представь себе, что программа пишется один раз, а потом ты пишешь плугины, которые по желанию можешь вкомпилить в главную программу без ее изменения. Как это сделать? Хотя так уже и ничего не менять не получится. Есть идеи?

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

Элементарно! dlsym всё равно указатель возвращает. Ну так и сделать простенький враппер, который в зависимости от одного только #ifdef будет либо дёргать dlopen и dlsym, или просто возвращать callback. Обычно это так и делают. Если будет свободное время - нарисую простенький пример такой технологии.

Antichrist
()

Спасибо конечно, только щас оно приблизительно так и работает :)) Тоже вроперчик.

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

Все, прикрутил Сделал как в ядре. То есть в конечном elf-e добавил свою секцию в которую пихаются все нужные функции. А в начале и в конце симболы определил типа __begin_seg __end_seg.

А потом

extern char __begin_seg;

((void (*)(void))&__begin_seg)()

Если кому интересно могу подробнее

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

Ну вот - и получилась непортабельная какашка. Кому такое надо?!?

Antichrist
()

Что значит не портабельная? Обясни свою мысль.

Ты знаешь, что при конфигурировании ld, он из шаблонов строит аналогичные скрипты для каждой платформы. Я делаю то же самое, но для elf_i386. То есть то что сделал я будет нормально работать на всех elf_i386 платформах.

Вот кусок шаблона. Вернее это скрипт для его формирования.

test -z "$ENTRY" && ENTRY=_start
test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi
test -z "${ELFSIZE}" && ELFSIZE=32
test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8"
test "$LD_FLAG" = "N" && DATA_ADDR=.
INTERP=".interp ${RELOCATING-0} : { *(.interp) }"
PLT=".plt ${RELOCATING-0} : { *(.plt) }"
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
RODATA=".rodata ${RELOCATING-0} : { *(.rodata) ${RELOCATING+*(.rodata.*)} ${RELOCATING+*(.gnu.linkonce.r.*)} }"
SBSS2=".sbss2 ${RELOCATING-0} : { *(.sbss2) ${RELOCATING+*(.sbss2.*)} ${RELOCATING+*(.gnu.linkonce.sb2.*)} }"
SDATA2=".sdata2 ${RELOCATING-0} : { *(.sdata2) ${RELOCATING+*(.sdata2.*)} ${RELOCATING+*(.gnu.linkonce.s2.*)} }"
CTOR=".ctors ${CONSTRUCTING-0} :
{
${CONSTRUCTING+${CTOR_START}}
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */

KEEP (*crtbegin.o(.ctors))

/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */

KEEP (*(EXCLUDE_FILE (*crtend.o $OTHER_EXCLUDE_FILES) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
${CONSTRUCTING+${CTOR_END}}
}"

DTOR=" .dtors ${CONSTRUCTING-0} :
{
${CONSTRUCTING+${DTOR_START}}
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o $OTHER_EXCLUDE_FILES) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
${CONSTRUCTING+${DTOR_END}}
}"

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

> Что значит не портабельная?
[...]
> будет нормально
> работать на всех elf_i386 платформах

 Ты сам себе ответил. К примеру, alpha-dec-osf1 уже идёт на хрен,
i386-gnu-cygwin32 туда же, про sparc-sun-solaris вообще забыть можно.

 Так какая на фиг портабельность? Никакой портабельности. И всё
ради дешевенького извращения, на хрен не нужного и никаких преимуществ,
стоящих портабельности, не дающего.

Antichrist
()

1.Я могу сделать и сделаю (не долго), чтобы она работала на всех платформах для которых ld умеет делать бинарники.
2.Это не извращение. Преимущество то, что я сделал бинарник, который на этапе компиляции не знает, что он будет вызывать. То есть какой-то чувак пишет плугин который может работать как *.so а может быть вкомпилян во внутрь. Главная программа вызывает одну функцию которая возвращает всю необходимую информацию, а дальше пляшет исходя из нее.

Таким образом, портабельность остается, а преимущество всетаки есть.
Ладно, спасибо за дискусию. :))

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

Еще раз объясняю - аналогичная функциональность достигается через коллбэки. Не надо никаких извращений. Похоже, мне таки придётся примерчик написать...

Antichrist
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.