Загрузка / выгрузка секций ELF по запросу? - PullRequest
3 голосов
/ 30 октября 2009

Для довольно неясного варианта использования я хотел бы иметь (большой) статически связанный исполняемый файл Linux, состоящий из небольшого фрагмента управляющего кода и больших фрагментов статических (только для чтения) данных. Можно ли для экономии памяти заставить загрузчик загружать только секции для управляющего кода, а затем вручную загружать секции данных RO по мере необходимости и выгружать их снова после завершения обработки?

Возможно ли это?

(Я полагаю, что для решения этой проблемы можно использовать потоки данных (на уровне файловой системы), но они недоступны для меня (EXT3), и распределение будет затруднительным, поскольку потоки данных легко теряются.)

Ответы [ 4 ]

4 голосов
/ 31 октября 2009

Об этом (очень вероятно) уже позаботились о вас.

Реальный ответ, конечно, будет зависеть от системы, но, как правило, современные операционные системы (и, конечно, Linux) используют подкачку по требованию для исполняемых файлов, поэтому фактически ОЗУ не будет выделено для разделов файла ELF, на которые вы не ссылаетесь .

1 голос
/ 22 мая 2011

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

Доказательство:

$ cat /proc/self/maps
**08048000**-08052000 r-xp 00000000 08:03 78433      /bin/cat
**08052000**-08053000 rw-p 0000a000 08:03 78433      /bin/cat
...

Это только две части из того, что будет отображено. Зачем? Потому что это единственные, которые имеют тип DT_LOAD:

$ readelf -l /bin/cat

Elf file type is EXEC (Executable file)
Entry point 0x8049cf8
There are 8 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
  INTERP         0x000134 0x08048134 0x08048134 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 **0x08048000** 0x08048000 0x09ba0 0x09ba0 R E 0x1000  <<
  LOAD           0x00a000 **0x08052000** 0x08052000 0x00228 0x00804 RW  0x1000  <<
  DYNAMIC        0x00a014 0x08052014 0x08052014 0x000c8 0x000c8 RW  0x4
  NOTE           0x000148 0x08048148 0x08048148 0x00044 0x00044 R   0x4
  GNU_EH_FRAME   0x008c48 0x08050c48 0x08050c48 0x002a4 0x002a4 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

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

На практике у вас будет доступ только к первым 40 КиБ (0x8052000-0x8048000 = 40960 байт) файла. Этого достаточно для заголовков ELF, но вы не сможете получить доступ, например, к заголовкам DWARF .debug, не говоря уже о таблице строк (.strtab).

Если вы хотите получить доступ ко всем разделам ELF, проще всего будет отобразить весь файл.

1 голос
/ 06 ноября 2009

Вместо того, чтобы связывать ваши двоичные объекты в двоичный файл, добавляйте их к нему. Они не будут отображаться, но вы можете читать или отображать их по мере необходимости.

0 голосов
/ 30 октября 2009

Нет, если это часть файла ELF, он будет отображен. Я не уверен в деталях ELF, но если бы это был PE-файл, вы могли бы просто добавить свои добавленные данные в конец PE-файла, за пределы структуры PE. Данные, которые не являются частью структуры PE, не отображаются в памяти в Windows. Я подозреваю, что то же самое существует в ELF.

...