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

Laurent Dufour ldufour at linux.vnet.ibm.com
Tue May 19 04:18:23 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,");
> +	}

Hi Cyrill,

Here you are copying all the blob's file to get loaded at runtime. But,
only ELF sections flagged "PROGBITS" should be copied in memory at
runtime, and so in the output stream (there is no need to load
relocation sections, symbol tables, etc).

There is a major side effect: the offset of the loaded section is
changed due to interleaved section ignored. So this should be handle
earlier, to have correct section's offset.

Cheers,
Laurent.

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



More information about the CRIU mailing list