Перемещение символа
Ниже показано, как будет вызван вызов функции (в первый раз) в PIC
- Перейти к
PLT
запись нашего символа. - Перейти к
GOT
запись нашего символа. - Перейти к
PLT
введите и сдвиньте смещение в стеке. Что смещение на самом делеElf_Rel
структура, описывающая, как исправить символ. - Перейти к
PLT
запись окурка. - Нажмите указатель на
link_map
структура для того, чтобы компоновщик мог найти, к какой библиотеке принадлежит символ. - Процедура распознавания вызовов.
- Патч
GOT
запись.
Это отличается от того, как делается ссылка на данные, которая просто использует GOT
Таблица
Итак, почему эта разница? Почему 2 разных подхода?
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
"и т. д. Но гораздо проще и быстрее разрешить все ссылки на глобальные переменные при запуске.