[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, &regs_orig);
+	ret = ptrace_get_regs(pid, &regs_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, &regs);
+	ret = ptrace_get_regs(pid, &regs);
 	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, &regs);
+		ret = ptrace_get_regs(pid, &regs);
 		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, &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 +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