Перемещение символов

Ниже показано, как вызов функции (в первый раз) будет разрешен в PIC

  1. Перейдите к записи PLT нашего символа.
  2. Перейдите к записи GOT нашего символа.
  3. Вернитесь к записи PLT и поместите смещение в стек. Что смещение на самом деле представляет собой структуру Elf_Rel, описывающую, как исправлять символ.
  4. Перейти к записи-заглушке PLT.
  5. Нажмите указатель на структуру link_map, чтобы компоновщик нашел, к какой библиотеке принадлежит символ.
  6. Процедура распознавателя вызовов.
  7. Исправьте запись GOT.

Это отличается от того, как создается ссылка на данные, которая просто использует таблицу GOT.

Итак, почему существует эта разница? Почему 2 разных подхода?



person ray an    schedule 28.05.2018    source источник
comment
Пожалуйста, не группируйте несвязанные вопросы. это не будет стоить вам дополнительных затрат, если вы попросите два отдельных.   -  person Employed Russian    schedule 29.05.2018
comment
Недавно я задал вопрос (относящийся только к этой теме) и не получил ответа. Не могли бы вы взглянуть на это?   -  person ray an    schedule 29.05.2018
comment
stackoverflow.com/questions/50453228/   -  person ray an    schedule 29.05.2018
comment
Что касается второго вопроса, я сделаю для него новый пост, как вы предложили. спасибо   -  person ray an    schedule 29.05.2018


Ответы (1)


почему такая разница? Почему 2 разных подхода?

То, что вы описали, является ленивым перемещением.

Вам не обязательно использовать его, и вы не будете его использовать, если, например. LD_BIND_NOW=1 установлен в среде.

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

Представьте себе программу, которая может вызывать foo(), bar() или baz(), в зависимости от аргументов, и которая вызывает точно одну из подпрограмм в любом заданном выполнении.

Если бы вы не использовали отложенное перемещение, динамический загрузчик должен был бы разрешить все 3 подпрограммы при запуске программы. Ленивая релокация позволяет динамическому загрузчику выполнять только одну релокацию, которая действительно требуется в каждом заданном выполнении (вызываемая одна функция), и точно в нужное время (когда функция вызывается).

Почему же переменные не могут быть разрешены таким же образом?

Потому что у динамического загрузчика нет удобного способа узнать, когда выполнять это перемещение.

Предположим, что глобальными переменными являются a, b и c, и что foo() ссылается на a и b, bar() ссылается на b и c, а baz() ссылается на a и c. Теоретически динамический загрузчик может сканировать тела foo, bar и baz и строить карту "при вызове foo, то также разрешать глобальные переменные a и b" и т. д. Но гораздо проще и быстрее просто разрешать все ссылки на глобальные переменные в запускать.

person Employed Russian    schedule 29.05.2018