Общие библиотеки ELF - мотивация для PLT

11

Может ли самоизменяющийся код использоваться для ускорения вызова функций в динамически связанных библиотеках?

Насколько я понимаю, разделяемые библиотеки ELF используют своего рода таблицу косвенных переходов (таблица связывания процедур или PLT), чтобы обеспечить ленивое связывание библиотечных функций. Похоже, что цель состоит в том, чтобы избежать необходимости изменять таблицу в сегменте кода, в то же время позволяя лениво разрешать позиции функций при первом вызове.

Разве не было бы быстрее динамически создать код для этой таблицы во время загрузки или, возможно, даже при первом вызове функции?

Позволяет ли максимально разделять сегмент кода между процессами (динамическая таблица была бы приватной для процесса)? Это из соображений безопасности (доступный для записи код не должен быть исполняемым - но JIT делают это постоянно, а загрузчик может добавлять и удалять разрешение на запись перед тем, как запустить программу)?

Или это их комбинация, и небольшой прирост производительности на вызов функции просто не стоит усилий?

lxgr
источник

Ответы:

8

Я полагаю, мы говорим об архитектуре x86.

Вы не можете иметь самоизменяющийся код в защищенном режиме , который используется большинством операционных систем на основе UNIX (и не только), о которых я знаю, потому что сегменты кода всегда доступны только для чтения. Загрузчик не контролирует, что это то, что обрабатывается подсистемой управления памятью ядра.

Но даже если бы вы могли «создать код для этой таблицы во время загрузки», как вы говорите, это не соответствовало бы всей цели разделяемых библиотек. Таким образом, каждый процесс будет иметь «частную» копию функций библиотеки в своем адресном пространстве, эффективно увеличивая объем занимаемой памяти - одна из причин, по которой были созданы общие библиотеки, заключалась в решении этой проблемы.

Весь описанный вами процесс довольно сложен, и он будет стоить больше циклов обработки, чем метод PLT, который используется в настоящее время, и, вероятно, привнесет больше новых и интересных проблем безопасности.

dkaragasidis
источник
2
Вы можете использовать системный вызов mprotect (2), чтобы сделать страницы сегмента .text доступными для записи и выполнения.
Брюс Эдигер
1
Это правильно, сэр. Вероятно, это будет работать прилично в средней системе на основе UNIX, но весь процесс компоновки прекратится, как только кто-то попытается укрепить систему, например, с помощью PaX, что накладывает ограничения на mprotect (2).
dkaragasidis
(Кажется, я пропустил упоминание @BruceEdiger в моем предыдущем комментарии)
dkaragasidis
1

DSO ELF могут использовать флаг (DF_TEXREL), чтобы объявить, что им требуется перераспределение путем изменения их текстового раздела (который обычно доступен только для чтения). Подход таблицы переходов вместе с независимым от PIE кодом должен быть более оптимальным.

(Обнаружено, что в http://www.akkadia.org/drepper/dsohowto.pdf , но другие ресурсы упоминают об этом тоже).

PSkocik
источник