2011-10-13 20 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來重現該行爲。