Возможно, ваше замешательство имеет значение extern
. Поскольку по умолчанию используется значение extern
, любая переменная, объявленная вне области действия функции без ключевого слова static
, равна extern
.
Причина, по которой GOT необходим, заключается в том, что адрес переменных, к которым обращается код совместно используемой библиотеки, неизвестен во время создания разделяемой библиотеки. Это зависит либо от адреса загрузки, по которому загружается библиотека (если определение находится в самой библиотеке), либо от стороннего кода, в котором определена переменная (если определение находится в другом месте). Поэтому вместо того, чтобы вставлять адрес в код в коде, компилятор генерирует код для чтения GOT совместно используемой библиотеки, а затем загружает адрес из GOT во время выполнения.
Если переменная известна и должна быть определена в той же общей библиотеке (либо потому, что она использовала static
, либо hidden
или protected
атрибут видимости, который она использовала), то адрес относительно к коду в библиотеке можно исправить при создании файла общей библиотеки. В этом случае, вместо того, чтобы выполнять поиск через GOT, компилятор просто генерирует код для доступа к переменной с программно-счетной адресацией. Это дешевле как во время выполнения, так и во время загрузки (поскольку весь поиск символов и процесс перемещения могут быть пропущены во время загрузки).