Заголовки файлов ELF - PullRequest
       21

Заголовки файлов ELF

10 голосов
/ 24 октября 2008

Быстрый вопрос о заголовках файлов elf, я не могу найти ничего полезного о том, как добавлять / изменять поля в заголовке elf. Я хотел бы иметь возможность изменить магические числа и добавить дату сборки в заголовок, и, возможно, несколько других вещей.

Насколько я понимаю, компоновщик создает информацию заголовка, но я не вижу в скрипте LD ничего, что бы на него ссылалось (хотя я новичок в скриптах ld).

Я использую gcc и build для ARM.

спасибо!

Обновление:

  • хорошо, возможно, мой первый вопрос должен быть: возможно ли создать / отредактировать заголовочный файл во время ссылки?

Ответы [ 9 ]

7 голосов
/ 24 октября 2008

Я не знаю команд сценариев компоновщика, которые могут сделать это, но вы можете сделать это после ссылки, используя команду objcopy . Параметр - add-section можно использовать для добавления раздела, содержащего произвольные данные, в файл ELF. Если в заголовке ELF нет нужных полей, просто создайте новый раздел и добавьте их туда.

7 голосов
/ 26 октября 2008

Эта ссылка (двоичный файл elensy elf) была чьим-то ответом на другой вопрос, но в некоторых подробностях она разбирается в тонкостях заголовка ELF.

2 голосов
/ 24 октября 2008

Я вполне уверен, что достаточно сложный скрипт ld может делать то, что вы хотите. Тем не менее, я понятия не имею, как.

С другой стороны, elfsh может легко выполнять любые манипуляции с объектами эльфа, поэтому поверните его.

1 голос
/ 03 ноября 2017

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

идент

Например, как часть процесса сборки вы можете сгенерировать - скажем - info.c, который содержит одну или несколько директив #ident:

#ident "Build: 1.2.3 (Halloween)"
#ident "Environment: example.org"

Скомпилируйте это:

$ gcc -c info.c

Проверьте, включена ли информация:

$ readelf -p .comment info.o
String dump of section '.comment':
  [     1]  Build: 1.2.3 (Halloween)
  [    1a]  Environment: example.org
  [    33]  GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2)

В качестве альтернативы вы можете использовать objdump -s --section .comment info.o. Обратите внимание, что по умолчанию GCC также пишет собственный комментарий.

Проверьте информацию после связывания исполняемого файла ELF:

$ gcc -o main main.o info.o
$ readelf -p .comment main 
String dump of section '.comment':
  [     0]  GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2)
  [    2c]  Build: 1.2.3 (Halloween)
  [    45]  Environment: example.org

Раздел комментариев

Использование #ident в модуле перевода C в основном эквивалентно созданию раздела .comment в файле ассемблера. Пример: * * тысяча двадцать-шесть

$ cat info.s
.section .comment
.string "Build: 1.2.3 (Halloween)"
.string "Environment: example.org"
$ gcc -c info.s
String dump of section '.comment':
  [     0]  Build: 1.2.3 (Halloween)
  [    19]  Environment: example.org

Использование необычного имени раздела также работает (например, .section .blahblah). Но .comment используется и понимается другими инструментами. GNU as также понимает директиву .ident, и именно это GCC переводит #ident в.

с символами

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

Objcopy

Скажем, вы хотите включить несколько магических байтов, хранящихся в файле данных:

$ cat magic.bin 
2342

Преобразовать в объектный файл с помощью GNU objcopy :

$ objcopy -I binary -O elf64-x86-64 -B i386 \
    --rename-section .data=.rodata,alloc,load,readonly,data,contents \
    magic.bin magic.o

Проверьте символы:

$ nm  magic.o  
0000000000000005 R _binary_magic_bin_end
0000000000000005 A _binary_magic_bin_size
0000000000000000 R _binary_magic_bin_start

Пример использования:

#include <stdio.h>
#include <string.h>
#include <inttypes.h>

extern const char _binary_magic_bin_start[];
extern const char _binary_magic_bin_end[];
extern const unsigned char _binary_magic_bin_size;
static const size_t magic_bin_size = (uintptr_t) &_binary_magic_bin_size;

int main()
{
  char s[23];
  memcpy(s, _binary_magic_bin_start,
      _binary_magic_bin_end - _binary_magic_bin_start);
  s[magic_bin_size] = 0;
  puts(s);
  return 0;
}

Свяжите все вместе:

$ gcc -g -o main_magic main_magic.c magic.o

GNU ld

GNU ld также может преобразовывать файлы данных в объектные файлы, используя схему именования, совместимую с objcopy:

$ ld -r -b binary magic.bin -o magic-ld.o

В отличие от objcopy, он помещает символы в .data вместо .rodata, хотя (ср. objdump -h magic.o).

INCBIN

Если объект GNU objcopy недоступен, можно использовать GNU в качестве директивы .incbin для создания объектного файла (сборка с gcc -c incbin.s):

    .section .rodata

    .global _binary_magic_bin_start
    .type _binary_magic_bin_start, @object
_binary_magic_bin_start:
    .incbin "magic.bin"
    .size _binary_magic_bin_start, . - _binary_magic_bin_start

    .global _binary_magic_bin_size
    .type _binary_magic_bin_size, @object
    .set _binary_magic_bin_size, . - _binary_magic_bin_start

    .global _binary_magic_bin_end
    .type _binary_magic_bin_end, @object
    .set _binary_magic_bin_end, _binary_magic_bin_start + _binary_magic_bin_size
    ; an alternate  way to include the size    
    .global _binary_magic_bin_len
    .type _binary_magic_bin_len, @object
    .size _binary_magic_bin_len, 8
_binary_magic_bin_len:
    .quad _binary_magic_bin_size

XXD

Более переносимая альтернатива, которая не требует GNU objcopy или GNU, как, например, создать промежуточный файл C, скомпилировать и связать его. Например, с xxd :

$ xxd -i magic.bin | sed 's/\(unsigned\)/const \1/' > magic.c
$ gcc -c magic.c
$ nm magic.o
0000000000000000 R magic_bin
0000000000000008 R magic_bin_len
$ cat magic.c
const unsigned char magic_bin[] = {
  0x32, 0x33, 0x34, 0x32, 0x0a
};
const unsigned int magic_bin_len = 5;
0 голосов
/ 28 октября 2008

В консоли Linux:

$ man ld

$ ld --verbose

НТН

0 голосов
/ 25 октября 2008

Я не закончил книгу, но в iirc Линкеры и загрузчики Джона Левина были мрачные детали, которые вам понадобятся, чтобы это сделать.

0 голосов
/ 24 октября 2008

В Solaris вы можете использовать elfedit , но я думаю, что вы действительно ищете решения для Linux. Linux не является UniX: P

0 голосов
/ 24 октября 2008

Я давно этого не делал, но вы не можете просто добавить произвольные данные в исполняемый файл. Если вы всегда добавляете данные фиксированного размера, было бы тривиально восстановить все, что вы добавляете. Переменный размер не будет намного сложнее. Вероятно, проще, чем испортить заголовки w / elf и потенциально испортить вам исполняемые файлы.

0 голосов
/ 24 октября 2008

Вы можете использовать libmelf, мертвый проект на свежем мясе, но доступный в LOPI - http://www.ipd.bth.se/ska/lopi.html

В противном случае вы можете получить спецификацию и (пере) написать заголовок самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...