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
49arch_addr_t
50get_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
61void
62set_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
75arch_addr_t
76get_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
87arch_addr_t
88get_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