[devel] libc on i586: WTF?
Sergey Vlasov
vsu на altlinux.ru
Сб Окт 16 11:40:16 UTC 2010
On Sat, Oct 16, 2010 at 12:26:18PM +0800, REAL wrote:
> Что-то загадочное произошло на вчерашнем срезе сизифа (может быть и
> раньше так было, только не замечал):
>
> $ gfortran -O2 -c ilaenv.f
> $ nm ilaenv.o|grep stack_chk_fail
> U __stack_chk_fail
>
> НО:
> $ gfortran -fPIC -O2 -c ilaenv.f
> $ nm ilaenv.o|grep stack_chk_fail
> U __stack_chk_fail_local
>
> Проявляется на i586, на x86_64 всё в порядке.
На самом деле так было уже очень давно.
> Символ __stack_chk_fail_local присутствует только в libc.a, не в libc.so:
Ещё он присутствует в libc_nonshared.a, при этом файл libc.so,
используемый при компоновке, на самом деле представляет собой ld
script:
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )
Т.е., в каждый исполняемый файл или разделяемую библиотеку попадает
собственная копия необходимых функций из libc_nonshared.a.
Функция __stack_chk_fail_local на самом деле просто вызывает функцию
__stack_chk_fail из libc.so.6. Эта промежуточная функция, локальная
для разделяемой библиотеки, добавлена с целью оптимизации. Дело в
том, что вызов функции __stack_chk_fail из другого модуля должен
производиться через PLT, для чего i386 ELF ABI требует перед вызовом
загрузить в регистр %ebx указатель на GOT; вызов же локальной для
модуля функции __stack_chk_fail_local может производиться напрямую и
не требует предварительной инициализации %ebx, а уже в реализации
__stack_chk_fail_local в одном экземпляре на каждый модуль
присутствует код, устанавливающий требуемое значение %ebx перед
вызовом __stack_chk_fail через PLT.
В системе команд x86_64, в отличие от i386, есть возможность адресации
данных по смещению от адреса текущей команды (%rip), поэтому не
требуется занимать отдельный регистр для хранения адреса GOT, и вызов
функции через PLT не требует предварительной подготовки, поэтому там
функция __stack_chk_fail просто вызывается напрямую, и локальная для
модуля функция __stack_chk_fail_local не нужна.
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя : отсутствует
Тип : application/pgp-signature
Размер : 198 байтов
Описание: Digital signature
Url : <http://lists.altlinux.org/pipermail/devel/attachments/20101016/07b273c0/attachment.bin>
Подробная информация о списке рассылки Devel