GDB показывает неверный адрес перехода в разделе PLT - PullRequest
3 голосов
/ 19 сентября 2019

Я написал следующий пример, чтобы понять раздел 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

1 Ответ

3 голосов
/ 19 сентября 2019

Почему он уже загружен с нетерпением?

Поскольку динамический загрузчик mmap s всех общих библиотек, с которыми вы напрямую ссылаетесь.

Если вы хотите, чтобы разделяемая библиотека загружалась по требованию, вы должны использовать dlopen вместо того, чтобы связывать двоичный файл с libshar.so.

указатель на GOT уже был перезаписан фактической функциейуказатель, но GDB по-прежнему показывает указатель GOT.Почему это так?

Одна из двух вероятных причин:

  1. У вас установлено LD_BIND_NOW в среде или
  2. Ваш двоичный файл был связан с -Wl,-z,now (что может быть значением по умолчанию в более новом дистрибутиве Linux).

Вы можете проверить, верно ли 2 выше с:

readelf -d bin_shared | grep FLAGS

Для двоичного файла -z nowбудет видеть:

  0x000000000000001e (FLAGS)              BIND_NOW
...