2011-10-13 18 views
0

我试图做的在C检查点/重新启动程序,我正在学习cryoPID的代码,看看进程如何重新启动。在它的代码中,cryoPID在使用某个全局变量的函数中创建要重新启动的进程的ELF头,这实际上令人困惑。cryoPID如何创建ELF头文件或者是否有一个简单的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是在cryopid.h宏declare_writer定义一个全局变量:

#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 

该宏用于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头?

+0

'_binary_stub_XXXXX_start'和'_size'可能来自使用[objcopy](http://sourceware.org/binutils/docs-2.16/binutils/objcopy.html)转换为目标文件的一些二进制数据。 – user786653

回答

0

正如在评论中提到的那样,它使用类似于objcopy的设置来设置这些变量(它不使用objcopy命令,但我认为可能是区域“设置”变量的自定义连接器)。无法准确找到什么,但是我可以通过对先前编译的可执行文件进行mmap处理并使用该地图设置变量stub_start和stub_size来重现该行为。