From 5e95eb8fde93f0de94ae4b6b18e15f184c732ba9 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Tue, 26 Mar 2013 13:39:28 +0100 Subject: [PATCH] On s390, set highest bit of PC in 31-bit tracer --- ...e-0.7.2-s390-set_instruction_pointer.patch | 94 +++++++++++++++++++ ltrace.spec | 12 ++- 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 ltrace-0.7.2-s390-set_instruction_pointer.patch diff --git a/ltrace-0.7.2-s390-set_instruction_pointer.patch b/ltrace-0.7.2-s390-set_instruction_pointer.patch new file mode 100644 index 0000000..c80bcf9 --- /dev/null +++ b/ltrace-0.7.2-s390-set_instruction_pointer.patch @@ -0,0 +1,94 @@ +From cb58fdb5a072ad70087a07f67d0c094ff77ca4b7 Mon Sep 17 00:00:00 2001 +From: Petr Machata +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 + diff --git a/ltrace.spec b/ltrace.spec index f6a6795..b3000f1 100644 --- a/ltrace.spec +++ b/ltrace.spec @@ -1,7 +1,7 @@ Summary: Tracks runtime library calls from dynamically linked executables Name: ltrace Version: 0.7.2 -Release: 4%{?dist} +Release: 5%{?dist} URL: http://ltrace.alioth.debian.org/ License: GPLv2+ Group: Development/Debuggers @@ -24,6 +24,9 @@ Patch1: ltrace-0.7.2-arm.patch # Work around a recently-added GCC warning. Patch2: ltrace-0.7.2-unused-typedef.patch +# s390 set_instruction_pointer: Set highest bit in 31-bit tracer +Patch3: ltrace-0.7.2-s390-set_instruction_pointer.patch + %description Ltrace is a debugging program which runs a specified command until the command exits. While the command is executing, ltrace intercepts and @@ -39,6 +42,7 @@ execution of processes. %patch0 -p1 %patch1 -p1 %patch2 -p1 +%patch3 -p1 %build autoreconf -i @@ -64,6 +68,12 @@ echo ====================TESTING END===================== %config(noreplace) %{_sysconfdir}/ltrace.conf %changelog +* Tue Mar 26 2013 Petr Machata - 0.7.2-5 +- On s390, the highest bit in PC address is used to distinguish + between 24-bit and 31-bit addressing modes. Linux used to do this + for us, but not anymore. + (ltrace-0.7.2-s390-set_instruction_pointer.patch) + * Wed Feb 6 2013 Petr Machata - 0.7.2-4 - Update the ARM patch (ltrace-0.7.2-arm.patch) with support for parameter passing conventions.