Заголовки программы ELF и виртуальный адрес

Я понимаю ELF и его заголовки программ. Когда я читаю ELF, используя readelf с типом файла как DYN. Я вижу, что значение виртуального адреса в заголовках программ фактически взято из виртуального адресного пространства ядра.

Elf file type is DYN (Shared object file)
Entry point 0x1060
There are 13 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000002d8 0x00000000000002d8  R      0x8
  INTERP         0x0000000000000318 0x0000000000000318 0x0000000000000318
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000600 0x0000000000000600  R      0x1000
  LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                 0x00000000000001f5 0x00000000000001f5  R E    0x1000
  LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000
                 0x0000000000000168 0x0000000000000168  R      0x1000
  LOAD           0x0000000000002db8 0x0000000000003db8 0x0000000000003db8
                 0x0000000000000258 0x0000000000000260  RW     0x1000
  DYNAMIC        0x0000000000002dc8 0x0000000000003dc8 0x0000000000003dc8
                 0x00000000000001f0 0x00000000000001f0  RW     0x8
  NOTE           0x0000000000000338 0x0000000000000338 0x0000000000000338
                 0x0000000000000020 0x0000000000000020  R      0x8
  NOTE           0x0000000000000358 0x0000000000000358 0x0000000000000358
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_PROPERTY   0x0000000000000338 0x0000000000000338 0x0000000000000338
                 0x0000000000000020 0x0000000000000020  R      0x8
  GNU_EH_FRAME   0x0000000000002018 0x0000000000002018 0x0000000000002018
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000002db8 0x0000000000003db8 0x0000000000003db8
                 0x0000000000000248 0x0000000000000248  R      0x1

Я могу определить фактический VirtAddr во время загрузки двоичного файла, который должен быть = Base Address + VirtAddr. Но я не могу узнать, как загрузчик вычисляет значение базового адреса?

Кроме того, я знаю, что .text и .data - это два сегмента PT_LOAD для загрузки двоичного файла. Но в моем примере я вижу 4 заголовка программы PT_LOAD. Для чего используются два заголовка программы PT_LOAD?


person shivank    schedule 08.08.2020    source источник
comment
См. docs.oracle.com/cd/E19683 -01 / 816-1386 / chapter6-83432 / index.html   -  person Xypron    schedule 08.08.2020
comment
На самом деле я получил представление о базовом адресе только на этой странице. В нем говорится, что исполняемые и общие объектные файлы имеют базовый адрес, который является наименьшим виртуальным адресом, связанным с образом памяти объектного файла программы. Одно из применений базового адреса - перемещение образа программы в памяти во время динамического связывания. Но я все еще не понимаю, как найти этот самый низкий виртуальный адрес?   -  person shivank    schedule 08.08.2020


Ответы (2)


Я вижу, что значение виртуального адреса в заголовках программ фактически взято из виртуального адресного пространства ядра.

Нет, вы не этого видите. Ни один из адресов в вашем выводе не имеет ничего общего с ядром.

Перед вами независимый от позиции исполняемый файл, который может быть загружается где угодно в памяти.

Я не могу узнать, как загрузчик вычисляет значение базового адреса?

Загрузчик не загружает основной исполняемый файл (это делает ядро) и не определяет адрес загрузки.

Учитывая, что тип файла ET_DYN, ядро ​​выполняет эквивалент mmap(0, ...) (без флага MAP_FIXED) и выбирает подходящий виртуальный адрес, который затем передается загрузчику в векторе aux.

Но в моем примере я вижу 4 заголовка программы PT_LOAD. Для чего используются два заголовка программы PT_LOAD?

См. этот ответ.

person Employed Russian    schedule 10.08.2020

Это не программа с установленным базовым адресом. Вместо этого это независимый от позиции исполняемый файл, который может быть связан с любым адресом в памяти, тем самым обеспечивая рандомизацию компоновки адресного пространства, то есть ALSR.

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

Самый низкий адрес виртуальной памяти здесь - это именно 0x0000000000000040, что соответствует смещению файла 0x0000000000000040.

person Antti Haapala    schedule 08.08.2020