Косвенные указатели на назначение функций отображаемых библиотек - C - OSX
Учитывая следующий простой фрагмент кода:
int main (void) {
void* foo = scanf;
void* bar = sscanf;
}
Вот разборка (взята из исполняемого файла mach-o):
Небольшая часть неленивых символических указателей:
Малая часть таблицы символов:
Кажется, я не понимаю 5-ую и 6-ю строчки в исполняемом файле (Movq от scanf & sscanf в rax/rcx). Как foo и bar (в конце концов) имеют адреса scanf & sscanf соответственно. Я думаю, что это как-то связано с динамическими библиотеками, которые сопоставляются с процессом (и ленивые указатели символов, скорее всего, указывают на это или что-то в этом роде), но я не могу понять, как это сделать.
Спасибо
2 ответа
Сгенерированный код загружает адрес scanf
из ленивого указателя символа. Там нет ничего особенного. Когда dyld загружает исполняемый файл, он "связывает" каждый ленивый указатель символа, устанавливая его значение в правильный адрес символа.
Не ленивые символьные указатели используются для ссылок, которые (1) указывают на что-то в другой библиотеке, и (2) являются ссылками на данные, а не вызовами функции. В вашем примере вы не звоните scanf
непосредственно, так что это ссылка на данные, и scanf
отсутствует в вашем исполняемом файле, поэтому это ссылка на другую библиотеку.
Ссылки в одном и том же исполняемом файле использовали фиксированное относительное смещение ПК: компилятор и компоновщик знают, что код и данные будут загружаться рядом друг с другом, поэтому они могут выбирать смещение во время сборки. Ссылки на вызовы функций ленивы: во время выполнения первый вызов функции направляется через dyld first, который ищет символ и связывает ленивый указатель символа для будущих вызовов.
Как указал 0xced, вы можете установить переменную окружения DYLD_PRINT_BINDINGS
смотреть работу Дилда. Страница руководства dyld описывает другие переменные, которые вы можете установить.
Динамический компоновщик dyld отвечает за связывание символов. Чтобы увидеть, что происходит, сначала скомпилируйте ваш тестовый проект с -fno-pie
возможность отключить независимый от позиции исполняемый файл. Таким образом, смещение, которое вы видите в MachOView, будет таким же во время выполнения. Затем запустите исполняемый файл с DYLD_PRINT_BINDINGS
переменная окружения установлена в YES
, Вот результат:
$ DYLD_PRINT_BINDINGS=YES ./a.out
dyld: bind: a.out:0x100001010 = libsystem_c.dylib:_scanf, *0x100001010 = 0x7FFF94578017
dyld: bind: a.out:0x100001018 = libsystem_c.dylib:_sscanf, *0x100001018 = 0x7FFF94578707
...