2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-09-05 08:45:49 +00:00

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 <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
Dmitry Safonov
2016-04-12 19:10:52 +03:00
committed by Andrei Vagin
parent 2aa583b45b
commit 024bae0af5
5 changed files with 42 additions and 16 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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(&regs)) {
user_regs_struct64 *r = &regs.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 = &regs->native;
iov.iov_len = sizeof(user_regs_struct64);
} else {

View File

@@ -4,6 +4,8 @@
#include <stdint.h>
#include <stdbool.h>
#include <signal.h>
#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