diff --git a/criu/arch/aarch64/include/asm/infect-types.h b/criu/arch/aarch64/include/asm/infect-types.h index 76fcfebf5..714881c57 100644 --- a/criu/arch/aarch64/include/asm/infect-types.h +++ b/criu/arch/aarch64/include/asm/infect-types.h @@ -23,6 +23,8 @@ typedef struct user_fpsimd_state user_fpregs_struct_t; #define REG_IP(r) ((uint64_t)(r).pc) #define REG_SYSCALL_NR(r) ((uint64_t)(r).regs[8]) +#define user_regs_native(pregs) true + /* * Range for task size calculated from the following Linux kernel files: * arch/arm64/include/asm/memory.h diff --git a/criu/arch/arm/include/asm/infect-types.h b/criu/arch/arm/include/asm/infect-types.h index 3552ec931..9c2092e5d 100644 --- a/criu/arch/arm/include/asm/infect-types.h +++ b/criu/arch/arm/include/asm/infect-types.h @@ -57,6 +57,8 @@ struct user_vfp_exc { #define REG_IP(regs) ((regs).ARM_pc) #define REG_SYSCALL_NR(regs) ((regs).ARM_r7) +#define user_regs_native(pregs) true + /* * Range for task size calculated from the following Linux kernel files: * arch/arm/include/asm/memory.h diff --git a/criu/arch/ppc64/include/asm/infect-types.h b/criu/arch/ppc64/include/asm/infect-types.h index 1969ca2b5..f243def73 100644 --- a/criu/arch/ppc64/include/asm/infect-types.h +++ b/criu/arch/ppc64/include/asm/infect-types.h @@ -76,6 +76,8 @@ typedef struct { #define REG_IP(regs) ((uint64_t)(regs).nip) #define REG_SYSCALL_NR(regs) ((uint64_t)(regs).gpr[0]) +#define user_regs_native(pregs) true + /* * Copied from the following kernel header files : * include/linux/auxvec.h diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c index 85f2f54ed..f48aa82de 100644 --- a/criu/arch/x86/crtools.c +++ b/criu/arch/x86/crtools.c @@ -67,7 +67,7 @@ int arch_task_compatible(pid_t pid) if (ret) return -1; - return !r.is_native; + return !user_regs_native(&r); } #define USER32_CS 0x23 @@ -120,7 +120,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, user_regs_struct_t regs = ctl->orig.regs; int err; - if (regs.is_native) { + if (user_regs_native(®s)) { user_regs_struct64 *r = ®s.native; r->ax = (uint64_t)nr; @@ -152,7 +152,7 @@ static int save_task_regs(CoreEntry *core, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs); #define get_signed_user_reg(pregs, name) \ - (((pregs)->is_native) ? (int64_t)((pregs)->native.name) : \ + ((user_regs_native(pregs)) ? (int64_t)((pregs)->native.name) : \ (int32_t)((pregs)->compat.name)) int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core) { @@ -222,7 +222,7 @@ static int save_task_regs(CoreEntry *core, #define assign_reg(dst, src, e) do { dst->e = (__typeof__(dst->e))src.e; } while (0) #define assign_array(dst, src, e) memcpy(dst->e, &src.e, sizeof(src.e)) - if (regs.is_native) { + if (user_regs_native(regs)) { assign_reg(gpregs, regs->native, r15); assign_reg(gpregs, regs->native, r14); assign_reg(gpregs, regs->native, r13); @@ -314,11 +314,11 @@ int ptrace_get_regs(pid_t pid, user_regs_struct_t *regs) ret = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov); if (iov.iov_len == sizeof(regs->native)) { - regs->is_native = true; + regs->__is_native = NATIVE_MAGIC; return ret; } if (iov.iov_len == sizeof(regs->compat)) { - regs->is_native = false; + regs->__is_native = COMPAT_MAGIC; return ret; } @@ -332,7 +332,7 @@ int ptrace_set_regs(pid_t pid, user_regs_struct_t *regs) { struct iovec iov; - if (regs->is_native) { + if (user_regs_native(regs)) { iov.iov_base = ®s->native; iov.iov_len = sizeof(user_regs_struct64); } else { diff --git a/criu/arch/x86/include/asm/infect-types.h b/criu/arch/x86/include/asm/infect-types.h index d56902acf..08344f747 100644 --- a/criu/arch/x86/include/asm/infect-types.h +++ b/criu/arch/x86/include/asm/infect-types.h @@ -4,6 +4,8 @@ #include #include #include +#include "log.h" +#include "common/bug.h" #include "common/page.h" #include "syscall-types.h" @@ -61,27 +63,45 @@ typedef struct { } user_regs_struct32; #ifdef CONFIG_X86_64 +/* + * To be sure that we rely on inited reg->__is_native, this member + * is (short int) instead of initial (bool). The right way to + * check if regs are native or compat is to use user_regs_native() macro. + * This should cost nothing, as *usually* sizeof(bool) == sizeof(short) + */ typedef struct { union { user_regs_struct64 native; user_regs_struct32 compat; }; - bool is_native; + short __is_native; /* use user_regs_native macro to check it */ } user_regs_struct_t; -#define get_user_reg(pregs, name) (((pregs)->is_native) ? \ - ((pregs)->native.name) : \ - ((pregs)->compat.name)) -#define set_user_reg(pregs, name, val) (((pregs)->is_native) ? \ - ((pregs)->native.name = val) : \ - ((pregs)->compat.name = val)) + +#define NATIVE_MAGIC 0x0A +#define COMPAT_MAGIC 0x0C +static inline bool user_regs_native(user_regs_struct_t *pregs) +{ + return pregs->__is_native == NATIVE_MAGIC; +} + +#define get_user_reg(pregs, name) \ + ((user_regs_native(pregs)) ? \ + ((pregs)->native.name) : \ + ((pregs)->compat.name)) + +#define set_user_reg(pregs, name, val) \ + ((user_regs_native(pregs)) ? \ + ((pregs)->native.name = (val)) : \ + ((pregs)->compat.name = (val))) #else typedef struct { union { user_regs_struct32 native; }; } user_regs_struct_t; -#define get_user_reg(pregs, name) ((pregs)->native.name) -#define set_user_reg(pregs, name, val) ((pregs)->native.name = val) +#define user_regs_native(pregs) true +#define get_user_reg(pregs, name) ((pregs)->native.name) +#define set_user_reg(pregs, name, val) ((pregs)->native.name = val) #endif #if 0