From 024bae0af586ab6f42297e302f6ced095aa8b51c Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Tue, 12 Apr 2016 19:10:52 +0300 Subject: [PATCH] x86: add user_regs_native macro (optional) This will document that {get,set}_user_reg should be used only on initialized register set. Otherwise, after some code changes we may find ourself in situation when setting not inited user regs will set them for compatible register set: (is_native == false). Signed-off-by: Dmitry Safonov Acked-by: Cyrill Gorcunov Signed-off-by: Pavel Emelyanov Signed-off-by: Andrei Vagin --- criu/arch/aarch64/include/asm/infect-types.h | 2 ++ criu/arch/arm/include/asm/infect-types.h | 2 ++ criu/arch/ppc64/include/asm/infect-types.h | 2 ++ criu/arch/x86/crtools.c | 14 ++++---- criu/arch/x86/include/asm/infect-types.h | 38 +++++++++++++++----- 5 files changed, 42 insertions(+), 16 deletions(-) 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