Смешивание объектных модулей 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; но это невозможно сделать на некоторых архитектурах.

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