Мне нужно добавить произвольный раздел в файл ELF. Я не могу использовать код GPL в этой программе, поэтому BFD не может быть и речи. Я могу использовать libelf/gelf для чтения разделов, но документация для них довольно скудна, и я не могу понять, как добавить раздел. Кто-нибудь знает, как это сделать? Я бы предпочел написать собственный код ELF.
Добавление раздела в файл ELF
Ответ 1
Вот несколько (возможно) связанных ответов в этом вопросе об заголовках файлов ELF. В принятом ответе упоминалось использование objcopy
для добавления разделов в файл ELF, а BSD bintools утверждает, что имеет лицензированную BSD реализацию objcopy
, который может удовлетворить ваши потребности.
Ответ 2
Я знаю, что это старый вопрос, но я нашел рабочий пример, который помог мне применить его к моему проекту. (Если кто-то наткнется на этот вопрос)
взято из Sourceware Mail Archiv
$ echo 'int main() { puts ("Hello world"); }' | gcc -x c - -c -o hello.o
$ echo "this is my special data" >mydata
$ objcopy --add-section .mydata=mydata \
--set-section-flags .mydata=noload,readonly hello.o hello2.o
$ gcc hello2.o -o hello
$ ./hello
Hello world
$ objdump -sj .mydata hello
Ответ 3
Следующие ссылки могут быть полезны:
- Учебник libelf by Example" содержит раздел о создании новых объектов ELF.
- проект elftoolchain содержит подробные страницы с описанием
libelf
API.
Ответ 4
взгляните на ELFsh, который теперь является частью проекта ERESI http://www.eresi-project.org/ У них есть много документации и прохладное использование их инструментов.
Ответ 5
Не пробовал (пока) сам, но вы можете посмотреть на функцию elf_newscn в libelf
Ответ 6
Вы можете посмотреть на этот код:
#include "packer.h"
extern uint64_t loader_size;
extern uint64_t infos_size;
extern void entry_loader(void);
static Elf64_Shdr new_section = {
.sh_name = (uint32_t)0,
.sh_type = (uint32_t)SHT_PROGBITS,
.sh_flags = (uint64_t)SHF_EXECINSTR | SHF_ALLOC,
.sh_addr = (Elf64_Addr)0,
.sh_offset = (Elf64_Off)0,
.sh_size = (uint64_t)0,
.sh_link = (uint32_t)0,
.sh_info = (uint32_t)0,
.sh_addralign = (uint64_t)16,
.sh_entsize = (uint64_t)0,
};
uint64_t entry_addr, entry_size, key;
static int32_t create_section(t_elf *elf, uint16_t last_section, uint16_t last_ptload)
{
Elf64_Shdr *new_shdrs;
uint8_t **new_sects;
uint8_t *loader;
elf->elf_header->e_shnum += 1;
if (!(new_shdrs = realloc(elf->section_header, sizeof(Elf64_Shdr) * elf->elf_header->e_shnum))) {
perror("realloc");
return (-1);
}
if (!(new_sects = realloc(elf->section_data, sizeof(uint8_t *) * elf->elf_header->e_shnum))) {
perror("realloc");
return (-1);
}
elf->section_header = new_shdrs;
elf->section_data = new_sects;
new_section.sh_offset = elf->prog_header[last_ptload].p_offset + elf->prog_header[last_ptload].p_memsz;
new_section.sh_addr = elf->prog_header[last_ptload].p_vaddr + elf->prog_header[last_ptload].p_memsz;
new_section.sh_size = loader_size;
if (!(loader = malloc(loader_size))) {
perror("malloc");
return (-1);
}
memcpy(loader, (void *)entry_loader, loader_size);
memcpy(loader + loader_size - 24, &key, sizeof(uint64_t));
memcpy(loader + loader_size - 16, &entry_addr, sizeof(uint64_t));
memcpy(loader + loader_size - 8, &entry_size, sizeof(uint64_t));
memmove(new_shdrs + last_section + 2, new_shdrs + last_section + 1, sizeof(Elf64_Shdr) * (elf->elf_header->e_shnum - last_section - 2));
memmove(new_sects + last_section + 2, new_sects + last_section + 1, sizeof(uint8_t *) * (elf->elf_header->e_shnum - last_section - 2));
memcpy(new_shdrs + last_section + 1, &new_section, sizeof(Elf64_Shdr));
new_sects[last_section + 1] = loader;
return (0);
}
Код не очень сложен для понимания, но если вы хотите узнать контекст или то, как этот раздел вставлен в elf, вы можете взглянуть на оригинальную реализацию этой функции в упаковщике sebastiencs:
https://github.com/sebastiencs/Packer_ELF/blob/master/src/insert_section.c