Просто скажи что-нибудь дополнительное.
В url, указанном в вопросе , упоминается, что вы можете передать -mcmodel=large
в gcc, чтобы сказать компилятору сгенерировать 64-битный операнд непосредственного адреса для вашего кода.
Итак, gcc -mcmodel=large -shared a.c
создаст общий объект без PIC.
-
Демонстрация:
a.c:
#include <stdio.h>
void foo(void)
{
printf("%p\n", main);
}
32-битный операнд непосредственного адреса блокирует создание объекта без PIC.
xiami@gentoo ~ $ cc -shared -o a.so a.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: /tmp/cck3FWeL.o: relocation R_X86_64_32 against `main' can not be used when making a shared object; recompile with -fPIC
/tmp/cck3FWeL.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
Используйте -mcmodel=large
, чтобы решить. (Предупреждения появляются только в моей системе, поскольку изменение в .text запрещено моим ядром PaX.)
xiami@gentoo ~ $ cc -mcmodel=large -shared -o a.so a.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: /tmp/ccZ3b9Xk.o: warning: relocation in readonly section `.text'.
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: warning: creating a DT_TEXTREL in object.
Теперь вы можете видеть тип записи перемещения: R_X86_64_64 вместо R_X86_64_32, R_X86_64_PLT32, R_X86_64_PLTOFF64.
xiami@gentoo ~ $ objdump -R a.so
a.so: file format elf64-x86-64
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
...
0000000000000758 R_X86_64_64 printf
...
А в моей системе свяжите этот общий объект с обычным кодом и запустите программу, которая выдаст такие ошибки, как:
./a.out: error while loading shared libraries: ./a.so: cannot make segment writable for relocation: Permission denied
Это доказывает, что динамический загрузчик вынужден выполнять перемещения на .text , чего не будет в библиотеке PIC.