Ответ 1
Краткое объяснение: gp
, по всем практическим меркам, является скрытым параметром для всех функций, соответствующих Itanium ABI. Это своего рода указатель this
для глобальных переменных, которые использует функция. Насколько я знаю, никакая основная ОС не делает этого больше.
GP означает "указатель globals". Это базовый адрес для данных, статически выделяемых исполняемыми файлами, а для архитектуры Itanium для этого есть регистр.
Например, если у вас были эти глобальные переменные и эта функция в вашей программе:
int foo;
int bar;
int baz;
int func()
{
foo++;
bar += foo;
baz *= bar / foo;
return foo + bar + baz;
}
Пара gp/function концептуально будет &foo, &func
. Код, сгенерированный для func
, будет ссылаться на gp
, чтобы найти, где находятся глобальные блоки. Компилятор знает, что foo
можно найти в gp
, bar
можно найти в gp + 4
и baz
можно найти в gp + 8
.
Предполагая, что func
определяется во внешней библиотеке, если вы вызываете его из своей программы, компилятор будет использовать последовательность инструкций, подобных этой:
- сохранить текущее значение gp в стеке;
- введите код нагрузки из пары для
func
в некоторый регистр; - загрузить значение gp из той же пары в GP;
- выполнить косвенный вызов в регистре, где мы сохранили адрес кода;
- восстановить прежнее значение gp, которое мы сохранили в стек раньше, возобновить функцию вызова.
Это делает исполняемые файлы полностью независимыми от позиции, поскольку они никогда не сохраняют абсолютные адреса в символах данных и, следовательно, позволяют поддерживать только один экземпляр любого исполняемого файла в памяти, независимо от того, сколько его использует процесс (вы могли бы даже загружать один и тот же исполняемый файл несколько раз в течение одного процесса и по-прежнему иметь только одну копию исполняемого кода в системе), за счет того, что указатели функций немного странные. С помощью Itanium ABI указатель на функцию не является кодовым адресом (например, с "регулярными" x86 ABI): это адрес для значения gp и адрес кода, поскольку этот код может не стоить многого, если он может " t получить доступ к своим глобальным переменным, точно так же, как метод, возможно, не сможет многое сделать, если у него нет указателя this
.
Единственный другой ABI, который я знаю, использует эту концепцию Mac OS Classic PowerPC ABI. Они называли эти пары "переходными векторами".
Так как x86_64 поддерживает RIP-относительную адресацию (x86 не имеет эквивалентной EIP-относительной адресации), теперь довольно легко создать независимый от позиции код без необходимости использовать дополнительный регистр или использовать "расширенные" указатели на функции. Код и данные просто должны храниться при постоянных смещениях. Таким образом, эта часть Itanium ABI, вероятно, ушла на пользу на платформах Intel.
Из Соглашения о регистрации Itanium:
8.2 Регистр gp
Каждая процедура, которая ссылается на статически распределенные данные или вызывает другую процедуру, требует указатель на свой сегмент данных в регистре gp, чтобы он мог получить доступ к своим статическим данным и их таблицам связей. Каждый загрузочный модуль имеет свой собственный сегмент данных, а регистр gp должен быть установлен правильно до вызова любой точки входа в этом загрузочном модуле.
Соглашения о привязке требуют, чтобы каждый модуль загрузки определял ровно одно значение gp, чтобы ссылаться на местоположение в его коротком сегменте данных. Ожидается, что это местоположение будет выбрано так, чтобы максимизировать полезность немедленных инструкций короткого перемещения для адресации скаляров и записей таблицы привязки. DLL-загрузчик будет определять абсолютное значение регистра gp для каждого загрузочного модуля после загрузки его сегмента данных в память.
Для вызовов внутри модуля загрузки регистр gp останется без изменений, поэтому вызовы, известные как локальные, могут быть оптимизированы соответствующим образом.
Для вызовов между модулями нагрузки регистр gp должен быть инициализирован с правильным значением gp для нового модуля загрузки, а вызывающая функция должна гарантировать, что его собственное значение gp будет сохранено и восстановлено.