Разрешение ссылок во время ссылки или во время выполнения? - PullRequest
0 голосов
/ 03 апреля 2012

Друзья, у меня есть два файла, ac и bc.Я определил функцию foo в ac, которая вызывается из bc

. Насколько я понимаю, когда компилятор пытается скомпилировать bc, он увидит, что реализация foo находится не в b, поэтомудобавит запись для foo в таблицу символов, которая будет разрешена во время компоновки.Я правильно понял эту концепцию.

Теперь у меня есть другая функция printf в bc, которая реализована в glibc.Из того, что я понимаю, printf может быть связан во время загрузки или во время выполнения.Если printf будет связан во время выполнения, для каждого вызова printf должна быть заглушка, которая будет разрешена во время выполнения с помощью системного вызова.

мой вопрос: «Правильно ли мое понимание ???+ как компилятор определяет, что функция foo будет разрешена компоновщиком, а не во время выполнения ??? "

я заметил несколько похожих вопросов, но не смог понять их значение здесь ???

1 Ответ

3 голосов
/ 04 апреля 2012

Я нахожу ваш вопрос немного трудным для чтения, поэтому я не совсем уверен, как вы его понимаете, поэтому я просто опишу, как он работает.

  1. Если символв этом же файле (bc) компилятор ссылается на него напрямую.Компоновщик не используется для разрешения чего-либо.

  2. Если символ находится не в том же файле, а -fPIC - это , а не , то компилятор просто выдаетвызов неопределенного символа.В этом случае компоновщик будет искать символ в других файлах .o или в библиотеках и вставлять прямую ссылку во время ссылки, в основном вставляя ее в пробел.

    Это именно то, как вы обычно строитепрограмма (в отличие от библиотеки).Если программа использует динамические библиотеки, то могут быть некоторые символы, которые нельзя исправить во время соединения.Если это так, компоновщик проверит, есть ли в библиотеке их, и он будет предоставлен динамическому компоновщику, чтобы завершить работу во время выполнения.

    Можно было бы сделать это точно также в общих библиотеках, толькос динамическим компоновщиком, всегда вставляющим адреса в программу во время выполнения, но это означало бы, что библиотека shared не может быть общей: каждая программа должна иметь свою собственную копию со своим исправлением-UPS.Вот почему этого не происходит.

  3. Если символ находится не в том же файле, а -fPIC указан , то компилятор не используетимя символа напрямую.Вместо этого он вызывает функции через PLT (таблица связывания процедур) и получает адрес других символов через GOT (глобальную таблицу смещений).

    GOT - это специальная таблица, созданная компоновщиком, и в основном этопросто список неопределенных ссылок на символы, похожих на те, которые вы найдете в обычной не PIC-программе (за исключением того, что они обычно смещаются к основанию GOT).Динамический компоновщик заполняет пробелы во время выполнения.Компилятор организует, чтобы адрес GOT всегда находился в определенном регистре ЦП, чтобы всегда можно было найти таблицу.

    PLT - это набор батутов, созданных компоновщиком.Компилятор создает переходы в PLT, а динамический компоновщик устанавливает PLT для возврата к реальному расположению функции.На самом деле, во многих случаях PLT не заполняется динамическим компоновщиком при загрузке библиотеки: PLT заполняет себя при первом вызове с помощью GOT (это самоизменяющийся код).

    Вот почему динамические библиотеки обычно создаются с -fPIC: GOT и PLT можно изменять для каждой программы, сохраняя при этом текст библиотек неизмененным и, следовательно, позволяя им оставаться общими.

Итак, теперь ответы на ваши вопросы:

Я думаю, что заглушка, о которой вы говорили, может быть PLT?

Компилятор делает не знать, когда функция будет решена.Он только знает, что не может решить это сам.Фактически, когда вы используете динамические библиотеки, компоновщик даже не пытается разрешить символы полностью (хотя я думаю, что он проверяет, определены ли они в библиотеке);это означает, что можно переопределить определенную функцию в библиотеке, предоставив другую функцию с тем же именем.Такие инструменты, как tsocks, используют это вместе с LD_PRELOAD для перехвата библиотечных вызовов.

...