Каковы различия, сравнивающие PIE, код PIC и исполняемый файл на 64-битной платформе x86 platfomr?

Тест находится на Ubuntu 12.04 64-бит. x86.

Я запутался в концепции "Независимый исполняемый файл Position (PIE) и независимый от положения код (PIC)", и я предполагаю, что они не ортогональны.

Вот мой быстрый эксперимент.

gcc -fPIC -pie quickSort.c -o a_pie.out
gcc -fPIC      quickSort.c -o a_pic.out
gcc                           a.out

objdump -Dr -j .text a.out > a1.temp
objdump -Dr -j .text a_pic.out > a2.temp
objdump -Dr -j .text a_pie.out > a3.temp

И у меня есть следующие выводы.

A. a.out содержит некоторый код PIC, но только поддерживает функции пролога и эпилога libc, как показано ниже:

4004d0:       48 83 3d 70 09 20 00    cmpq   $0x0,0x200970(%rip)        # 600e48 <__JCR_END__> 

В инструкциях по сборке моей простой программы быстрой сортировки я не нашел никаких инструкций PIC.

B. a_pic.out содержит код PIC, и я не нашел никаких инструкций не PIC... В инструкциях моей программы быстрой сортировки все Доступ к глобальным данным осуществляется с помощью инструкций ПОС:

  40053b:       48 8d 05 ea 02 00 00    lea    0x2ea(%rip),%rax        # 40082c <_IO_stdin_used+0x4>

C. a_pie.out содержит синтаксически идентичные инструкции по сравнению с a_pic.out. Однако адреса памяти раздела a_pie.out .text варьируются от 0x630 до 0xa57, тогда как тот же раздел a_pic.out находится в диапазоне от 0x400410 до 0x400817.

Может ли кто-нибудь дать мне некоторые объяснения этих феноменов? Особенно нахождение C. Опять же, я действительно запутался в PIE против PIC, и понятия не имею, как объяснить вывод C..

Ответ 1

Я запутался в концепции "Независимый исполняемый файл Position (PIE) и независимый от положения код (PIC)", и я предполагаю, что они не ортогональны.

Единственное реальное различие между PIE и PIC заключается в том, что вам разрешено вводить символы в PIC, но не в PIE. Кроме того, они в значительной степени эквивалентны.

Здесь вы можете прочитать о размещении символа .

С. a_pie.out содержит синтаксически идентичные инструкции по сравнению с a_pic.out. Тем не менее, адреса памяти раздела a_pie.out.text варьируются от 0x630 до 0xa57, тогда как один и тот же раздел a_pic.out находится в диапазоне от 0x400410 до 0x400817.

Трудно понять, что вы удивитесь в этом.

Двоичный файл PIE связан как с общей библиотекой, поэтому его адрес загрузки по умолчанию (.p_vaddr первого сегмента LOAD) равен нулю. Ожидается, что что-то переместит эту бинарную страницу от нулевой страницы и загрузит ее на какой-то случайный адрес.

С другой стороны, исполняемый файл не PIE всегда загружается по его связанному адресу. В Linux адрес по умолчанию для двоичных файлов x86_64 равен 0x400000, поэтому .text заканчивается недалеко от него.