[CRIU] [PATCH 2/6] parasite-syscall: generalize the CPU register retrieval and set routines

Alexander Kartashov alekskartashov at parallels.com
Tue Oct 8 00:45:34 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 architecture-independent CRIU code be compatible
with architectures that don't support the PTRACE_GETREGS and PTRACE_SETREGS
ptrace calls. Such an architecture provides a generalized notinon of
a register set that is accessible by PTRACE_GETREGSET and PTRACE_SETREGSET
ptrace calls.

Architecture specific implementation is chosen by the macro ARCH_NEED_PTRACE_REGSET
that is defined for an architecture that support register sets and
doesn't support the legacy interface.

Note that ARM supports both interfaces, x86 supports the legacy version
only and AArch64 doesn't support it that makes it impossible to use
a single implementation everywhere.

Signed-off-by: Alexander Kartashov <alekskartashov at parallels.com>
---
 include/parasite-syscall.h |   39 +++++++++++++++++++++++++++++++++++++++
 parasite-syscall.c         |   20 ++++++++++----------
 2 files changed, 49 insertions(+), 10 deletions(-)

diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index 2f4ca82..70c55c4 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -3,6 +3,7 @@
 
 #define BUILTIN_SYSCALL_SIZE	8
 
+#include <sys/ptrace.h>
 #include "pstree.h"
 
 struct parasite_dump_thread;
@@ -116,4 +117,42 @@ extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
 
 extern int parasite_stop_on_syscall(int tasks, int sys_nr);
 extern int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr);
+
+
+#ifdef ARCH_NEED_PTRACE_REGSET
+
+#include <elf.h>
+
+static inline 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 inline 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);
+}
+
+#else
+
+static inline int ptrace_get_regs(int pid, user_regs_struct_t *regs)
+{
+	return ptrace(PTRACE_GETREGS, pid, NULL, regs);
+}
+
+static inline int ptrace_set_regs(int pid, user_regs_struct_t *regs)
+{
+	return ptrace(PTRACE_SETREGS, pid, NULL, regs);
+}
+
+#endif
+
 #endif /* __CR_PARASITE_SYSCALL_H__ */
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 6956798..66cb228 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -78,7 +78,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 +91,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 +130,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 +150,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 +520,7 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 	}
 	tc->has_blk_sigset = true;
 
-	ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs_orig);
+	ret = ptrace_get_regs(pid, &regs_orig);
 	if (ret) {
 		pr_perror("Can't obtain registers (pid: %d)", pid);
 		return -1;
@@ -801,7 +801,7 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
 		return -1;
 	}
 
-	ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
+	ret = ptrace_get_regs(pid, &regs);
 	if (ret) {
 		pr_perror("Unable to get registers");
 		return -1;
@@ -865,7 +865,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, &regs);
+		ret = ptrace_get_regs(pid, &regs);
 		if (ret) {
 			pr_perror("ptrace");
 			return -1;
@@ -981,7 +981,7 @@ int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr)
 
 	regs = ctl->regs_orig;
 	parasite_setup_regs(addr, 0, &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_sig;
 	}
@@ -994,7 +994,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 +1032,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