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