Я написал следующий пример, чтобы понять раздел PLT / GOT.
Общая библиотека libshar
код:
shared.h
int sum(int a, int b);
shared.c
#include "shared.h"
int sum(int a, int b){
return a + b;
}
Исполняемый код bin_shared
:
#include <stdio.h>
#include "shared.h"
int main(void){
printf("Starting the programm... \n");
int s = sum(1, 2); //<=== I expected the dynamic linker would be called here
int s2 = sum(2, 3);
printf("s = %d, s2 = %d\n", s, s2);
}
Поэтому я скомпилировал и связал разделяемую библиотеку с исполняемым файлом и написал следующий gdb-скрипт, чтобы войти в код динамического компоновщика.Я ожидал, что он будет выполнен при первом вызове sum
.
set pagination off
file build/bin_shared
b main
commands
layout asm
info proc mappings
end
r
Я столкнулся с двумя проблемами:
I. Когда была достигнута точка останова в записи функции main
, info proc mappings
показывает, что libshar.so
уже был сопоставлен:
0x7ffff7bd3000 0x7ffff7bd4000 0x1000 0x0 /home/me/c/build/libshar.so
0x7ffff7bd4000 0x7ffff7dd3000 0x1ff000 0x1000 /home/me/c/build/libshar.so
0x7ffff7dd3000 0x7ffff7dd4000 0x1000 0x0 /home/me/c/build/libshar.so
0x7ffff7dd4000 0x7ffff7dd5000 0x1000 0x1000 /home/me/c/build/libshar.so
Функция общей библиотеки sum
еще не была вызвана.Почему он уже загружен с нетерпением?
II. При вводе sum@plt
в первый раз я вижу следующее asm:
0x555555554690 <sum@plt> jmp QWORD PTR [rip+0x200932] # 0x555555754fc8
Это указатель на GOT, как и ожидалось:
(gdb) disassemble 0x555555754fc8
Dump of assembler code for function _GLOBAL_OFFSET_TABLE_:
Но проблема в том, что пошаговое выполнение одной команды в этот момент получает gdb
прямо в
0x7ffff7bd3580 <sum> lea eax,[rdi+rsi*1]
означает, что указатель на GOT уже был перезаписан фактическим указателем на функцию, но GDB по-прежнему показывает указатель GOT.Почему это так?
Я извлек необработанную память по адресу от jmp
до GOT
в надежде найти перезаписанный адрес, но он не похож на один:
(gdb) x/2xg 0x555555554690
0x555555554690 <sum@plt>: 0x01680020093225ff 0xffffffd0e9000000