Нам не нужно , и до последнего года или двух все исполняемые файлы Linux зависели от позиции (не PIC). См. 32-разрядные абсолютные адреса, более не разрешенные в x86-64 Linux? .
Вы по-прежнему можете создавать не-PIE исполняемый файл с gcc -fno-pie -no-pie
, а статические исполняемые ELF-файлы всегда не-PIE с их адресом загрузки, выбранным во время соединения. Обычно по умолчанию устанавливается начало текстового сегмента на 401000
.
Позиционно-независимые исполняемые файлы ELF начинались как хак: общий объект ELF с точкой входа. Но в наши дни это широко используется и по умолчанию gcc
в большинстве дистрибутивов Linux. Адрес загрузки может быть рандомизирован во время выполнения.
Также обратите внимание, что многие ОС поддерживают исправления во время выполнения при загрузке исполняемого файла или библиотеки по адресу, отличному от предпочтительного адреса.
Общие объекты ELF в Linux, например, могут содержать перемещения для 64-битных абсолютных адресов, поэтому вы можете иметь традиционные таблицы переходов (массив указателей кода) или статически инициализированные массивы указателей (на данные или функции) в коде, скомпилированном с gcc -fPIC
для x86 и x86-64.
Обратите внимание, что gcc -fPIC
также включает поддержку вставки символов, поэтому функции не могут напрямую обращаться к глобальным переменным; они должны загрузить адрес из GOT, если символ не имеет «скрытой» видимости ELF. (Или, конечно, если вы сделаете его static
вместо глобального).
См. https://www.macieira.org/blog/2012/01/sorry-state-of-dynamic-libraries-on-linux/
(Некоторые идеи, предложенные в этом блоге, были реализованы, например, GCC поддерживает -fno-plt
.)
Фактическая стоимость просто независимости от позиции с -fpie
довольно мала. Но все же ненулевое значение в ОС, где гарантированно загружаются зависящие от позиции исполняемые файлы в низком 32-битном виртуальном адресном пространстве (например, в Linux), поэтому вы можете использовать 32-битные абсолютные адреса для 5-байтового mov r32, imm32
вместо 7-байтовый REA-относительный LEA для помещения статического адреса в регистр или [array + reg]
для индексации статического массива с его адресом в смещении disp32
как части режима адресации.