[CRIU] [PATCH 1/8] parasite-syscall: use the ptrace requests PTRACE_(GET|SET)REGSET to retrieve and set CPU registers
Alexander Kartashov
alekskartashov at parallels.com
Thu Oct 10 23:47:58 PDT 2013
This patch introduces the routines ptrace_get_gpregs() and ptrace_set_gpregs()
that wrap the ptrace interface to get and set CPU registers respectively.
The motivation is to make the CRIU code be compatible with architectures that
don't support the PTRACE_GETREGS and PTRACE_SETREGS ptrace calls ---
the requests PTRACE_GETREGSET and PTRACE_SETREGSET are implemented instead.
Signed-off-by: Alexander Kartashov <alekskartashov at parallels.com>
---
include/ptrace.h | 5 +++++
parasite-syscall.c | 39 +++++++++++++++++++++++++++++----------
2 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/include/ptrace.h b/include/ptrace.h
index 61c3b6a..3bcc951 100644
--- a/include/ptrace.h
+++ b/include/ptrace.h
@@ -27,6 +27,11 @@ struct ptrace_peeksiginfo_args {
#define PTRACE_PEEKSIGINFO_SHARED (1 << 0)
#endif
+#ifndef PTRACE_GETREGSET
+# define PTRACE_GETREGSET 0x4204
+# define PTRACE_SETREGSET 0x4205
+#endif
+
#define PTRACE_GETSIGMASK 0x420a
#define PTRACE_SETSIGMASK 0x420b
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 6956798..8761f6d 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -30,6 +30,7 @@
#include <string.h>
#include <stdlib.h>
+#include <elf.h>
#include "asm/parasite-syscall.h"
#include "asm/dump.h"
@@ -37,6 +38,24 @@
#define parasite_size (round_up(sizeof(parasite_blob), PAGE_SIZE))
+static int ptrace_get_regs(int pid, user_regs_struct_t *regs)
+{
+ struct iovec iov;
+
+ iov.iov_base = regs;
+ iov.iov_len = sizeof(user_regs_struct_t);
+ return ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov);
+}
+
+static int ptrace_set_regs(int pid, user_regs_struct_t *regs)
+{
+ struct iovec iov;
+
+ iov.iov_base = regs;
+ iov.iov_len = sizeof(user_regs_struct_t);
+ return ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov);
+}
+
static int can_run_syscall(unsigned long ip, unsigned long start, unsigned long end)
{
return ip >= start && ip < (end - code_syscall_size);
@@ -78,7 +97,7 @@ static int parasite_run(pid_t pid, unsigned long ip, void *stack,
}
parasite_setup_regs(ip, stack, regs);
- if (ptrace(PTRACE_SETREGS, pid, NULL, regs)) {
+ if (ptrace_set_regs(pid, regs)) {
pr_perror("Can't set registers for %d", pid);
goto err_regs;
}
@@ -91,7 +110,7 @@ static int parasite_run(pid_t pid, unsigned long ip, void *stack,
return 0;
err_cont:
- if (ptrace(PTRACE_SETREGS, pid, NULL, oregs))
+ if (ptrace_set_regs(pid, oregs))
pr_perror("Can't restore regs for %d", pid);
err_regs:
if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), omask))
@@ -130,7 +149,7 @@ static int parasite_trap(struct parasite_ctl *ctl, pid_t pid,
goto err;
}
- if (ptrace(PTRACE_GETREGS, pid, NULL, regs)) {
+ if (ptrace_get_regs(pid, regs)) {
pr_perror("Can't obtain registers (pid: %d)", pid);
goto err;
}
@@ -150,7 +169,7 @@ static int parasite_trap(struct parasite_ctl *ctl, pid_t pid,
ret = 0;
err:
- if (ptrace(PTRACE_SETREGS, pid, NULL, regs_orig)) {
+ if (ptrace_set_regs(pid, regs_orig)) {
pr_perror("Can't restore registers (pid: %d)", pid);
ret = -1;
}
@@ -520,7 +539,7 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
}
tc->has_blk_sigset = true;
- ret = ptrace(PTRACE_GETREGS, pid, NULL, ®s_orig);
+ ret = ptrace_get_regs(pid, ®s_orig);
if (ret) {
pr_perror("Can't obtain registers (pid: %d)", pid);
return -1;
@@ -801,7 +820,7 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
return -1;
}
- ret = ptrace(PTRACE_GETREGS, pid, NULL, ®s);
+ ret = ptrace_get_regs(pid, ®s);
if (ret) {
pr_perror("Unable to get registers");
return -1;
@@ -865,7 +884,7 @@ int parasite_stop_on_syscall(int tasks, const int sys_nr)
pr_err("%d\n", status);
return -1;
}
- ret = ptrace(PTRACE_GETREGS, pid, NULL, ®s);
+ ret = ptrace_get_regs(pid, ®s);
if (ret) {
pr_perror("ptrace");
return -1;
@@ -981,7 +1000,7 @@ int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr)
regs = ctl->regs_orig;
parasite_setup_regs(addr, 0, ®s);
- if (ptrace(PTRACE_SETREGS, pid, NULL, ®s)) {
+ if (ptrace_set_regs(pid, ®s)) {
pr_perror("Can't set registers for %d", pid);
goto err_sig;
}
@@ -994,7 +1013,7 @@ int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr)
ret = parasite_stop_on_syscall(1, __NR_munmap);
err_regs:
- if (ptrace(PTRACE_SETREGS, pid, NULL, &ctl->regs_orig)) {
+ if (ptrace_set_regs(pid, &ctl->regs_orig)) {
pr_perror("Can't restore regs for %d", pid);
ret = -1;
}
@@ -1032,7 +1051,7 @@ struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_
goto err;
}
- if (ptrace(PTRACE_GETREGS, pid, NULL, &ctl->regs_orig)) {
+ if (ptrace_get_regs(pid, &ctl->regs_orig)) {
pr_err("Can't obtain registers (pid: %d)\n", pid);
goto err;
}
--
1.7.9.5
More information about the CRIU
mailing list