Commit 6068d10c authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

core/x86: add compatible 32 register set

Introduced user_regs_struct32.
Other changes mainly are reforming existing code to use the new
register sets union.

For protobuf images - reuse user_x86_regs_entry for both compatible
and native tasks with enum in the beggining that describes register
set type. That's better and simpler, than introducing a new 32-bit
register set for compatible tasks. I tried to do this firstly with
oneof keyword:
https://github.com/0x7f454c46/criu/commit/499c93ae0e2b8ffb8c562f309bb046d77d6b07c0
But protobuf supports oneof keyword only from recent version 2.6.0,
so I tried to rework it into enum + 2 register sets:
https://github.com/0x7f454c46/criu/commit/aab4489bd4e0b1360b6e05614c2fce3ff2a52eb7

But that did not work either because restorer pie takes gpregs as
thread_restore_args parameter and UserRegsEntry shouldn't contain
pointers, but structure objects. This may be fixed by redefining
UserRegsEntry not as typedef for UserX86RegsEntry, but containing
needed objects, than treat it right for restorer - but that's
more complicated that reusing user_x86_regs_entry.
Signed-off-by: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent d94b9f30
This diff is collapsed.
......@@ -5,6 +5,9 @@ extern int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core);
extern int arch_alloc_thread_info(CoreEntry *core);
extern void arch_free_thread_info(CoreEntry *core);
#define ARCH_HAS_GET_REGS
extern int ptrace_get_regs(pid_t pid, user_regs_struct_t *regs);
extern int ptrace_set_regs(pid_t pid, user_regs_struct_t *regs);
#define core_put_tls(core, tls)
......
......@@ -11,34 +11,78 @@
#define SIGMAX_OLD 31
typedef struct {
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long bp;
unsigned long bx;
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long ax;
unsigned long cx;
unsigned long dx;
unsigned long si;
unsigned long di;
unsigned long orig_ax;
unsigned long ip;
unsigned long cs;
unsigned long flags;
unsigned long sp;
unsigned long ss;
unsigned long fs_base;
unsigned long gs_base;
unsigned long ds;
unsigned long es;
unsigned long fs;
unsigned long gs;
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t bp;
uint64_t bx;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t ax;
uint64_t cx;
uint64_t dx;
uint64_t si;
uint64_t di;
uint64_t orig_ax;
uint64_t ip;
uint64_t cs;
uint64_t flags;
uint64_t sp;
uint64_t ss;
uint64_t fs_base;
uint64_t gs_base;
uint64_t ds;
uint64_t es;
uint64_t fs;
uint64_t gs;
} user_regs_struct64;
typedef struct {
uint32_t bx;
uint32_t cx;
uint32_t dx;
uint32_t si;
uint32_t di;
uint32_t bp;
uint32_t ax;
uint32_t ds;
uint32_t es;
uint32_t fs;
uint32_t gs;
uint32_t orig_ax;
uint32_t ip;
uint32_t cs;
uint32_t flags;
uint32_t sp;
uint32_t ss;
} user_regs_struct32;
#ifdef CONFIG_X86_64
typedef struct {
union {
user_regs_struct64 native;
user_regs_struct32 compat;
};
bool is_native;
} 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))
#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)
#endif
#if 0
typedef struct {
......@@ -74,9 +118,9 @@ static inline unsigned long task_size(void) { return TASK_SIZE; }
typedef uint64_t auxv_t;
typedef uint32_t tls_t;
#define REG_RES(regs) ((regs).ax)
#define REG_IP(regs) ((regs).ip)
#define REG_SYSCALL_NR(regs) ((regs).orig_ax)
#define REG_RES(regs) get_user_reg(&regs, ax)
#define REG_IP(regs) get_user_reg(&regs, ip)
#define REG_SYSCALL_NR(regs) get_user_reg(&regs, orig_ax)
#define AT_VECTOR_SIZE 44
......
......@@ -69,6 +69,7 @@ unsigned long get_exec_start(struct vm_area_list *vmas)
return 0;
}
#ifndef ARCH_HAS_GET_REGS
static inline int ptrace_get_regs(int pid, user_regs_struct_t *regs)
{
struct iovec iov;
......@@ -86,6 +87,7 @@ static inline int ptrace_set_regs(int pid, user_regs_struct_t *regs)
iov.iov_len = sizeof(user_regs_struct_t);
return ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov);
}
#endif
static int get_thread_ctx(int pid, struct thread_ctx *ctx)
{
......
......@@ -2,6 +2,12 @@ syntax = "proto2";
import "opts.proto";
enum user_x86_regs_case_t {
NATIVE = 1;
COMPAT = 2;
}
/* Reusing entry for both 64 and 32 bits register sets */
message user_x86_regs_entry {
required uint64 r15 = 1;
required uint64 r14 = 2;
......@@ -30,6 +36,7 @@ message user_x86_regs_entry {
required uint64 es = 25;
required uint64 fs = 26;
required uint64 gs = 27;
optional user_x86_regs_case_t gpregs_case = 28 [default = NATIVE];
}
message user_x86_xsave_entry {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment