[CRIU] [PATCH 09/10] compel: Initial commit
Dmitry Safonov
dsafonov at virtuozzo.com
Wed Mar 23 03:55:24 PDT 2016
On 03/22/2016 10:15 PM, Cyrill Gorcunov wrote:
> 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).
>
> Here we simply shuffle old piegen code around adding support for
> flags fetching via compel executable directly.
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
Looks-good-to-me: Dmitry Safonov <dsafonov at virtuozzo.com>
> ---
> Makefile | 11 +-
> Makefile.versions | 4 +
> compel/Makefile | 33 +++++
> {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 | 19 +--
> criu/pie/Makefile | 12 +-
> criu/pie/pie-relocs.c | 2 +-
> criu/pie/pie-relocs.h | 2 +-
> criu/pie/piegen/Makefile | 17 ---
> 17 files changed, 188 insertions(+), 97 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 32fb75d6549d..24033e7c2c33 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,11 +136,12 @@ lib: criu
> $(Q) $(MAKE) -C lib all
> .PHONY: lib
>
> -all: criu lib
> +all: compel criu lib
> .PHONY: all
>
> clean-built:
> $(Q) $(MAKE) $(build)=images clean
> + $(Q) $(MAKE) $(build)=compel clean
> $(Q) $(MAKE) -C criu clean
> $(Q) $(MAKE) -C lib clean
> $(Q) $(MAKE) -C Documentation 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..6bcb825f9e2c
> --- /dev/null
> +++ b/compel/Makefile
> @@ -0,0 +1,33 @@
> +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.
> +lib-name := lib/compel.a
> +lib-y += lib/compel.o
> +
> +COMPEL_SO := libcompel.so
> +cflags-so += $(CFLAGS) -rdynamic -Wl,-soname,$(COMPEL_SO).$(COMPEL_SO_VERSION_MAJOR)
> +$(obj)/$(COMPEL_SO): $(obj)/$(lib-name)
> + $(call msg-link, $@)
> + $(Q) $(CC) -shared $(cflags-so) -o $@ $^ $(ldflags-so) $(LDFLAGS)
> +all-y += $(obj)/$(COMPEL_SO)
> +cleanup-y += $(obj)/$(COMPEL_SO)
> 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 25d75dfd7d3e..4a9464d4dcaf 100644
> --- a/criu/Makefile
> +++ b/criu/Makefile
> @@ -142,33 +142,22 @@ 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
>
> #
> # CRIU executable
> -PROGRAM-BUILTINS += ../images/built-in.o
> +PROGRAM-BUILTINS += $(SRC_DIR)/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,11 +172,9 @@ clean:
> $(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) ./*.{gcda,gcno,gcov}
> $(Q) $(RM) ./pie/*.{gcda,gcno,gcov}
> - $(Q) $(RM) ./pie/piegen/*.{gcda,gcno,gcov}
> $(Q) $(RM) -r ./gcov
> $(Q) $(RM) $(VERSION_HEADER)
> $(Q) $(RM) $(CONFIG_HEADER)
> diff --git a/criu/pie/Makefile b/criu/pie/Makefile
> index b455a02a6331..04836d999536 100644
> --- a/criu/pie/Makefile
> +++ b/criu/pie/Makefile
> @@ -15,13 +15,9 @@ 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
> -endif
> +ccflags-y += -DCR_NOGLIBC $(shell $(SRC_DIR)/compel/compel --arch=$(ARCH) cflags)
>
> ifeq ($(SRCARCH),arm)
> ccflags-y += -marm
> @@ -68,9 +64,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 5c3d68b84817..000000000000
> --- a/criu/pie/piegen/Makefile
> +++ /dev/null
> @@ -1,17 +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)
> -incdeps := y
> -endif
--
Regards,
Dmitry Safonov
More information about the CRIU
mailing list