[CRIU] [PATCH 10/10] compel: Initial commit

Cyrill Gorcunov gorcunov at openvz.org
Thu Mar 24 11:25:42 PDT 2016


The compel component is a replacement for several aspects of CRIU
functionality: binary blobs generation for PIE parasite/restore code,
and a library for parasite code injection and execution (to be implemented).

In this patch we move "piegen" functionality into compel executable
which is enough to build CRIU, but in future we gonna ship compel
executable as am own tool together with CRIU so we will have to
separate "piegen" mode used during CRIU building procedure and
one shipped with executable. That said I probably need to make
some symlinks for hostprog-y.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 Makefile                                         |  11 +-
 Makefile.versions                                |   4 +
 compel/Makefile                                  |  30 ++++
 {criu/pie/piegen => compel/include}/piegen.h     |   1 +
 compel/include/uapi/libcompel.h                  |   4 +
 {criu/pie/piegen => compel/include}/uapi/types.h |   0
 compel/lib/compel.c                              |   0
 {criu/pie/piegen => compel/src}/elf-ppc64.c      |   0
 {criu/pie/piegen => compel/src}/elf-x86-32.c     |   0
 {criu/pie/piegen => compel/src}/elf-x86-64.c     |   0
 {criu/pie/piegen => compel/src}/elf.c            |   2 +-
 {criu/pie/piegen => compel/src}/main.c           | 178 ++++++++++++++++-------
 criu/Makefile                                    |  18 +--
 criu/pie/Makefile                                |  13 +-
 criu/pie/pie-relocs.c                            |   2 +-
 criu/pie/pie-relocs.h                            |   2 +-
 criu/pie/piegen/Makefile                         |  19 ---
 17 files changed, 186 insertions(+), 98 deletions(-)
 create mode 100644 compel/Makefile
 rename {criu/pie/piegen => compel/include}/piegen.h (98%)
 create mode 100644 compel/include/uapi/libcompel.h
 rename {criu/pie/piegen => compel/include}/uapi/types.h (100%)
 create mode 100644 compel/lib/compel.c
 rename {criu/pie/piegen => compel/src}/elf-ppc64.c (100%)
 rename {criu/pie/piegen => compel/src}/elf-x86-32.c (100%)
 rename {criu/pie/piegen => compel/src}/elf-x86-64.c (100%)
 rename {criu/pie/piegen => compel/src}/elf.c (99%)
 rename {criu/pie/piegen => compel/src}/main.c (57%)
 delete mode 100644 criu/pie/piegen/Makefile

diff --git a/Makefile b/Makefile
index 1d5f37160c48..39cd80ea01f5 100644
--- a/Makefile
+++ b/Makefile
@@ -109,6 +109,10 @@ CFLAGS			+= $(WARNINGS) $(DEFINES)
 $(eval $(call gen-built-in,images))
 
 #
+# Compel get used by CRIU, build it earlier
+$(eval $(call gen-built-in,compel))
+
+#
 # CRIU building done in own directory
 # with slightly different rules so we
 # can't use nmk engine directly (we
@@ -116,9 +120,9 @@ $(eval $(call gen-built-in,images))
 #
 # But note that we're already included
 # the nmk so we can reuse it there.
-criu/%: images/built-in.o
+criu/%: images/built-in.o compel/compel
 	$(Q) $(MAKE) -C criu $@
-criu: images/built-in.o
+criu: images/built-in.o compel/compel
 	$(Q) $(MAKE) -C criu all
 .PHONY: criu
 
@@ -132,7 +136,7 @@ lib: criu
 	$(Q) $(MAKE) -C lib all
 .PHONY: lib
 
-all: criu lib
+all: compel criu lib
 .PHONY: all
 
 subclean:
@@ -144,6 +148,7 @@ subclean:
 
 clean: subclean
 	$(Q) $(MAKE) $(build)=images $@
+	$(Q) $(MAKE) $(build)=compel $@
 	$(Q) $(MAKE) -C criu $@
 .PHONY: clean
 
diff --git a/Makefile.versions b/Makefile.versions
index 1c66439bd805..6980320751c5 100644
--- a/Makefile.versions
+++ b/Makefile.versions
@@ -17,3 +17,7 @@ CRIU_SO_VERSION_MINOR	:= 0
 
 export CRIU_SO_VERSION_MAJOR CRIU_SO_VERSION_MINOR
 
+COMPEL_SO_VERSION_MAJOR	:= 1
+COMPEL_SO_VERSION_MINOR	:= 0
+
+export COMPEL_SO_VERSION_MAJOR COMPEL_SO_VERSION_MINOR
diff --git a/compel/Makefile b/compel/Makefile
new file mode 100644
index 000000000000..a8f19ddea8fd
--- /dev/null
+++ b/compel/Makefile
@@ -0,0 +1,30 @@
+include $(SRC_DIR)/Makefile.versions
+
+ccflags-y	+= -iquote criu/include
+ccflags-y	+= -iquote compel/include
+ccflags-y	+= -DCOMPEL_VERSION=\"$(COMPEL_SO_VERSION_MAJOR).$(COMPEL_SO_VERSION_MINOR)\"
+
+host-ccflags-y	+= $(ccflags-y)
+HOSTCFLAGS	+= $(WARNINGS) $(DEFINES)
+HOSTLDFLAGS	+= $(LDFLAGS)
+
+hostprogs-y	+= compel
+compel-objs	+= src/main.o
+
+ifneq ($(filter ia32 x86, $(ARCH)),)
+compel-objs	+= src/elf-x86-32.o
+compel-objs	+= src/elf-x86-64.o
+endif
+ifeq ($(SRCARCH),ppc64)
+compel-objs	+= src/elf-ppc64.o
+endif
+
+#
+# Compel library for usage inside CRIU.
+lib-name	:= lib/compel.a
+lib-y		+= lib/compel.o
+
+# Compel library for exporting as dynamic.
+libso-y		:= libcompel
+libcompel-objs	+= lib/compel.a
+ldflags-so	:= $(CFLAGS) -rdynamic -Wl,-soname,libcompel.so.$(COMPEL_SO_VERSION_MAJOR)
diff --git a/criu/pie/piegen/piegen.h b/compel/include/piegen.h
similarity index 98%
rename from criu/pie/piegen/piegen.h
rename to compel/include/piegen.h
index 8ac5b34b43c2..0c695c6a7b48 100644
--- a/criu/pie/piegen/piegen.h
+++ b/compel/include/piegen.h
@@ -7,6 +7,7 @@
 typedef struct {
 	char		*input_filename;
 	char		*output_filename;
+	char		*uapi_dir;
 	char		*stream_name;
 	char		*prefix_name;
 	char		*var_name;
diff --git a/compel/include/uapi/libcompel.h b/compel/include/uapi/libcompel.h
new file mode 100644
index 000000000000..6eae570937f0
--- /dev/null
+++ b/compel/include/uapi/libcompel.h
@@ -0,0 +1,4 @@
+#ifndef __LIBCOMPEL_H__
+#define __LIBCOMPEL_H__
+
+#endif /* __LIBCOMPEL_H__ */
diff --git a/criu/pie/piegen/uapi/types.h b/compel/include/uapi/types.h
similarity index 100%
rename from criu/pie/piegen/uapi/types.h
rename to compel/include/uapi/types.h
diff --git a/compel/lib/compel.c b/compel/lib/compel.c
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/criu/pie/piegen/elf-ppc64.c b/compel/src/elf-ppc64.c
similarity index 100%
rename from criu/pie/piegen/elf-ppc64.c
rename to compel/src/elf-ppc64.c
diff --git a/criu/pie/piegen/elf-x86-32.c b/compel/src/elf-x86-32.c
similarity index 100%
rename from criu/pie/piegen/elf-x86-32.c
rename to compel/src/elf-x86-32.c
diff --git a/criu/pie/piegen/elf-x86-64.c b/compel/src/elf-x86-64.c
similarity index 100%
rename from criu/pie/piegen/elf-x86-64.c
rename to compel/src/elf-x86-64.c
diff --git a/criu/pie/piegen/elf.c b/compel/src/elf.c
similarity index 99%
rename from criu/pie/piegen/elf.c
rename to compel/src/elf.c
index c6b97257ba61..00f8c4926276 100644
--- a/criu/pie/piegen/elf.c
+++ b/compel/src/elf.c
@@ -158,7 +158,7 @@ int handle_elf(void *mem, size_t size)
 	}
 
 	pr_out("/* Autogenerated from %s */\n", opts.input_filename);
-	pr_out("#include \"piegen/uapi/types.h\"\n");
+	pr_out("#include \"%s/types.h\"\n", opts.uapi_dir);
 
 	for (i = 0; i < symtab_hdr->sh_size / symtab_hdr->sh_entsize; i++) {
 		Sym_t *sym = &symbols[i];
diff --git a/criu/pie/piegen/main.c b/compel/src/main.c
similarity index 57%
rename from criu/pie/piegen/main.c
rename to compel/src/main.c
index c89b1575fb61..5f1f058a2a67 100644
--- a/criu/pie/piegen/main.c
+++ b/compel/src/main.c
@@ -1,10 +1,11 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdbool.h>
+#include <fcntl.h>
 #include <unistd.h>
-#include <stdint.h>
-#include <getopt.h>
+#include <ctype.h>
 #include <string.h>
+#include <errno.h>
+#include <getopt.h>
 
 #include <fcntl.h>
 #include <elf.h>
@@ -14,19 +15,23 @@
 #include <sys/mman.h>
 
 #include "compiler.h"
-#include "config.h"
 #include "piegen.h"
 
+FILE *fout;
+
+static const char compel_cflags_pie[] = "-fpie -Wa,--noexecstack -fno-stack-protector";
+static const char compel_cflags_nopic[] = "-fno-pic -Wa,--noexecstack -fno-stack-protector";
+static const char compel_ldflags[] = "-r";
+
 piegen_opt_t opts = {
 	.input_filename		= NULL,
 	.stream_name		= "stream",
 	.prefix_name		= "__",
 	.var_name		= "elf_relocs",
 	.nrgotpcrel_name	= "nr_gotpcrel",
+	.uapi_dir		= "compel/uapi",
 };
 
-FILE *fout;
-
 static int handle_elf(void *mem, size_t size)
 {
 #if defined(CONFIG_X86_32) || defined(CONFIG_X86_64)
@@ -65,43 +70,120 @@ static int handle_elf(void *mem, size_t size)
 	return -1;
 }
 
-/*
- * That;s the tool to generate patches object files.
- */
-int main(int argc, char *argv[])
+static int piegen(void)
 {
 	struct stat st;
-	int opt, idx;
 	void *mem;
 	int fd;
 
-	static const char short_opts[] = "f:o:s:p:v:r:h";
+	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;
+	}
+
+	fout = fopen(opts.output_filename, "w");
+	if (fout == NULL) {
+		pr_perror("Can't open %s", opts.output_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(mem, st.st_size)) {
+		fclose(fout);
+		unlink(opts.output_filename);
+		goto err;
+	}
+
+err:
+	fclose(fout);
+	printf("%s generated successfully.\n", opts.output_filename);
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	const char *current_cflags = NULL;
+	int opt, idx, i;
+	char *action;
+
+	typedef struct {
+		const char	*arch;
+		const char	*cflags;
+	} compel_cflags_t;
+
+	static const compel_cflags_t compel_cflags[] = {
+		{
+			.arch	= "x86",
+			.cflags	= compel_cflags_pie,
+		}, {
+			.arch	= "ia32",
+			.cflags	= compel_cflags_nopic,
+		}, {
+			.arch	= "aarch64",
+			.cflags	= compel_cflags_pie,
+		}, {
+			.arch	= "arm",
+			.cflags	= compel_cflags_pie,
+		}, {
+			.arch	= "ppc64",
+			.cflags	= compel_cflags_pie,
+		},
+	};
+
+	const char short_opts[] = "f:o:s:p:v:r:a:u:Vh";
 	static struct option long_opts[] = {
-		{ "file",	required_argument,	0, 'f' },
-		{ "output",	required_argument,	0, 'o' },
-		{ "stream",	required_argument,	0, 's' },
-		{ "sym-prefix",	required_argument,	0, 'p' },
-		{ "variable",	required_argument,	0, 'v' },
-		{ "pcrelocs",	required_argument,	0, 'r' },
-		{ "help",	required_argument,	0, 'h' },
+		{ "arch",		required_argument,	0, 'a' },
+		{ "file",		required_argument,	0, 'f' },
+		{ "output",		required_argument,	0, 'o' },
+		{ "stream",		required_argument,	0, 's' },
+		{ "uapi-dir",		required_argument,	0, 'u' },
+		{ "sym-prefix",		required_argument,	0, 'p' },
+		{ "variable",		required_argument,	0, 'v' },
+		{ "pcrelocs",		required_argument,	0, 'r' },
+		{ "version",		no_argument,		0, 'V' },
+		{ "help",		no_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 'a':
+			for (i = 0; i < ARRAY_SIZE(compel_cflags); i++) {
+				if (!strcmp(optarg, compel_cflags[i].arch)) {
+					current_cflags = compel_cflags[i].cflags;
+					break;
+				}
+
+			}
+
+			if (!current_cflags)
+				goto usage;
+			break;
 		case 'f':
 			opts.input_filename = optarg;
 			break;
 		case 'o':
 			opts.output_filename = optarg;
 			break;
+		case 'u':
+			opts.uapi_dir = optarg;
+			break;
 		case 's':
 			opts.stream_name = optarg;
 			break;
@@ -114,48 +196,44 @@ int main(int argc, char *argv[])
 		case 'r':
 			opts.nrgotpcrel_name = optarg;
 			break;
+		case 'V':
+			printf("version %s\n", COMPEL_VERSION);
+			return 0;
 		case 'h':
-		default:
 			goto usage;
+		default:
+			break;
 		}
 	}
 
-	if (!opts.input_filename)
+	if (optind >= argc)
 		goto usage;
 
-	fd = open(opts.input_filename, O_RDONLY);
-	if (fd < 0) {
-		pr_perror("Can't open file %s", opts.input_filename);
-		goto err;
-	}
+	action = argv[optind++];
 
-	if (fstat(fd, &st)) {
-		pr_perror("Can't stat file %s", opts.input_filename);
-		goto err;
+	if (!strcmp(action, "cflags")) {
+		if (!current_cflags)
+			goto usage;
+		printf("%s", current_cflags);
+		return 0;
 	}
 
-	fout = fopen(opts.output_filename, "w");
-	if (fout == NULL) {
-		pr_perror("Can't open %s", opts.output_filename);
-		goto err;
+	if (!strcmp(action, "ldflags")) {
+		printf("%s", compel_ldflags);
+		return 0;
 	}
 
-	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 (!strcmp(action, "piegen")) {
+		if (!opts.input_filename)
+			goto usage;
 
-	if (handle_elf(mem, st.st_size)) {
-		fclose(fout);
-		unlink(opts.output_filename);
-		goto err;
+		return piegen();
 	}
-	fclose(fout);
-	printf("%s generated successfully.\n", opts.output_filename);
-	return 0;
+
 usage:
-	fprintf(stderr, "Usage: %s -f filename\n", argv[0]);
-err:
+	printf("Usage:\n");
+	printf("  compel --arch=(x86|ia32|aarch64|arm|ppc64) cflags\n");
+	printf("  compel --arch=(x86|ia32|aarch64|arm|ppc64) ldflags\n");
+	printf("  compel -f filename piegen\n");
 	return 1;
 }
diff --git a/criu/Makefile b/criu/Makefile
index 0380295a934d..d864313c06a7 100644
--- a/criu/Makefile
+++ b/criu/Makefile
@@ -144,25 +144,13 @@ arch_lib: syscalls_lib
 .PHONY: arch_lib
 
 #
-# piegen tool needed for PIE code.
-ifeq ($(piegen-y),y)
-piegen-bin		:= pie/piegen/piegen
-
-pie/piegen/%: config
-	$(Q) CC=$(HOSTCC) LD=$(HOSTLD) CFLAGS="$(ccflags-y) $(HOSTCFLAGS) $(WARNINGS) $(DEFINES)" $(MAKE) $(build)=pie/piegen $@
-$(piegen-bin): pie/piegen/built-in.o
-	$(call msg-link, $@)
-	$(Q) $(HOSTCC) $(HOSTCFLAGS) $^ $(LDFLAGS) -o $@
-endif
-
-#
 # PIE library code.
 pie/lib.a: arch_lib
 	$(Q) $(MAKE) $(call build-as,Makefile.library,pie) all
 
 #
 # PIE code blobs themseves.
-pie: $(piegen-bin) pie/lib.a
+pie: pie/lib.a
 	$(Q) $(MAKE) $(build)=pie all
 .PHONY: pie
 
@@ -171,6 +159,7 @@ pie: $(piegen-bin) pie/lib.a
 PROGRAM-BUILTINS	+= ../images/built-in.o
 PROGRAM-BUILTINS	+= built-in.o
 PROGRAM-BUILTINS	+= pie/lib.a
+PROGRAM-BUILTINS	+= $(SRC_DIR)/compel/lib/compel.a
 
 built-in.o: pie
 	$(Q) $(MAKE) $(call build-as,Makefile.crtools,.) all
@@ -183,7 +172,6 @@ criu: $(PROGRAM-BUILTINS)
 subclean:
 	$(Q) $(RM) ./*.{gcda,gcno,gcov}
 	$(Q) $(RM) ./pie/*.{gcda,gcno,gcov}
-	$(Q) $(RM) ./pie/piegen/*.{gcda,gcno,gcov}
 	$(Q) $(RM) -r ./gcov
 	$(Q) $(RM) criu
 .PHONY: subclean
@@ -194,7 +182,6 @@ clean: subclean
 	$(Q) $(MAKE) $(call build-as,Makefile.syscalls,$(ARCH_DIR)) $@
 	$(Q) $(MAKE) $(call build-as,Makefile.library,pie) $@
 	$(Q) $(MAKE) $(call build-as,Makefile.crtools,.) $@
-	$(Q) $(MAKE) $(build)=pie/piegen $@
 	$(Q) $(MAKE) $(build)=pie $@
 .PHONY: clean
 
@@ -204,7 +191,6 @@ mrproper: subclean
 	$(Q) $(MAKE) $(call build-as,Makefile.syscalls,$(ARCH_DIR)) $@
 	$(Q) $(MAKE) $(call build-as,Makefile.library,pie) $@
 	$(Q) $(MAKE) $(call build-as,Makefile.crtools,.) $@
-	$(Q) $(MAKE) $(build)=pie/piegen $@
 	$(Q) $(MAKE) $(build)=pie $@
 	$(Q) $(RM) $(VERSION_HEADER)
 	$(Q) $(RM) $(CONFIG_HEADER)
diff --git a/criu/pie/Makefile b/criu/pie/Makefile
index c125e8c40f90..e2f9e790f331 100644
--- a/criu/pie/Makefile
+++ b/criu/pie/Makefile
@@ -15,12 +15,11 @@ restorer-obj-e		+= ./$(ARCH_DIR)/syscalls.built-in.o
 # applications, which is not the target of the
 # project.
 #
-CFLAGS			:= $(filter-out -pg $(CFLAGS-GCOV),$(CFLAGS)) -iquote pie/piegen -iquote arch/$(ARCH)/include -iquote $(SRC_DIR) -iquote $(SRC_DIR)/criu/include
+CFLAGS			:= $(filter-out -pg $(CFLAGS-GCOV),$(CFLAGS)) -iquote $(SRC_DIR)/compel/include -iquote arch/$(ARCH)/include -iquote $(SRC_DIR) -iquote $(SRC_DIR)/criu/include
 
-ifneq ($(filter-out ia32,$(ARCH)),)
-        ccflags-y	+= -DCR_NOGLIBC -fpie -Wa,--noexecstack -fno-stack-protector
-else
-        ccflags-y	+= -DCR_NOGLIBC -fno-pic -Wa,--noexecstack -fno-stack-protector
+ccflags-y		+= -DCR_NOGLIBC
+ifneq ($(filter-out clean mrproper,$(MAKECMDGOALS)),)
+	ccflags-y	+= $(shell $(SRC_DIR)/compel/compel --arch=$(ARCH) cflags)
 endif
 
 ifeq ($(SRCARCH),arm)
@@ -68,9 +67,9 @@ $(obj)/%.built-in.bin.o: $(obj)/%.built-in.o $(obj)/lib.a $(obj)/$(PIELDS)
 	$(call msg-gen, $@)
 	$(Q) $(LD) -r -T $(obj)/$(PIELDS) -o $@ $< $(obj)/lib.a
 
-$(obj)/%-blob.h: $(obj)/%.built-in.bin.o $(obj)/$(PIELDS) pie/piegen
+$(obj)/%-blob.h: $(obj)/%.built-in.bin.o $(obj)/$(PIELDS) $(SRC_DIR)/compel/compel
 	$(call msg-gen, $@)
-	$(Q) pie/piegen/piegen -f $< -v $(call target-name,$@)_relocs -p $(call target-name,$@)_blob_offset__ -s $(call target-name,$@)_blob -o $@ $(piegen_stdout)
+	$(Q) $(SRC_DIR)/compel/compel piegen -f $< -v $(call target-name,$@)_relocs -p $(call target-name,$@)_blob_offset__ -s $(call target-name,$@)_blob -u $(SRC_DIR)/compel/include/uapi -o $@ $(piegen_stdout)
 
 else
 
diff --git a/criu/pie/pie-relocs.c b/criu/pie/pie-relocs.c
index 7e825b2320d9..72665e39621f 100644
--- a/criu/pie/pie-relocs.c
+++ b/criu/pie/pie-relocs.c
@@ -15,7 +15,7 @@
 #include "asm-generic/int.h"
 
 #include "compiler.h"
-#include "piegen/uapi/types.h"
+#include "compel/include/uapi/types.h"
 #include "bug.h"
 
 __maybe_unused void elf_relocs_apply(void *mem, void *vbase, size_t size, elf_reloc_t *elf_relocs, size_t nr_relocs)
diff --git a/criu/pie/pie-relocs.h b/criu/pie/pie-relocs.h
index 1449ca630908..bd313f8bfcba 100644
--- a/criu/pie/pie-relocs.h
+++ b/criu/pie/pie-relocs.h
@@ -1,7 +1,7 @@
 #ifndef __PIE_RELOCS_H__
 #define __PIE_RELOCS_H__
 
-#include "piegen/uapi/types.h"
+#include "compel/include/uapi/types.h"
 
 #include "compiler.h"
 #include "config.h"
diff --git a/criu/pie/piegen/Makefile b/criu/pie/piegen/Makefile
deleted file mode 100644
index 0af489070ba0..000000000000
--- a/criu/pie/piegen/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-CFLAGS += -iquote pie/piegen
-
-obj-y += main.o
-ifneq ($(filter ia32 x86, $(ARCH)),)
-obj-y += elf-x86-32.o
-obj-y += elf-x86-64.o
-endif
-ifeq ($(SRCARCH),ppc64)
-obj-y += elf-ppc64.o
-endif
-
-cleanup-y += $(obj)/piegen
-cleanup-y += $(obj)/*.o
-
-ifneq ($(MAKECMDGOALS),clean)
-ifneq ($(MAKECMDGOALS),mrproper)
-incdeps := y
-endif
-endif
-- 
2.5.5



More information about the CRIU mailing list