diff --git a/compel/arch/aarch64/plugins/std/parasite-head.S b/compel/arch/aarch64/plugins/std/parasite-head.S index 5e7067f6b..456c2117d 100644 --- a/compel/arch/aarch64/plugins/std/parasite-head.S +++ b/compel/arch/aarch64/plugins/std/parasite-head.S @@ -2,19 +2,6 @@ .section .head.text, "ax" ENTRY(__export_parasite_head_start) - adr x2, __export_parasite_head_start // get the address of this instruction - - ldr x0, __export_parasite_cmd - - ldr x1, parasite_args_ptr - add x1, x1, x2 // fixup __export_parasite_args - bl parasite_service brk #0 // the instruction BRK #0 generates the signal SIGTRAP in Linux - -parasite_args_ptr: - .quad __export_parasite_args - -__export_parasite_cmd: - .quad 0 END(__export_parasite_head_start) diff --git a/compel/arch/aarch64/scripts/compel-pack.lds.S b/compel/arch/aarch64/scripts/compel-pack.lds.S index eba89cd5f..57895ec9b 100644 --- a/compel/arch/aarch64/scripts/compel-pack.lds.S +++ b/compel/arch/aarch64/scripts/compel-pack.lds.S @@ -29,8 +29,4 @@ SECTIONS *(.eh_frame*) *(*) } - -/* Parasite args should have 4 bytes align, as we have futex inside. */ -. = ALIGN(4); -__export_parasite_args = .; } diff --git a/compel/arch/arm/plugins/std/parasite-head.S b/compel/arch/arm/plugins/std/parasite-head.S index e72646b50..6e46bed1f 100644 --- a/compel/arch/arm/plugins/std/parasite-head.S +++ b/compel/arch/arm/plugins/std/parasite-head.S @@ -2,21 +2,7 @@ .section .head.text, "ax" ENTRY(__export_parasite_head_start) - sub r2, pc, #8 @ get the address of this instruction - - adr r0, __export_parasite_cmd - ldr r0, [r0] - - adr r1, parasite_args_ptr - ldr r1, [r1] - add r1, r1, r2 @ fixup __export_parasite_args - bl parasite_service .byte 0xf0, 0x01, 0xf0, 0xe7 @ the instruction UDF #32 generates the signal SIGTRAP in Linux -parasite_args_ptr: - .long __export_parasite_args - -__export_parasite_cmd: - .long 0 END(__export_parasite_head_start) diff --git a/compel/arch/arm/scripts/compel-pack.lds.S b/compel/arch/arm/scripts/compel-pack.lds.S index f8a4739f3..3d97bb139 100644 --- a/compel/arch/arm/scripts/compel-pack.lds.S +++ b/compel/arch/arm/scripts/compel-pack.lds.S @@ -29,8 +29,4 @@ SECTIONS *(.eh_frame*) *(*) } - -/* Parasite args should have 4 bytes align, as we have futex inside. */ -. = ALIGN(4); -__export_parasite_args = .; } diff --git a/compel/arch/mips/plugins/std/parasite-head.S b/compel/arch/mips/plugins/std/parasite-head.S index 38e87f823..978c0b58c 100755 --- a/compel/arch/mips/plugins/std/parasite-head.S +++ b/compel/arch/mips/plugins/std/parasite-head.S @@ -6,15 +6,10 @@ ENTRY(__export_parasite_head_start) .set push .set noreorder - lw a0, __export_parasite_cmd - dla a1, __export_parasite_args jal parasite_service nop .byte 0x0d, 0x00, 0x00, 0x00 //break .set pop // .byte 0x40,0x01,0x00,0x00 //pause - -__export_parasite_cmd: - .long 0 END(__export_parasite_head_start) diff --git a/compel/arch/mips/scripts/compel-pack.lds.S b/compel/arch/mips/scripts/compel-pack.lds.S index cadb19aef..24ee408e8 100755 --- a/compel/arch/mips/scripts/compel-pack.lds.S +++ b/compel/arch/mips/scripts/compel-pack.lds.S @@ -30,8 +30,4 @@ SECTIONS *(.MIPS.options) *(.gnu.attributes) } - -/* Parasite args should have 4 bytes align, as we have futex inside. */ -. = ALIGN(32); -__export_parasite_args = .; } diff --git a/compel/arch/ppc64/plugins/std/parasite-head.S b/compel/arch/ppc64/plugins/std/parasite-head.S index c870efdc2..c675ab508 100644 --- a/compel/arch/ppc64/plugins/std/parasite-head.S +++ b/compel/arch/ppc64/plugins/std/parasite-head.S @@ -4,10 +4,6 @@ .align 8 ENTRY(__export_parasite_head_start) - - // int __used parasite_service(unsigned int cmd, void *args) - // cmd = r3 = *__export_parasite_cmd (u32 ?) - // args = r4 = @parasite_args_ptr + @pc bl 0f 0: mflr r2 @@ -15,12 +11,6 @@ ENTRY(__export_parasite_head_start) addis reg,r2,(name - 0b)@ha; \ addi reg,r2,(name - 0b)@l; - LOAD_REG_ADDR(r3,__export_parasite_cmd) - lwz r3,0(r3) - - LOAD_REG_ADDR(r4,parasite_args_ptr) - ld r4,0(r4) - LOAD_REG_ADDR(r12,parasite_service_ptr) ld r12,0(r12) mtctr r12 @@ -28,9 +18,6 @@ ENTRY(__export_parasite_head_start) bctrl // call parasite_service twi 31,0,0 // Should generate SIGTRAP -parasite_args_ptr: - .quad __export_parasite_args - parasite_service_ptr: // We want to run the function prototype to set r2. // Since the relocation will prefer the local entry @@ -39,7 +26,4 @@ parasite_service_ptr: // FIXME: There should be a way to specify the global entry here. .quad parasite_service - 8 -__export_parasite_cmd: - .long 0 - END(__export_parasite_head_start) diff --git a/compel/arch/ppc64/scripts/compel-pack.lds.S b/compel/arch/ppc64/scripts/compel-pack.lds.S index e0f826d7d..572f1c42d 100644 --- a/compel/arch/ppc64/scripts/compel-pack.lds.S +++ b/compel/arch/ppc64/scripts/compel-pack.lds.S @@ -33,8 +33,4 @@ SECTIONS *(.group*) *(.eh_frame*) } - -/* Parasite args should have 4 bytes align, as we have futex inside. */ -. = ALIGN(4); -__export_parasite_args = .; } diff --git a/compel/arch/s390/plugins/std/parasite-head.S b/compel/arch/s390/plugins/std/parasite-head.S index f4cb37276..1e276a2f5 100644 --- a/compel/arch/s390/plugins/std/parasite-head.S +++ b/compel/arch/s390/plugins/std/parasite-head.S @@ -2,25 +2,7 @@ .section .head.text, "ax" -/* - * Entry point for parasite_service() - * - * Addresses of symbols are exported in auto-generated criu/pie/parasite-blob.h - * - * Function is called via parasite_run(). The command for parasite_service() - * is stored in global variable __export_parasite_cmd. - * - * Load parameters for parasite_service(unsigned int cmd, void *args): - * - * - Parameter 1 (cmd) : %r2 = *(uint32 *)(__export_parasite_cmd + pc) - * - Parameter 2 (args): %r3 = __export_parasite_args + pc - */ ENTRY(__export_parasite_head_start) - larl %r14,__export_parasite_cmd - llgf %r2,0(%r14) - larl %r3,__export_parasite_args brasl %r14,parasite_service .long 0x00010001 /* S390_BREAKPOINT_U16: Generates SIGTRAP */ -__export_parasite_cmd: - .long 0 END(__export_parasite_head_start) diff --git a/compel/arch/s390/scripts/compel-pack.lds.S b/compel/arch/s390/scripts/compel-pack.lds.S index 91ffbda3e..2571ac852 100644 --- a/compel/arch/s390/scripts/compel-pack.lds.S +++ b/compel/arch/s390/scripts/compel-pack.lds.S @@ -33,8 +33,4 @@ SECTIONS *(.group*) *(.eh_frame*) } - -/* Parasite args should have 4 bytes align, as we have futex inside. */ -. = ALIGN(4); -__export_parasite_args = .; } diff --git a/compel/arch/x86/plugins/std/parasite-head.S b/compel/arch/x86/plugins/std/parasite-head.S index 465cd887b..2225568b9 100644 --- a/compel/arch/x86/plugins/std/parasite-head.S +++ b/compel/arch/x86/plugins/std/parasite-head.S @@ -11,8 +11,6 @@ andq $~15, %rsp pushq $\num movq %rsp, %rbp - movl __export_parasite_cmd(%rip), %edi - leaq __export_parasite_args(%rip), %rsi call parasite_service .endm @@ -48,7 +46,3 @@ ENTRY(__export_parasite_head_start) PARASITE_ENTRY 0 int $0x03 END(__export_parasite_head_start) - -.align 8 -GLOBAL(__export_parasite_cmd) - .long 0 diff --git a/compel/arch/x86/scripts/compel-pack-compat.lds.S b/compel/arch/x86/scripts/compel-pack-compat.lds.S index ff9c2c6b2..2d907a4a7 100644 --- a/compel/arch/x86/scripts/compel-pack-compat.lds.S +++ b/compel/arch/x86/scripts/compel-pack-compat.lds.S @@ -34,8 +34,4 @@ SECTIONS *(.group*) *(.eh_frame*) } - -/* Parasite args should have 4 bytes align, as we have futex inside. */ -. = ALIGN(4); -__export_parasite_args = .; } diff --git a/compel/arch/x86/scripts/compel-pack.lds.S b/compel/arch/x86/scripts/compel-pack.lds.S index 0c936f84d..68ddb3622 100644 --- a/compel/arch/x86/scripts/compel-pack.lds.S +++ b/compel/arch/x86/scripts/compel-pack.lds.S @@ -34,8 +34,4 @@ SECTIONS *(.group*) *(.eh_frame*) } - -/* Parasite args should have 4 bytes align, as we have futex inside. */ -. = ALIGN(4); -__export_parasite_args = .; } diff --git a/compel/include/uapi/infect.h b/compel/include/uapi/infect.h index aebaa8f75..8f9de0e1c 100644 --- a/compel/include/uapi/infect.h +++ b/compel/include/uapi/infect.h @@ -153,6 +153,7 @@ struct parasite_blob_desc { size_t nr_gotpcrel; unsigned long parasite_ip_off; unsigned long cmd_off; + unsigned long args_ptr_off; unsigned long args_off; compel_reloc_t *relocs; unsigned int nr_relocs; diff --git a/compel/plugins/include/uapi/std/infect.h b/compel/plugins/include/uapi/std/infect.h index 1e784f8b4..78de781b2 100644 --- a/compel/plugins/include/uapi/std/infect.h +++ b/compel/plugins/include/uapi/std/infect.h @@ -4,7 +4,10 @@ #include "common/compiler.h" extern int parasite_get_rpc_sock(void); -extern int __must_check parasite_service(unsigned int cmd, void *args); + +extern unsigned int __export_parasite_service_cmd; +extern void * __export_parasite_service_args_ptr; +extern int __must_check parasite_service(void); /* * Must be supplied by user plugins. diff --git a/compel/plugins/std/infect.c b/compel/plugins/std/infect.c index d5e1b4354..9749db7b7 100644 --- a/compel/plugins/std/infect.c +++ b/compel/plugins/std/infect.c @@ -196,8 +196,22 @@ err: # define __parasite_entry #endif -int __used __parasite_entry parasite_service(unsigned int cmd, void *args) +/* + * __export_parasite_service_{cmd,args} serve as arguments to the + * parasite_service() function. We use these global variables to make it + * easier to pass arguments when invoking from ptrace. + * + * We need the linker to allocate these variables. Hence the dummy + * initialization. Otherwise, we end up with COMMON symbols. + */ +unsigned int __export_parasite_service_cmd = 0; +void * __export_parasite_service_args_ptr = NULL; + +int __used __parasite_entry parasite_service(void) { + unsigned int cmd = __export_parasite_service_cmd; + void *args = __export_parasite_service_args_ptr; + pr_info("Parasite cmd %d/%x process\n", cmd, cmd); if (cmd == PARASITE_CMD_INIT_DAEMON) diff --git a/compel/src/lib/handle-elf.c b/compel/src/lib/handle-elf.c index 6fb0fb37f..8a79151b4 100644 --- a/compel/src/lib/handle-elf.c +++ b/compel/src/lib/handle-elf.c @@ -699,10 +699,9 @@ int __handle_elf(void *mem, size_t size) pr_out("\t\tpbd->hdr.parasite_ip_off = " "%s_sym__export_parasite_head_start_compat;\n", opts.prefix); pr_out("#endif /* CONFIG_COMPAT */\n"); - pr_out("\tpbd->hdr.cmd_off = " - "%s_sym__export_parasite_cmd;\n", opts.prefix); - pr_out("\tpbd->hdr.args_off = " - "%s_sym__export_parasite_args;\n", opts.prefix); + pr_out("\tpbd->hdr.cmd_off = %s_sym__export_parasite_service_cmd;\n", opts.prefix); + pr_out("\tpbd->hdr.args_ptr_off = %s_sym__export_parasite_service_args_ptr;\n", opts.prefix); + pr_out("\tpbd->hdr.args_off = round_up(pbd->hdr.bsize, 4);\n"); pr_out("\tpbd->hdr.relocs = %s_relocs;\n", opts.prefix); pr_out("\tpbd->hdr.nr_relocs = " "sizeof(%s_relocs) / sizeof(%s_relocs[0]);\n", diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 887a22d2a..78fe1f1a6 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -822,6 +822,13 @@ void compel_relocs_apply(void *mem, void *vbase, struct parasite_blob_desc *pbd) size_t i, j; + /* + * parasite_service() reads the value of __export_parasite_service_args_ptr. + * The reason it is set here is that semantically, we are doing a symbol + * resolution on parasite_service_args, and it turns out to be relocatable. + */ + *(void **)(mem + pbd->hdr.args_ptr_off) = vbase + pbd->hdr.args_off; + #ifdef CONFIG_MIPS compel_relocs_apply_mips(mem, vbase, pbd); #else @@ -883,7 +890,30 @@ int compel_infect(struct parasite_ctl *ctl, unsigned long nr_threads, unsigned l * without using ptrace at all. */ - parasite_size = ctl->pblob.hdr.bsize; + /* + * The parasite memory layout is the following: + * Low address start first. + * The number in parenthesis denotes the size of the section. + * The arrow on the right shows the different variables that + * corresponds to a given offset. + * +------------------------------------------------------+ <--- 0 + * | Parasite blob (sizeof(parasite_blob)) | + * +------------------------------------------------------+ <--- hdr.bsize + * align 4 + * +------------------------------------------------------+ <--- hdr.args_off + * | Args area (args_size) | + * +------------------------------------------------------+ + * align 64 + * +------------------------------------------------------+ <--- ctl->rsigframe + * | sigframe (RESTORE_STACK_SIGFRAME) | ctl->sigframe + * +------------------------------------------------------+ + * | main stack (PARASITE_STACK_SIZE) | + * +------------------------------------------------------+ <--- ctl->rstack + * | compel_run_in_thread stack (PARASITE_STACK_SIZE) | + * +------------------------------------------------------+ <--- ctl->r_thread_stack + * map_exchange_size + */ + parasite_size = ctl->pblob.hdr.args_off; ctl->args_size = args_size; parasite_size += ctl->args_size;