简体   繁体   中英

How does cryoPID create ELF headers or is there an easy way for ELF generation?

I'm trying to do a checkpoint/restart program in C and I'm studying cryoPID's code to see how a process can be restarted. In it's code, cryoPID creates the ELF header of the process to be restarted in a function that uses some global variable and it's really confusing.

I have been searching for an easy way to create an ELF executable file, even trying out libelf, but I find that most of the times some necessary information is vague in the documentation of these programs and I cannot get to understand how to do it. So any help in that matter would be great.

Seeing cryoPID's code I see that it does the whole creation in an easy way, not having to set all header fields, etc. But I cannot seem to understand the code that it uses. First of all, in the function that creates the ELF the following code is relevant (it's in 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 is a global variable defined with the macro declare_writer in 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 = &x; \
    char *stub_start = (char*)&_binary_stub_##s##_start; \
    long stub_size = (long)&_binary_stub_##s##_size

This macro is used in writer_*.c which are the files that implement writers for files. For example in writer_buffered.c, the macro is called with this code:

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");

So stub_start gets declared as an uninitialized global variable (the code above is not in any function) and seeing that all the variables in declare_writer are not set in any other part of the code, I assume that stub_start just point to some part of the .bss section, but it seems like cryoPID use it like it's pointing to its own ELF header.

Can anyone help me with this problem or assist me in anyway to create ELF headers easily?

As mentioned in the comment, it uses something similar to objcopy to set those variables (it doesn't use the objcopy command, but custom linkers that I think could be the ones that area "setting" the variables). Couldn't exactly find what, but I could reproduce the behavior by mmap'ing an executable file previously compiled and setting the variables stub_start and stub_size with that map.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM