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:
committed by
Andrei Vagin
parent
2aa583b45b
commit
024bae0af5
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user