GCC связывает статическую libc и некоторую другую библиотеку динамически, пересматривается?
следующие вопросы актуальны, но не отвечают на мой вопрос:
связывание частично статическое и частично динамическое в GCC
GCC: статическое связывание только некоторых библиотек
статическая ссылка функции общей библиотеки в gcc
Я задал очень похожий вопрос ранее, но так как предыдущий вопрос, начатый мной, был несколько загроможден в разделе комментариев и не полностью ответил (но я отметил его как ответ, так как это было хорошее усилие и, по крайней мере, частично ответил на него), я задам новый вопрос. Вопрос в том, как связать libc как статический, при этом динамически связывая некоторую другую библиотеку (например, libm). Это было предложено, что не может быть сделано в первом вопросе, это правда? Если так было бы очень интересно узнать, почему не.
возможно ли это сделать? Кто-то сделал комментарий (который был удален по какой-то причине, может быть, это было неправильно?) что можно, но надо тогда и существует динамически связанная версия libc, так как она потребуется динамической библиотеке (например, dynamic libm потребует динамического libc (?)).
это хорошо для меня, но мне не очевидно, как сказать GCC сделать это, т. е. ссылка в libc как статическая, так и динамическая. Как мне быть? это (я сделал пару попыток, некоторые показаны позже в вопросе)? Или есть другой способ сделать то, что я хочу?
сначала мы видим это, просто запустив тест gcc.c-lm, все связано динамически, следующим образом:
$ gcc test.c -lm
$ ldd a.out
linux-vdso.so.1 (0x00007fffb37d1000)
libm.so.6 => /lib64/libm.so.6 (0x00007f3b0eeb6000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3b0eb10000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3b0f1b0000)
чтобы связать только libm как статический, позволяя libc оставаться динамическим, мы можем сделать (как указал Z бозон в одном из вышеупомянутых вопросов):
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libm.a
$ ldd a.out
linux-vdso.so.1 (0x00007fff747ff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f09aaa0c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f09aadb2000)
однако попытка той же процедуры связать libc static и libm dynamic, похоже, не работает:
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a -lm
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
что означает это сообщение об ошибке означает?
некоторые другие попытки (большинство из них также вошли в мой первый вопрос):
$ gcc test.c /usr/lib64/libc.a
linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
urned 1 exit status
$ gcc test.c -Wl,-Bdynamic -lm -Wl,-Bstatic -lc
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bdynamic -lm -Wl,-Bstatic -lc test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bstatic -lc -Wl,-Bdynamic -lm test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.so -lm
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.so /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a -lm
обратите внимание, что последний составлен и успешно связаны. Однако libc не был связан статически, только динамически, поэтому это еще одна неудачная попытка.
тестовая программа просто следующая:
$ cat test.c
#include <stdio.h>
#include <math.h>
int main(int argc, char **argv)
{
int i;
int result;
for(i = 0; i < 65535; i++) {
result = sin(i);
}
return 0;
}
Edit:
Я также пробовал statifier и горностай, как подсказывает в этом вопросе:
статическая ссылка функции общей библиотеки в gcc
не работает.
2 ответов
в принципе, ваш первый подход-правильный способ сделать это:
gcc test.c libc.a -lm
после того, как gcc добавит неявные библиотеки, он будет выглядеть (концептуально) следующим образом:
gcc crt1.o test.c libc.a -lm -lc -lgcc -lc
это означает, что любые функции libc вызываются либо crt1.o
или test.c
будет вытащен из libc.a
и связаны статически, тогда как любые функции называются исключительно С libm
или libgcc
будет связан динамически (но он будет повторно использовать статические функции, если вызовет libm что-то уже вытащил).
компоновщик всегда начинается с самого левого файла / библиотеки и работает вправо; он никогда не возвращается. .c
и .o
файлы связаны безоговорочно, но .a
файлы и -l
параметры используются только для поиска функций, которые уже ссылаются, но еще не определены. Поэтому библиотека слева бессмысленна (и -lc
должен появиться дважды, потому что -lc
зависит от -lgcc
и -lgcc
зависит от -lc
). порядок ссылок важен!
к сожалению, вы, кажется, были сорваны тем, что может быть ошибкой в strcmp
(или, скорее, в libc, который содержит strcmp
): the STT_GNU_IFUNC
thing-Это умная функция, которая позволяет включать несколько версий функции и выбирать наиболее оптимальную во время выполнения, основываясь на том, какое оборудование доступно. Я не уверен, но похоже, что эта функция доступна только в пироге (независимый от позиции исполняемый файл) или совместно сборка библиотеки.
почему это было бы в статике libc.a
для меня загадка, но есть простой обходной путь: реализовать собственный strcmp
(базовая, медленная реализация-это всего несколько строк C) и свяжите ее в до libc.a
.
gcc test.c mystrcmp.c libc.a -lm
кроме того, вы можете извлечь функции из libc.a
что вы хотите и только те в статически:
ar x libc.a
gcc test.c somefile.o -lm
ar
это .a
файлы tar
это .tar
файлы, хотя использование команды немного варьируется, поэтому в этом примере извлекается .o
файлы .a
file, а затем связывает их явно.
на основе ответа ams я сделал следующее
mystrcmp.c
int strcmp(const char *s1, const char *s2) {
}
Compile
gcc -c test.c
gcc -c mystrcmp.c
установочные файлы
ln -s `gcc -print-file-name=crt1.o`
ln -s `gcc -print-file-name=crti.o`
ln -s `gcc -print-file-name=crtn.o`
ln -s `gcc -print-file-name=libgcc_eh.a`
ln -s `gcc -print-file-name=libc.a`
ln -s `gcc -print-file-name=libm.so`
ссылке
LD-m elf_x86_64-o math crt1.o crti.тест о'.o mystrcmp.о библиотеки libc.в libgcc_eh.в библиотеку libc.в libm.так -динамического компоновщика /lib64/ЛД-ОС Linux для архитектуры x86-64.так.2 crtn.o
это ссылки и работает правильно. Однако,ldd
показывает
linux-vdso.so.1 => (0x00007fff51911000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8182470000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f81820a9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8182793000)
похоже, что динамический libm
требует динамический libc
. На самом деле, это легко показать.
ldd libm.так сообщает
linux-vdso.so.1 => (0x00007fff20dfe000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcaf74fe000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcaf7bed000)
таким образом, невозможно связать с libm.таким образом, не связывая libc.так же, если вам не удастся скомпилировать libm без зависимости от libc.