#c #elf
#c #elf
Вопрос:
Я пытаюсь создать программу проверки / перезапуска на C и изучаю код CryoPID, чтобы увидеть, как процесс может быть перезапущен. В своем коде CryoPID создает заголовок ELF процесса для перезапуска в функции, которая использует некоторую глобальную переменную, и это действительно сбивает с толку.
Я искал простой способ создания исполняемого файла ELF, даже опробовал libelf, но я обнаружил, что в большинстве случаев некоторая необходимая информация расплывчата в документации этих программ, и я не могу понять, как это сделать. Так что любая помощь в этом вопросе была бы отличной.
Просматривая код CryoPID, я вижу, что он выполняет все создание простым способом, без необходимости устанавливать все поля заголовка и т. Д. Но, похоже, я не могу понять код, который он использует. Прежде всего, в функции, которая создает ELF, имеет значение следующий код (он находится в arch-x86_64/elfwriter.c):
Elf64_Ehdr *e;
Elf64_Shdr *s;
Elf64_Phdr *p;
char* strtab;
int i, j;
int got_it;
unsigned long cur_brk = 0;
e = (Elf64_Ehdr*)stub_start;
assert(e->e_shoff != 0);
assert(e->e_shentsize == sizeof(Elf64_Shdr));
assert(e->e_shstrndx != SHN_UNDEF);
s = (Elf64_Shdr*)(stub_start (e->e_shoff (e->e_shstrndx*e->e_shentsize)));
strtab = stub_start s->sh_offset;
stub_start — это глобальная переменная, определенная с помощью макроса declare_writer в cryopid.h:
#define declare_writer(s, x, desc)
extern char *_binary_stub_##s##_start;
extern int _binary_stub_##s##_size;
struct stream_ops *stream_ops = amp;x;
char *stub_start = (char*)amp;_binary_stub_##s##_start;
long stub_size = (long)amp;_binary_stub_##s##_size
Этот макрос используется в writer_ *.c, которые являются файлами, которые реализуют записи для файлов. Например, в writer_buffered.c макрос вызывается с помощью этого кода:
struct stream_ops buf_ops = {
.init = buf_init,
.read = buf_read,
.write = buf_write,
.finish = buf_finish,
.ftell = buf_ftell,
.dup2 = buf_dup2,
};
declare_writer(buffered, buf_ops, "Writes an output file with buffering");
Итак, stub_start объявляется как неинициализированная глобальная переменная (приведенный выше код отсутствует ни в одной функции), и, видя, что все переменные в declare_writer не заданы ни в какой другой части кода, я предполагаю, что stub_start просто указывает на какую-то часть раздела .bss, но, похоже, CryoPID использует егокак будто он указывает на свой собственный заголовок ELF.
Может ли кто-нибудь помочь мне с этой проблемой или помочь мне в любом случае легко создавать заголовки ELF?
Комментарии:
1. И
_binary_stub_XXXXX_start
,_size
вероятно, исходят из некоторых двоичных данных, преобразованных в объектный файл с помощью objcopy .
Ответ №1:
Как упоминалось в комментарии, он использует что-то похожее на objcopy для установки этих переменных (он не использует команду objcopy, но пользовательские компоновщики, которые, я думаю, могут быть теми, которые «устанавливают» переменные). Не удалось точно найти, что, но я мог бы воспроизвести поведение, сопоставив исполняемый файл, ранее скомпилированный, и установив переменные stub_start и stub_size с этой картой.