我正在尝试在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是使用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 :(得分:0)
正如评论中所提到的,它使用类似于objcopy的东西来设置这些变量(它不使用objcopy命令,但我认为可以是“设置”变量区域的自定义链接器)。无法准确找到什么,但我可以通过mmap'先前编译的可执行文件并使用该映射设置变量stub_start和stub_size来重现行为。