[CRIU] [PATCH 1/8] piegen: Implement tool building, v2

Laurent Dufour ldufour at linux.vnet.ibm.com
Wed May 13 00:22:05 PDT 2015


On 11/05/2015 18:06, Cyrill Gorcunov wrote:
> 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 dbbbbf2a7da5..78cc761c5dca 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

Hi Cyrill,

Instead of embedding the processing C code in C code, why not creating
that C file and managed it under Git, and just generate the C file
containing the data to be processed which will be built and linked with
the one stored in Git?

I found that difficult to maintain when I tried to write the ppc64 part.

Cheers,
Laurent.

> +
> +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__ */
> 



More information about the CRIU mailing list