1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2013 Petr Machata, Red Hat Inc.
4  * Copyright (C) 2002,2004,2008,2009 Juan Cespedes
5  * Copyright (C) 2009 Juan Cespedes
6  * Copyright (C) 2006 Ian Wienand
7  * Copyright (C) 2001 IBM Poughkeepsie, IBM Corporation
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22  * 02110-1301 USA
23  */
24 
25 #include "config.h"
26 
27 #include <sys/types.h>
28 #include <sys/ptrace.h>
29 #include <asm/ptrace.h>
30 
31 #include "proc.h"
32 #include "common.h"
33 
34 #if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
35 # define PTRACE_PEEKUSER PTRACE_PEEKUSR
36 #endif
37 
38 #if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
39 # define PTRACE_POKEUSER PTRACE_POKEUSR
40 #endif
41 
42 #ifdef __s390x__
43 #define PSW_MASK	0xffffffffffffffff
44 #define PSW_MASK31	0x7fffffff
45 #else
46 #define PSW_MASK	0x7fffffff
47 #endif
48 
49 arch_addr_t
get_instruction_pointer(struct process * proc)50 get_instruction_pointer(struct process *proc)
51 {
52 	long ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWADDR, 0) & PSW_MASK;
53 #ifdef __s390x__
54 	if (proc->mask_32bit)
55 		ret &= PSW_MASK31;
56 #endif
57 	/* XXX double cast.  */
58 	return (arch_addr_t)ret;
59 }
60 
61 void
set_instruction_pointer(struct process * proc,arch_addr_t addr)62 set_instruction_pointer(struct process *proc, arch_addr_t addr)
63 {
64 #ifdef __s390x__
65 	if (proc->mask_32bit)
66 		/* XXX double cast.  */
67 		addr = (arch_addr_t)((uintptr_t)addr & PSW_MASK31);
68 #else
69 	/* XXX double cast.  */
70 	addr = (arch_addr_t)((uintptr_t)addr | ~PSW_MASK);
71 #endif
72 	ptrace(PTRACE_POKEUSER, proc->pid, PT_PSWADDR, addr);
73 }
74 
75 arch_addr_t
get_stack_pointer(struct process * proc)76 get_stack_pointer(struct process *proc)
77 {
78 	long ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR15, 0) & PSW_MASK;
79 #ifdef __s390x__
80 	if (proc->mask_32bit)
81 		ret &= PSW_MASK31;
82 #endif
83 	/* XXX double cast.  */
84 	return (arch_addr_t)ret;
85 }
86 
87 arch_addr_t
get_return_addr(struct process * proc,arch_addr_t stack_pointer)88 get_return_addr(struct process *proc, arch_addr_t stack_pointer)
89 {
90 	long ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR14, 0) & PSW_MASK;
91 #ifdef __s390x__
92 	if (proc->mask_32bit)
93 		ret &= PSW_MASK31;
94 #endif
95 	/* XXX double cast.  */
96 	return (arch_addr_t)ret;
97 }
98