Смешивание объектных модулей fPIC и не-fPIC
Окружающая среда: Ubuntu 16.04
В моем эксперименте я выполнил следующие команды:
gcc -c 1.c
gcc -c -fPIC 2.c
gcc -shared 1.o 2.o -o libmyxxx.so
Все функции, которые мне нужны, определены в 2.c через extern "C"
деклараций. Эти функции внутренне вызывают другие функции, которые определены в 1.c.
Обратите внимание, что я не подал заявку -fPIC
до 1.с. Тем не менее, кажется, что все без проблем компилируется / связывается.
Можем ли мы сделать вывод, что -fPIC
должны применяться только к тем исходным файлам, которые предоставляют внешние функции?
В целом у меня есть куча архивных (.a) файлов, которые, возможно, не были скомпилированы -fPIC
флаг. Мне нужно создать собственную общую библиотеку, которая будет связывать эти архивные файлы. Если мое предположение верно, я думаю, что было бы хорошо связать эти архивные файлы. Цените ваши мысли. С уважением.
2 ответа
Можем ли мы сделать вывод, что -fPIC должен применяться только к тем исходным файлам, которые предоставляют внешние функции?
Нет, мы не можем. Единственная цель -fPIC
Гарантируется, что полученный машинный код может быть связан в двоичный код, не зависящий от позиции. Тем не менее, возможно, что некоторый код, кажется, готов к PIC, даже если исходный код был скомпилирован без -fPIC
, Это могут быть короткие самодостаточные функции без внешних зависимостей, что бы не потребовало вспомогательных структур данных в сгенерированном объектном файле, таких как записи PLT и GOT.
В любом случае, компоновщик потерпит неудачу с полным сообщением об ошибке, если ваш объектный файл не может быть связан с независимым от позиции двоичным файлом. И вам нужно перекомпилировать его с помощью этой волшебной опции.
Так что вы должны всегда ставить -fPIC
в CFLAGS
вашей общей библиотеки, чтобы сэкономить ваше время и избежать ненужных перекомпиляций.
Если в исполняемом файле есть объектный файл, скомпилированный без флага -fPIC, будут страницы текста программы, которые имеют ссылки на память, зависящие от позиции. Эти страницы не смогут быть перемещены на подходящие адреса виртуальной памяти во время выполнения (что в основном предназначено для общих объектов). Когда вы создаете свой код на каком-то другом компьютере или связываете.so с каким-либо другим кодом, эти ссылки на память, зависящие от позиции, будут приходить и байтать вам.
-fPIC требуется для генерации независимого от позиции кода для:
- глобальные переменные
- статические переменные
- внешние переменные
- строковые константы
- принимая адреса функции
Кроме того, вы можете избежать каких-либо предупреждений или ошибок при компиляции / компоновке объектного файла без -fPIC в Linux/x86-32; но это невозможно сделать на некоторых архитектурах.