Как я могу сказать, что-то вроде objdump, был ли объектный файл собран с -fPIC?

Как я могу сказать, с чем-то вроде objdump, если объектный файл был построен с -fPIC?

7 ответов

Ответ зависит от платформы. На большинстве платформ, если вывод из

readelf --relocs foo.o | egrep '(GOT|PLT|JU?MP_SLOT)'

пусто, то либо foo.o не был скомпилирован с -fPIC, или же foo.o не содержит кода где -fPIC вопросы.

Мне просто нужно было сделать это на цели PowerPC, чтобы найти, какой общий объект (.so) создавался без -fPIC. Я запустил readelf -d libMyLib1.so и нашел TEXTREL. Если вы видите TEXTREL, один или несколько исходных файлов, составляющих ваш.so, не были созданы с -fPIC. При необходимости вы можете заменить readelf на elfdump.

Например,

[user@host lib]$ readelf -d libMyLib1.so | grep TEXT   # Bad, not -fPIC
 0x00000016 (TEXTREL)
[user@host lib]$ readelf -d libMyLib2.so | grep TEXT   # Good, -fPIC
[user@host lib]$

И чтобы помочь людям в поиске решений, ошибка, которую я получал, когда запускал свой исполняемый файл, была следующей:

root@target:/# ./program: error while loading shared libraries: /usr/lib/libMyLi
b1.so:  R_PPC_REL24 relocation at 0x0fc5987c for symbol 'memcpy' out of range

Я не знаю, относится ли эта информация ко всем архитектурам.

Источник: blogs.oracle.com/rie

Я предполагаю, что вы действительно хотите знать, состоит ли общая библиотека из объектных файлов, скомпилированных с -fPIC.

Как уже упоминалось, если есть TEXTREL, то -fPIC не использовался.

Существует отличный инструмент, называемый scanelf, который может показать вам символы, которые вызвали перемещение.text.

Дополнительную информацию можно найти в HOWTO. Найдите и исправьте текстовые перемещения TEXTREL.

readelf -a *.so | флаги grep
  Флаги:                             0x50001007, noreorder, рис., Cpic, o32, mips32

Это должно работать большую часть времени.

-fPIC означает, что код сможет выполнять в адресах, отличных от адреса, для которого был скомпилирован.

Для этого disasambler будет выглядеть так....

call get_offset_from_compilation_address
get_offset_from_compilation_address: pop ax
sub ax, ax , &get_offset_from_compilation_address

Теперь у Ax есть смещение, которое нам нужно добавить к любому доступу к памяти.

load bx, [ax + var_address}

Другой вариант, чтобы отличить, генерируется ли ваша программа с параметром -fPIC:

при условии, что в вашем коде при компиляции включена опция -g3 -gdwarf-2.

другой формат отладки gcc может также содержать информацию макроса:

Обратите внимание, что следующий синтаксис $'..' предполагает bash

echo $' main() { printf("%d\\n", \n#ifdef __PIC__\n__PIC__\n#else\n0\n#endif\n); }' | gcc -fPIC -g3 
-gdwarf-2 -o test -x c -

readelf --debug-dump=macro ./test | grep __PIC__

такой метод работает, потому что gcc manual объявляет, что если используется -fpic, PIC равен 1, а если -fPIC используется, PIC равен 2.

Ответы выше, проверяя ПОЛУЧЕННЫЙ, являются лучшим способом. Потому что предварительный запрос -g3 -gdwarf-2, я думаю, используется редко.

Из интерфейса программирования Linux :

В Linux/x86-32 можно создать общую библиотеку, используя модули, скомпилированные без этой опции. Однако при этом теряются некоторые преимущества разделяемых библиотек, поскольку страницы текста программы, содержащие зависящие от позиции ссылки на память, не используются совместно процессами. В некоторых архитектурах невозможно создавать общие библиотеки без этой опции.

Чтобы определить, был ли существующий объектный файл скомпилирован с опцией, мы можем проверить наличие имени_GLOBAL_OFFSET_TABLE_в таблице символов объектного файла с помощью одной из следующих команд:

       $ nm mod1.o | grep _GLOBAL_OFFSET_TABLE_
$ readelf -s mod1.o | grep _GLOBAL_OFFSET_TABLE_

И наоборот, если какая-либо из следующих эквивалентных команд дает какие-либо выходные данные, то указанная разделяемая библиотека включает по крайней мере один объектный модуль, который не был скомпилирован с–fPIC:

       $ objdump --all-headers libfoo.so | grep TEXTREL
$ readelf -d libfoo.so | grep TEXTREL

Однако ни приведенная выше цитата, ни какой-либо ответ на этот вопрос не работают для x86_64.

То, что я наблюдал на своей машине с x86_64 Ubuntu, это то, что если указать-fPICили нет, он будет генерировать fPIC . То есть

      gcc -g -Wall -c -o my_so.o my_so.c // has _GLOBAL_OFFSET_TABLE_
gcc -g -Wall -fPIC -c -o my_so_fpic.o my_so.c // has _GLOBAL_OFFSET_TABLE_

readelf -s my_so.o > 1.txt && readelf -s my_so_fpic > 2.txt && diff 1.txt 2.txt

нет разницы и то и другоеmy_so.oиmy_so_fpic.oможно использовать для создания общей библиотеки.

Чтобы сгенерировать объектный файл, отличный от fpic, я нашел флаг gcc с именем-fno-picв первом комментарии Как проверить, был ли бинарный файл Linux скомпилирован как позиционно-независимый код?.

Это работает,

      gcc -g —Wall -fno-pic -c -o my_so_fnopic.o my_so.c // no _GLOBAL_OFFSET_TABLE_ 

и

      gcc -g -Wall -shared -o libdemo.so my_so_fnopic.o 

дает ошибку:

      /usr/bin/ld: my_so_fnopic.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
collect2: error: ld returned 1 exit status

не могу создать общую библиотеку без картинок.o.

Другие вопросы по тегам