Где в файлах ELF хранится отображение разделов на сегменты?

В рамках попытки написать компилятор полностью с нуля, я сейчас работаю над частью обработки файлов ELF.

После беглого просмотра нескольких статей и спецификаций о них я все еще не совсем понимаю, где хранятся сопоставления разделов на сегменты. Наблюдая за небольшими исполняемыми файлами, сгенерированными NASM + ld, я вижу, что секция .text каким-то образом отображается на заголовок программы типа LOAD, но как?

Небольшой фрагмент вывода readelf, когда в качестве входных данных используется небольшой (рабочий) исполняемый файл:

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000000084 0x0000000000000084  R E    200000

 Section to Segment mapping:
  Segment Sections...
   00     .text 

Требуется ли это сопоставление для рабочего исполняемого файла? Или их можно полностью опустить, и у вас все равно останется действующий исполняемый файл?


person BizarreCake    schedule 11.04.2014    source источник


Ответы (2)


Я до сих пор не совсем понимаю, где хранятся сопоставления разделов на сегменты.

Они нигде не хранятся.

Вместо этого readelf вычисляет отображение, глядя на смещение файла и размер разделов и сегментов.

person Employed Russian    schedule 12.04.2014
comment
Смещения файлов, вот и все! Я думал, что это как-то связано с одинаковыми адресами виртуальной памяти. Спасибо, это работает. - person BizarreCake; 12.04.2014
comment
Вы имеете в виду: если исполняемый файл содержит необязательную таблицу заголовков разделов, тогда эта таблица должна указывать на середину сегментов, содержащих разделы? - person Ciro Santilli 新疆再教育营六四事件ۍ 30.06.2016
comment
@CiroSantilli 巴拿馬 文件 六四 事件 法轮功 Нет, не знал. Вопрос в том, где хранится отображение раздела на сегмент в выходных данных readelf, и ответ заключается в том, что оно вычисляется по запросу самим readelf и нигде не сохраняется. - person Employed Russian; 30.06.2016
comment
Хммм, тогда я не понимаю, как это можно вычислить по запросу (кроме того, что было сказано в предыдущем комментарии, который предоставляется по запросу, но требует необязательного заголовка раздела). То есть заголовок раздела опций отсутствует, значит, его нельзя определить, верно? - person Ciro Santilli 新疆再教育营六四事件ۍ 30.06.2016
comment
@CiroSantilli 巴拿馬 文件 六四 事件 法轮功 Если заголовок раздела отсутствует, то readelf не будет создавать выходные данные сопоставления раздела с сегментом. - person Employed Russian; 30.06.2016
comment
как узнать, есть ли у вас заголовки разделов? это с readelf -S? Если это дает результат, то у вас есть таблица заголовков разделов? В комментариях это указано как Необязательный заголовок раздела, подразумевающий, что присутствует только один из них. Вы имеете в виду массив заголовков разделов? - person Har; 22.05.2017
comment
@Har U может найти разделы с readelf --sections --wide a.out, обратите внимание, что заголовки разделов не являются обязательными и могут отсутствовать вообще. - person clockw0rk; 12.07.2019

Сделал тест по @Employed Russian.

readelf -l ./libandroid_servers.so

Elf file type is DYN (Shared object file)
Entry point 0x0
There are 6 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00000034 0x00000034 0x000c0 0x000c0 R   0x4
  LOAD           0x000000 0x00000000 0x00000000 0x0f830 0x0f830 R E 0x1000
  LOAD           0x010000 0x00010000 0x00010000 0x00cf4 0x011ac RW  0x1000
  DYNAMIC        0x010540 0x00010540 0x00010540 0x00130 0x00130 RW  0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0
  EXIDX          0x00f2e8 0x0000f2e8 0x0000f2e8 0x00548 0x00548 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .hash .dynsym .dynstr .rel.plt .rel.dyn .plt .text .rodata .ARM.extab .ARM.exidx 
   02     .init_array .fini_array .data.rel.ro .dynamic .got .data .bss 
   03     .dynamic 
   04     
   05     .ARM.exidx 

01 Смещение ЗАГРУЗКИ : 0x000000 размер файла 0x0f830
адрес конца раздела .ARM.exidx : шестнадцатеричный (0x00f2e8 + 0x00548) = 0xf830

02 Смещение ЗАГРУЗКИ: 0x010000 fileSize: 0x00cf4
Начальный адрес раздела .init_array : 10000h
адрес конца раздела .bss : шестнадцатеричный (0x00f2e8 + 0) = 0x10cf4

Вы видите, что readelf наверняка распечатывают разделы в сегментах с помощью вычислений. Они хорошо сочетаются.

person Victor Choy    schedule 12.09.2018
comment
Разделы доступны только во время ссылки. Сегменты доступны во время выполнения. Сегменты - это, по сути, просто большие фрагменты данных, а именно несколько разделов, сведенных вместе в соответствующий сегмент. Вы можете видеть, какие разделы в каком разделе находятся с сопоставлением раздела с сегментом. - person clockw0rk; 12.07.2019