[CRIU] [PATCH 01/16] piegen: Implement tool building, v2

Cyrill Gorcunov gorcunov at openvz.org
Thu Jun 4 14:04:02 PDT 2015


Here we simply build piegen tool which gonna be used
to generate parasite code safe to rellocate. The tool
is taking object file as an argument, parses it and
generates C file with rellocations encoded in form
suitable for fast appliance.

Currently only x86-32 x86-64 is supported.

v2 (by ldufour@):
 - Filter PIEGEN

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 Makefile                |  19 ++-
 pie/piegen/Makefile     |  14 ++
 pie/piegen/elf-x86-32.c |  16 +++
 pie/piegen/elf-x86-64.c |  16 +++
 pie/piegen/elf.c        | 338 ++++++++++++++++++++++++++++++++++++++++++++++++
 pie/piegen/main.c       | 127 ++++++++++++++++++
 pie/piegen/piegen.h     |  34 +++++
 7 files changed, 562 insertions(+), 2 deletions(-)
 create mode 100644 pie/piegen/Makefile
 create mode 100644 pie/piegen/elf-x86-32.c
 create mode 100644 pie/piegen/elf-x86-64.c
 create mode 100644 pie/piegen/elf.c
 create mode 100644 pie/piegen/main.c
 create mode 100644 pie/piegen/piegen.h

diff --git a/Makefile b/Makefile
index 099e692e3204..36fea8d666de 100644
--- a/Makefile
+++ b/Makefile
@@ -142,6 +142,9 @@ ARCH-LIB	:= $(ARCH_DIR)/crtools.built-in.o
 CRIU-SO		:= libcriu
 CRIU-LIB	:= lib/$(CRIU-SO).so
 CRIU-INC	:= lib/criu.h include/criu-plugin.h include/criu-log.h protobuf/rpc.proto
+ifneq ($(filter i386 ia32 x86_64, $(ARCH)),)
+PIEGEN		:= pie/piegen/piegen
+endif
 
 export CC MAKE CFLAGS LIBS SRCARCH DEFINES MAKEFLAGS CRIU-SO
 export SRC_DIR SYSCALL-LIB SH RM ARCH_DIR OBJCOPY LDARCH LD
@@ -184,9 +187,20 @@ $(ARCH_DIR)/%:: protobuf config
 $(ARCH_DIR): protobuf config
 	$(Q) $(MAKE) $(build)=$(ARCH_DIR) all
 
-pie/%:: $(ARCH_DIR)
+ifneq ($(filter i386 ia32 x86_64, $(ARCH)),)
+pie/piegen/%:
+	$(Q) $(MAKE) $(build)=pie/piegen $@
+pie/piegen:
+	$(Q) $(MAKE) $(build)=pie/piegen all
+$(PIEGEN): pie/piegen/built-in.o
+	$(E) "  LINK    " $@
+	$(Q) $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
+.PHONY: pie/piegen
+endif
+
+pie/%:: $(ARCH_DIR) $(PIEGEN)
 	$(Q) $(MAKE) $(build)=pie $@
-pie: $(ARCH_DIR)
+pie: $(ARCH_DIR) $(PIEGEN)
 	$(Q) $(MAKE) $(build)=pie all
 
 %.o %.i %.s %.d: $(VERSION_HEADER) pie
@@ -235,6 +249,7 @@ clean-built:
 	$(Q) $(RM) $(VERSION_HEADER)
 	$(Q) $(MAKE) $(build)=$(ARCH_DIR) clean
 	$(Q) $(MAKE) $(build)=protobuf clean
+	$(Q) $(MAKE) $(build)=pie/piegen clean
 	$(Q) $(MAKE) $(build)=pie clean
 	$(Q) $(MAKE) $(build)=lib clean
 	$(Q) $(MAKE) $(build-crtools)=. clean
