codonell / rpms / ltrace

Forked from rpms/ltrace 4 years ago
Clone
Blob Blame History Raw
From cb58fdb5a072ad70087a07f67d0c094ff77ca4b7 Mon Sep 17 00:00:00 2001
From: Petr Machata <pmachata@redhat.com>
Date: Tue, 26 Mar 2013 13:26:23 +0100
Subject: [PATCH] s390 set_instruction_pointer: Set highest bit in 31-bit tracer

- The highest bit is used to distinguish between 24-bit and 31-bit
  addressing modes.  Up until about 3.1, Linux did this automatically,
  but stopped doing so with the following commit:

    https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=d4e81b35b882d96f059afdb0f98e5b6025973b09
---
 sysdeps/linux-gnu/s390/regs.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/sysdeps/linux-gnu/s390/regs.c b/sysdeps/linux-gnu/s390/regs.c
index bb16c61..656654a 100644
--- a/sysdeps/linux-gnu/s390/regs.c
+++ b/sysdeps/linux-gnu/s390/regs.c
@@ -46,7 +46,7 @@
 #define PSW_MASK	0x7fffffff
 #endif
 
-void *
+arch_addr_t
 get_instruction_pointer(struct process *proc)
 {
 	long ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWADDR, 0) & PSW_MASK;
@@ -54,20 +54,22 @@ get_instruction_pointer(struct process *proc)
 	if (proc->mask_32bit)
 		ret &= PSW_MASK31;
 #endif
-	return (void *)ret;
+	/* XXX double cast.  */
+	return (arch_addr_t)ret;
 }
 
 void
-set_instruction_pointer(struct process *proc, void *addr)
+set_instruction_pointer(struct process *proc, arch_addr_t addr)
 {
 #ifdef __s390x__
 	if (proc->mask_32bit)
-		addr = (void *)((long)addr & PSW_MASK31);
+		/* XXX double cast.  */
+		addr = (arch_addr_t)((uintptr_t)addr & PSW_MASK31);
 #endif
 	ptrace(PTRACE_POKEUSER, proc->pid, PT_PSWADDR, addr);
 }
 
-void *
+arch_addr_t
 get_stack_pointer(struct process *proc)
 {
 	long ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR15, 0) & PSW_MASK;
@@ -75,16 +77,18 @@ get_stack_pointer(struct process *proc)
 	if (proc->mask_32bit)
 		ret &= PSW_MASK31;
 #endif
-	return (void *)ret;
+	/* XXX double cast.  */
+	return (arch_addr_t)ret;
 }
 
-void *
-get_return_addr(struct process *proc, void *stack_pointer)
+arch_addr_t
+get_return_addr(struct process *proc, arch_addr_t stack_pointer)
 {
 	long ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR14, 0) & PSW_MASK;
 #ifdef __s390x__
 	if (proc->mask_32bit)
 		ret &= PSW_MASK31;
 #endif
-	return (void *)ret;
+	/* XXX double cast.  */
+	return (arch_addr_t)ret;
 }
diff --git a/sysdeps/linux-gnu/s390/regs.c b/sysdeps/linux-gnu/s390/regs.c
index 656654a..51410d7 100644
--- a/sysdeps/linux-gnu/s390/regs.c
+++ b/sysdeps/linux-gnu/s390/regs.c
@@ -65,6 +65,9 @@ set_instruction_pointer(struct process *proc, arch_addr_t addr)
 	if (proc->mask_32bit)
 		/* XXX double cast.  */
 		addr = (arch_addr_t)((uintptr_t)addr & PSW_MASK31);
+#else
+	/* XXX double cast.  */
+	addr = (arch_addr_t)((uintptr_t)addr | ~PSW_MASK);
 #endif
 	ptrace(PTRACE_POKEUSER, proc->pid, PT_PSWADDR, addr);
 }
-- 
1.7.6.5