1ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata/*
2ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * This file is part of ltrace.
344ae188c8dcd2727e383dcac0d46c3f784d0da5fPetr Machata * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
4ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * Copyright (C) 1998,2002,2004,2008,2009 Juan Cespedes
5ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * Copyright (C) 2006 Ian Wienand
6ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata *
7ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * This program is free software; you can redistribute it and/or
8ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * modify it under the terms of the GNU General Public License as
9ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * published by the Free Software Foundation; either version 2 of the
10ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * License, or (at your option) any later version.
11ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata *
12ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * This program is distributed in the hope that it will be useful, but
13ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
14ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * General Public License for more details.
16ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata *
17ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * You should have received a copy of the GNU General Public License
18ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * along with this program; if not, write to the Free Software
19ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata * 02110-1301 USA
21ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata */
22ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include "config.h"
23ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
24ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include <sys/types.h>
25ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include <sys/ptrace.h>
26ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include <sys/reg.h>
27ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include <errno.h>
28ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include <stdio.h>
29ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include <string.h>
30ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
31ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include "backend.h"
32ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include "proc.h"
33ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
34ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
35ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata# define PTRACE_PEEKUSER PTRACE_PEEKUSR
36ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
37ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
38ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
39ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata# define PTRACE_POKEUSER PTRACE_POKEUSR
40ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
41ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
42ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__
43ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata# define XIP (8 * RIP)
44ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata# define XSP (8 * RSP)
45ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else
46ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata# define XIP (4 * EIP)
47ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata# define XSP (4 * UESP)
48ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
49ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
50bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machatastatic arch_addr_t
51bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machataconv_32(arch_addr_t val)
52ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata{
53bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	/* XXX Drop the multiple double casts when arch_addr_t
54ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	 * becomes integral.  */
55bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	return (arch_addr_t)(uintptr_t)(uint32_t)(uintptr_t)val;
56ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata}
57ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
58ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machatavoid *
59929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataget_instruction_pointer(struct process *proc)
60ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata{
61ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, XIP, 0);
62ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	if (proc->e_machine == EM_386)
63ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		ret &= 0xffffffff;
64ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	return (void *)ret;
65ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata}
66ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
67ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machatavoid
68929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataset_instruction_pointer(struct process *proc, arch_addr_t addr)
69ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata{
70ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	if (proc->e_machine == EM_386)
71ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		addr = conv_32(addr);
72ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	ptrace(PTRACE_POKEUSER, proc->pid, XIP, addr);
73ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata}
74ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
75ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machatavoid *
76929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataget_stack_pointer(struct process *proc)
77ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata{
78ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	long sp = ptrace(PTRACE_PEEKUSER, proc->pid, XSP, 0);
79ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	if (sp == -1 && errno) {
80ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		fprintf(stderr, "Couldn't read SP register: %s\n",
81ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata			strerror(errno));
82ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		return NULL;
83ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	}
84ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
85bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	/* XXX Drop the multiple double casts when arch_addr_t
86ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	 * becomes integral.  */
87bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	arch_addr_t ret = (arch_addr_t)(uintptr_t)sp;
88ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	if (proc->e_machine == EM_386)
89ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		ret = conv_32(ret);
90ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	return ret;
91ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata}
92ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
93ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machatavoid *
94929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataget_return_addr(struct process *proc, void *sp)
95ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata{
96ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	long a = ptrace(PTRACE_PEEKTEXT, proc->pid, sp, 0);
97ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	if (a == -1 && errno) {
98ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		fprintf(stderr, "Couldn't read return value: %s\n",
99ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata			strerror(errno));
100ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		return NULL;
101ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	}
102ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
103bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	/* XXX Drop the multiple double casts when arch_addr_t
104ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	 * becomes integral.  */
105bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	arch_addr_t ret = (arch_addr_t)(uintptr_t)a;
106ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	if (proc->e_machine == EM_386)
107ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		ret = conv_32(ret);
108ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	return ret;
109ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata}
110