Как работает импорт в программах?
Разбирался как работает импорт и непонятна одна вещь.Но все по порядку.Когда мы в программе вызываем какую то функцию,имя этой функции является адресом функции.Так...Если написать такой код:
std::cout << Beep << std::endl;
Мы получим адрес функции Beep из подгруженной библиотеки kernel32.dll.Но откуда берется этот адрес?Как программа знает где загружена эта функция,точнее ее адрес?Я знаю, что адрес можно получить из таблицы импорта,ссылавшись на поле FirstThunk структуры _IMAGE_IMPORT_DESCRIPTOR,но смотря на дизассемблер,там адрес функции выглядит примерно так: qword ptr ds:[<&Beep>] .Читаю про регистр ds,он должен ссылаться на секцию данных.Смотрю на регистр,он у меня: DS 002B. C этого момента я в тупике.Ведь,что это за смещение такое "002B", оно ведь слишком маленькое,откуда его отсчитывать..Мне крайне непонятен механизм импорта и связывания функций.
Ответы (1 шт):
Если написать такой код ... Мы получим адрес функции Beep из подгруженной библиотеки kernel32.dll
То, что выведет код std::cout << Beep, далеко не обязательно реальный адрес функции, причины описаны здесь: Что такое адрес функции?
Читаю про регистр ds,он должен ссылаться на секцию данных
Скорее всего, это просто ошибка дизассемблера, с чего бы адресу функции быть в секции данных? У меня вызов функции Beep превращается вот в такое в выводе dumpbin /disasm:
FF 15 00 B0 41 00 call dword ptr [__imp__Beep@8]
Код инструкции FF 15 (с учетом opcode extensions) здесь обозначает "Call near, absolute indirect, address given in r/m32" - т.е. вызов функции по адресу в заданной ячейке памяти (см. https://c9x.me/x86/html/file_module_x86_id_26.html). Операнд 00 B0 41 00 - сам адрес (перевернутый). Человеко-читаемый адрес тут будет: 0x41B000. Смотрим в выводе dumpbin секции:
SECTION HEADER #5
.idata name
CDF virtual size
1B000 virtual address (0041B000 to 0041BCDE)
То есть адрес функции ожидаемо попадает в секцию .idata, таблицу импорта. Из вывода dumpbin /imports узнать более точно:
KERNEL32.dll
41B000 Import Address Table
41B268 Import Name Table
Как видно, 41B000 - это начало Import Address Table модуля KERNEL32.dll. Эта таблица заполняется загрузчиком ОС при запуске программы, куда он пишет уже реальные адреса функций в загруженных модулях.