diff --git a/pie/piegen/Makefile b/pie/piegen/Makefile
new file mode 100644
index 000000000000..dd54c3f0b546
--- /dev/null
+++ b/pie/piegen/Makefile
@@ -0,0 +1,14 @@
+CFLAGS += -iquote pie/piegen
+
+obj-y += main.o
+ifneq ($(filter i386 ia32 x86_64, $(ARCH)),)
+obj-y += elf-x86-32.o
+obj-y += elf-x86-64.o
+endif
+
+cleanup-y += $(obj)/piegen
+cleanup-y += $(obj)/*.o
+
+ifneq ($(MAKECMDGOALS),clean)
+incdeps := y
+endif
diff --git a/pie/piegen/elf-x86-32.c b/pie/piegen/elf-x86-32.c
new file mode 100644
index 000000000000..413113ef396b
--- /dev/null
+++ b/pie/piegen/elf-x86-32.c
@@ -0,0 +1,16 @@
+#define ELF_X86_32
+#define handle_elf	handle_elf_x86_32
+
+#define Ehdr_t		Elf32_Ehdr
+#define Shdr_t		Elf32_Shdr
+#define Sym_t		Elf32_Sym
+#define Rel_t		Elf32_Rel
+#define Rela_t		Elf32_Rela
+
+#define ELF_ST_TYPE	ELF32_ST_TYPE
+#define ELF_ST_BIND	ELF32_ST_BIND
+
+#define ELF_R_SYM	ELF32_R_SYM
+#define ELF_R_TYPE	ELF32_R_TYPE
+
+#include "elf.c"
diff --git a/pie/piegen/elf-x86-64.c b/pie/piegen/elf-x86-64.c
new file mode 100644
index 000000000000..8ba26672bc82
--- /dev/null
+++ b/pie/piegen/elf-x86-64.c
@@ -0,0 +1,16 @@
+#define ELF_X86_64
+#define handle_elf	handle_elf_x86_64
+
+#define Ehdr_t		Elf64_Ehdr
+#define Shdr_t		Elf64_Shdr
+#define Sym_t		Elf64_Sym
+#define Rel_t		Elf64_Rel
+#define Rela_t		Elf64_Rela
+
+#define ELF_ST_TYPE	ELF64_ST_TYPE
+#define ELF_ST_BIND	ELF64_ST_BIND
+
+#define ELF_R_SYM	ELF64_R_SYM
+#define ELF_R_TYPE	ELF64_R_TYPE
+
+#include "elf.c"
diff --git a/pie/piegen/elf.c b/pie/piegen/elf.c
new file mode 100644
index 000000000000..5812c4ca351f
--- /dev/null
+++ b/pie/piegen/elf.c
@@ -0,0 +1,338 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <elf.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "asm-generic/int.h"
+
+#include "compiler.h"
+#include "piegen.h"
+
+static bool __ptr_oob(const void *ptr, const void *start, const size_t size)
+{
+	const void *end = (const void *)((const unsigned long)start + size);
+	return ptr > end || ptr < start;
+}
+
+static bool test_pointer(const void *ptr, const void *start, const size_t size,
+			 const char *name, const char *file, const int line)
+{
+	if (__ptr_oob(ptr, start, size)) {
+		pr_err("Corrupted pointer %p (%s) at %s:%d\n",
+		       ptr, name, file, line);
+		return true;
+	}
+	return false;
+}
+
+#define ptr_func_exit(__ptr)						\
+	do {								\
+		if (test_pointer((__ptr), mem, size, #__ptr,		\
+				 __FILE__, __LINE__)) {			\
+			free(sec_hdrs);					\
+			return -1;					\
+		}							\
+	} while (0)
+
+int handle_elf(const piegen_opt_t *opts, void *mem, size_t size)
+{
+	const char *symstrings = NULL;
+	Shdr_t *symtab_hdr = NULL;
+	Sym_t *symbols = NULL;
+	Ehdr_t *hdr = mem;
+
+	Shdr_t *secstrings_hdr = NULL;
+	Shdr_t *strtab_hdr = NULL;
+	Shdr_t **sec_hdrs = NULL;
+	const char *secstrings;
+
+	size_t i, k, nr_gotpcrel = 0;
+
+	pr_debug("Header\n------------\n");
+	pr_debug("\ttype 0x%x machine 0x%x version 0x%x\n",
+		 (unsigned)hdr->e_type, (unsigned)hdr->e_machine, (unsigned)hdr->e_version);
+
+#ifdef ELF_X86_64
+	if (hdr->e_type != ET_REL || hdr->e_machine != EM_X86_64 || hdr->e_version != EV_CURRENT) {
+		pr_err("Unsupported header detected\n");
+		goto err;
+	}
+#endif
+
+#ifdef ELF_X86_32
+	if (hdr->e_type != ET_REL || hdr->e_machine != EM_386 || hdr->e_version != EV_CURRENT) {
+		pr_err("Unsupported header detected\n");
+		goto err;
+	}
+#endif
+
+	sec_hdrs = malloc(sizeof(*sec_hdrs) * hdr->e_shnum);
+	if (!sec_hdrs) {
+		pr_err("No memory for section headers\n");
+		goto err;
+	}
+
+	secstrings_hdr = mem + hdr->e_shoff + hdr->e_shentsize * hdr->e_shstrndx;
+	secstrings = mem + secstrings_hdr->sh_offset;
+	ptr_func_exit(secstrings_hdr);
+	ptr_func_exit(secstrings);
+
+	pr_debug("Sections\n------------\n");
+	for (i = 0; i < hdr->e_shnum; i++) {
+		Shdr_t *sh = mem + hdr->e_shoff + hdr->e_shentsize * i;
+		ptr_func_exit(sh);
+
+		if (sh->sh_type == SHT_SYMTAB)
+			symtab_hdr = sh;
+
+		ptr_func_exit(&secstrings[sh->sh_name]);
+		pr_debug("\t index %-2zd type 0x%-2x name %s\n", i,
+			 (unsigned)sh->sh_type, &secstrings[sh->sh_name]);
+
+		sec_hdrs[i] = sh;
+	}
+
+	if (!symtab_hdr) {
+		pr_err("No symbol table present\n");
+		goto err;
+	}
+
+	if (!symtab_hdr->sh_link || symtab_hdr->sh_link >= hdr->e_shnum) {
+		pr_err("Corrupted symtab header\n");
+		goto err;
+	}
+
+	pr_debug("Symbols\n------------\n");
+	strtab_hdr = sec_hdrs[symtab_hdr->sh_link];
+	ptr_func_exit(strtab_hdr);
+
+	symbols = mem + symtab_hdr->sh_offset;
+	ptr_func_exit(symbols);
+	symstrings = mem + strtab_hdr->sh_offset;
+	ptr_func_exit(symstrings);
+
+	if (sizeof(*symbols) != symtab_hdr->sh_entsize) {
+		pr_err("Symbol table align differ\n");
+		goto err;
+	}
+
+	pr_out("/* Autogenerated from %s */\n", opts->input_filename);
+	for (i = 0; i < symtab_hdr->sh_size / symtab_hdr->sh_entsize; i++) {
+		Sym_t *sym = &symbols[i];
+		const char *name;
+		Shdr_t *sh_src;
+
+		ptr_func_exit(sym);
+		name = &symstrings[sym->st_name];
+		ptr_func_exit(name);
+
+		if (*name) {
+			pr_debug("\ttype 0x%-2x bind 0x%-2x shndx 0x%-4x value 0x%-2lx name %s\n",
+				 (unsigned)ELF_ST_TYPE(sym->st_info), (unsigned)ELF_ST_BIND(sym->st_info),
+				 (unsigned)sym->st_shndx, (unsigned long)sym->st_value, name);
+			if (strncmp(name, "__export", 8))
+				continue;
+			if (sym->st_shndx && sym->st_shndx < hdr->e_shnum) {
+				sh_src = sec_hdrs[sym->st_shndx];
+				ptr_func_exit(sh_src);
+#if 0
+				if (ELF_ST_TYPE(sym->st_info) == STT_FUNC ||
+				    ELF_ST_TYPE(sym->st_info) == STT_OBJECT)
+#endif
+					pr_out("#define %s%s 0x%lx\n",
+					       opts->prefix_name, name,
+					       (unsigned long)(sym->st_value + sh_src->sh_offset));
+			}
+		}
+	}
+
+	pr_out("typedef struct {\n"
+	       "	unsigned int	offset;\n"
+	       "	unsigned int	type;\n"
+	       "	long		addend;\n"
+	       "	long		value;\n"
+	       "} %s;\nstatic __maybe_unused %s %s[] = {\n",
+	       opts->type_name, opts->type_name, opts->var_name);
+
+	pr_debug("Relocations\n------------\n");
+	for (i = 0; i < hdr->e_shnum; i++) {
+		Shdr_t *sh = sec_hdrs[i];
+		Shdr_t *sh_rel;
+
+		if (sh->sh_type != SHT_REL && sh->sh_type != SHT_RELA)
+			continue;
+
+		sh_rel = sec_hdrs[sh->sh_info];
+		ptr_func_exit(sh_rel);
+
+		pr_debug("\tsection %2zd type 0x%-2x link 0x%-2x info 0x%-2x name %s\n", i,
+			 (unsigned)sh->sh_type, (unsigned)sh->sh_link,
+			 (unsigned)sh->sh_info, &secstrings[sh->sh_name]);
+
+		for (k = 0; k < sh->sh_size / sh->sh_entsize; k++) {
+			s64 __maybe_unused addend64, __maybe_unused value64;
+			s32 addend32, value32;
+			unsigned long place;
+			const char *name;
+			Shdr_t *sh_src;
+			void *where;
+			Sym_t *sym;
+
+			union {
+				Rel_t rel;
+				Rela_t rela;
+			} *r = mem + sh->sh_offset + sh->sh_entsize * k;
+			ptr_func_exit(r);
+
+			sym = &symbols[ELF_R_SYM(r->rel.r_info)];
+			ptr_func_exit(sym);
+
+			name = &symstrings[sym->st_name];
+			ptr_func_exit(name);
+
+			where = mem + sh_rel->sh_offset + r->rel.r_offset;
+			ptr_func_exit(where);
+
+			sh_src = sec_hdrs[sym->st_shndx];
+			ptr_func_exit(sh_src);
+
+			pr_debug("\t\tr_offset 0x%-4lx r_info 0x%-4lx / sym 0x%-2lx type 0x%-2lx symsecoff 0x%-4lx\n",
+				 (unsigned long)r->rel.r_offset, (unsigned long)r->rel.r_info,
+				 (unsigned long)ELF_R_SYM(r->rel.r_info),
+				 (unsigned long)ELF_R_TYPE(r->rel.r_info),
+				 (unsigned long)sh_src->sh_offset);
+
+			if (sym->st_shndx == SHN_UNDEF)
+				continue;
+
+			ptr_func_exit((mem + sh_rel->sh_offset + r->rel.r_offset));
+			if (sh->sh_type == SHT_REL) {
+				addend32 = *(s32 *)where;
+				addend64 = *(s64 *)where;
+			} else {
+				addend32 = (s32)r->rela.r_addend;
+				addend64 = (s64)r->rela.r_addend;
+			}
+
+			place = where - mem;
+
+			pr_debug("\t\t\tvalue 0x%-8lx addend32 %-4d addend64 %-8ld symname %s\n",
+				 (unsigned long)sym->st_value, addend32, (long)addend64, name);
+
+			value32 = (s32)sh_src->sh_offset + (s32)sym->st_value;
+			value64 = (s64)sh_src->sh_offset + (s64)sym->st_value;
+
+			switch (ELF_R_TYPE(r->rel.r_info)) {
+#ifdef ELF_X86_64
+			case R_X86_64_32: /* Symbol + Addend (4 bytes) */
+				pr_debug("\t\t\t\tR_X86_64_32   at 0x%-4lx val 0x%x\n", place, value32);
+				pr_out("	{ .offset = 0x%-8x, .type = 0, "
+				       ".addend = 0       , .value = 0x%-16x, }, /* R_X86_64_32 */\n",
+				       (unsigned int)place, value32 + addend32);
+				break;
+			case R_X86_64_64: /* Symbol + Addend (8 bytes) */
+				pr_debug("\t\t\t\tR_X86_64_64   at 0x%-4lx val 0x%lx\n", place, value64);
+				pr_out("	{ .offset = 0x%-8x, .type = 1, "
+				       ".addend = 0       , .value = 0x%-16lx, }, /* R_X86_64_64 */\n",
+				       (unsigned int)place, (long)(value64 + addend64));
+				break;
+			case R_X86_64_PC32: /* Symbol + Addend - Place (4 bytes) */
+				pr_debug("\t\t\t\tR_386_PC32 at 0x%-4lx val 0x%x\n", place, value32 + addend32 - (s32)place);
+				/*
+				 * R_X86_64_PC32 are relative, patch them inplace.
+				 */
+				*((s32 *)where) = value32 + addend32 - place;
+				break;
+			case R_X86_64_PLT32: /* ProcLinkage + Addend - Place (4 bytes) */
+				pr_debug("\t\t\t\tR_386_PLT32 at 0x%-4lx val 0x%x\n", place, value32 + addend32 - (s32)place);
+				/*
+				 * R_X86_64_PLT32 are relative, patch them inplace.
+				 */
+				*((s32 *)where) = value32 + addend32 - place;
+				break;
+			case R_X86_64_GOTPCREL: /* SymbolOffsetInGot + GOT + Addend - Place  (4 bytes) */
+				pr_debug("\t\t\t\tR_X86_64_GOTPCREL at 0x%-4lx val 0x%x\n", place, value32);
+				pr_out("	{ .offset = 0x%-8x, .type = 3, "
+				       ".addend = %-8d, .value = 0x%-16x, }, /* R_X86_64_GOTPCREL */\n",
+				       (unsigned int)place, addend32, value32);
+				nr_gotpcrel++;
+				break;
+#endif
+#ifdef ELF_X86_32
+			case R_386_32: /* Symbol + Addend */
+				pr_debug("\t\t\t\tR_386_32   at 0x%-4lx val 0x%x\n", place, value32 + addend32);
+				pr_out("	{ .offset = 0x%-8x, .type = 0, "
+				       ".addend = %-4d, .value = 0x%x, },\n",
+				       (unsigned int)place, addend32, value32);
+				break;
+			case R_386_PC32: /* Symbol + Addend - Place */
+				pr_debug("\t\t\t\tR_386_PC32 at 0x%-4lx val 0x%x\n", place, value32 + addend32 - (s32)place);
+				/*
+				 * R_386_PC32 are relative, patch them inplace.
+				 */
+				*((s32 *)where) = value32 + addend32 - place;
+				break;
+#endif
+			default:
+				pr_err("Unsupported relocation\n");
+				goto err;
+			}
+		}
+	}
+	pr_out("};\n");
+	pr_out("static __maybe_unused size_t %s = %zd;\n", opts->nrgotpcrel_name, nr_gotpcrel);
+
+	pr_out("static __maybe_unused const char %s[] = {\n\t", opts->stream_name);
+	for (i = 0; i < ALIGN(size, 8); i++) {
+		if (i && (i % 8) == 0)
+			pr_out("\n\t");
+		if (i < size)
+			pr_out("0x%02x,", ((unsigned char *)mem)[i]);
+		else
+			pr_out("0x00,");
+	}
+	pr_out("};\n");
+
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_32)
+pr_out(
+"static __maybe_unused void elf_apply_relocs(void *mem, size_t size, %s *elf_relocs, size_t nr_relocs)\n"
+"{\n"
+"	size_t i, j;\n"
+"\n"
+"	for (i = 0, j = 0; i < ARRAY_SIZE(elf_relocs); i++) {\n"
+"		if (elf_relocs[i].type) {\n"
+"			long *where = mem + elf_relocs[i].offset;\n"
+"			long *p = mem + size;\n"
+"\n"
+"			if (elf_relocs[i].type & 2) {\n"
+"				int *value = (int *)where;\n"
+"				int rel;\n"
+"\n"
+"				p[j] = (long)mem + elf_relocs[i].value;\n"
+"				rel = (unsigned)((void *)&p[j] - (void *)mem) - elf_relocs[i].offset - elf_relocs[i].addend;\n"
+"\n"
+"				*value = rel;\n"
+"				j++;\n"
+"			} else\n"
+"				*where = elf_relocs[i].value + elf_relocs[i].addend + (unsigned long)mem;\n"
+"		} else {\n"
+"			int *where = (mem + elf_relocs[i].offset);\n"
+"			*where = elf_relocs[i].value + elf_relocs[i].addend + (unsigned long)mem;\n"
+"		}\n"
+"	}\n"
+"}\n", opts->type_name);
+#endif
+
+err:
+	free(sec_hdrs);
+	return -1;
+}
diff --git a/pie/piegen/main.c b/pie/piegen/main.c
new file mode 100644
index 000000000000..45bbf24545a0
--- /dev/null
+++ b/pie/piegen/main.c
@@ -0,0 +1,127 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <elf.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "compiler.h"
+#include "config.h"
+#include "piegen.h"
+
+piegen_opt_t opts = {
+	.input_filename		= "file.o",
+	.stream_name		= "stream",
+	.type_name		= "elf_reloc_t",
+	.prefix_name		= "__",
+	.var_name		= "elf_relocs",
+	.nrgotpcrel_name	= "nr_gotpcrel",
+};
+
+static int handle_elf(const piegen_opt_t *opts, void *mem, size_t size)
+{
+#if defined(CONFIG_X86_32) || defined(CONFIG_X86_64)
+	unsigned char elf_ident_x86_32[EI_NIDENT] = {
+		0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	};
+
+	unsigned char elf_ident_x86_64[EI_NIDENT] = {
+		0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	};
+
+	if (memcmp(mem, elf_ident_x86_32, sizeof(elf_ident_x86_32)) == 0)
+		return handle_elf_x86_32(opts, mem, size);
+	else if (memcmp(mem, elf_ident_x86_64, sizeof(elf_ident_x86_64)) == 0)
+		return handle_elf_x86_64(opts, mem, size);
+#endif
+
+	pr_err("Unsupported Elf format detected\n");
+	return -1;
+}
+
+/*
+ * That;s the tool to generate patches object files.
+ */
+int main(int argc, char *argv[])
+{
+	struct stat st;
+	int opt, idx;
+	void *mem;
+	int fd;
+
+	static const char short_opts[] = "f:s:t:p:v:h";
+	static struct option long_opts[] = {
+		{ "file",	required_argument,	0, 'f' },
+		{ "stream",	required_argument,	0, 's' },
+		{ "type",	required_argument,	0, 't' },
+		{ "sym-prefix",	required_argument,	0, 'p' },
+		{ "variable",	required_argument,	0, 'v' },
+		{ "help",	required_argument,	0, 'h' },
+		{ },
+	};
+
+	if (argc < 3)
+		goto usage;
+
+	while (1) {
+		idx = -1;
+		opt = getopt_long(argc, argv, short_opts, long_opts, &idx);
+		if (opt == -1)
+			break;
+		switch (opt) {
+		case 'f':
+			opts.input_filename = optarg;
+			break;
+		case 's':
+			opts.stream_name = optarg;
+			break;
+		case 'p':
+			opts.prefix_name = optarg;
+			break;
+		case 't':
+			opts.type_name = optarg;
+			break;
+		case 'v':
+			opts.var_name = optarg;
+			break;
+		case 'h':
+		default:
+			goto usage;
+		}
+	}
+
+	fd = open(opts.input_filename, O_RDONLY);
+	if (fd < 0) {
+		pr_perror("Can't open file %s", opts.input_filename);
+		goto err;
+	}
+
+	if (fstat(fd, &st)) {
+		pr_perror("Can't stat file %s", opts.input_filename);
+		goto err;
+	}
+
+	mem = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);
+	if (mem == MAP_FAILED) {
+		pr_perror("Can't mmap file %s", opts.input_filename);
+		goto err;
+	}
+
+	if (handle_elf(&opts, mem, st.st_size))
+		goto err;
+	return 1;
+usage:
+	printf("Usage: %s -f filename\n", argv[0]);
+err:
+	return 0;
+}
diff --git a/pie/piegen/piegen.h b/pie/piegen/piegen.h
new file mode 100644
index 000000000000..10505d758125
--- /dev/null
+++ b/pie/piegen/piegen.h
@@ -0,0 +1,34 @@
+#ifndef __ELFTIL_H__
+#define __ELFTIL_H__
+
+#include <stdio.h>
+#include <unistd.h>
+
+typedef struct {
+	char		*input_filename;
+	char		*stream_name;
+	char		*type_name;
+	char		*prefix_name;
+	char		*var_name;
+	char		*nrgotpcrel_name;
+} piegen_opt_t;
+
+extern piegen_opt_t opts;
+
+#if defined(CONFIG_X86_32) || defined(CONFIG_X86_64)
+extern int handle_elf_x86_32(const piegen_opt_t *opts, void *mem, size_t size);
+extern int handle_elf_x86_64(const piegen_opt_t *opts, void *mem, size_t size);
+#endif
+
+#define pr_out(fmt, ...)	fprintf(stdout, fmt, ##__VA_ARGS__)
+
+#if 0
+# define pr_debug(fmt, ...)	fprintf(stderr, fmt, ##__VA_ARGS__)
+#else
+# define pr_debug(fmt, ...)
+#endif
+
+#define pr_err(fmt, ...)	fprintf(stderr, "Error (%s:%d): "fmt, __FILE__, __LINE__, ##__VA_ARGS__)
+#define pr_perror(fmt, ...)	fprintf(stderr, "Error (%s:%d): "fmt "%m\n", __FILE__, __LINE__, ##__VA_ARGS__)
+
+#endif /* __ELFTIL_H__ */
-- 
2.4.2



More information about the CRIU mailing list