1e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata/*
2e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This file is part of ltrace.
3e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2010 Edgar E. Iglesias
4e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata *
5e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is free software; you can redistribute it and/or
6e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * modify it under the terms of the GNU General Public License as
7e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * published by the Free Software Foundation; either version 2 of the
8e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * License, or (at your option) any later version.
9e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata *
10e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is distributed in the hope that it will be useful, but
11e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
12e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * General Public License for more details.
14e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata *
15e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * You should have received a copy of the GNU General Public License
16e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * along with this program; if not, write to the Free Software
17e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 02110-1301 USA
19e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata */
20e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata
21b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#if HAVE_CONFIG_H
22b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#include "config.h"
23b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#endif
24b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias
25b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#include <sys/types.h>
26b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#include <sys/wait.h>
27b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#include <signal.h>
28b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#include <sys/ptrace.h>
29b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#include <asm/ptrace.h>
30b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#include <elf.h>
31b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias
32366c2f46d844f040458df9b7e35fc3b8527ed2d3Petr Machata#include "proc.h"
33b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#include "common.h"
34b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias
35b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
36b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias# define PTRACE_PEEKUSER PTRACE_PEEKUSR
37b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#endif
38b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias
39b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
40b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias# define PTRACE_POKEUSER PTRACE_POKEUSR
41b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#endif
42b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias
43929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatavoid get_arch_dep(struct process *proc)
44b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias{
45b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias}
46b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias
47b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
48b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias */
49b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias#define SYSCALL_INSN   0xe93d
50929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataint syscall_p(struct process *proc, int status, int *sysnum)
51b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias{
52b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	if (WIFSTOPPED(status)
53b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
54b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias		long pc = (long)get_instruction_pointer(proc);
55b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias		unsigned int insn =
56b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias		    (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(long),
57b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias				0);
58b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias
59b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias		if ((insn >> 16) == SYSCALL_INSN) {
60b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias			*sysnum =
61b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias			    (int)ptrace(PTRACE_PEEKUSER, proc->pid,
62b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias					sizeof(long) * PT_R9, 0);
63b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias			if (proc->callstack_depth > 0
64b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias			    && proc->callstack[proc->callstack_depth -
65b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias					       1].is_syscall) {
66b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias				return 2;
67b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias			}
68b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias			return 1;
69b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias		}
70b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	}
71b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	return 0;
72b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias}
73b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias
74929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatalong gimme_arg(enum tof type, struct process *proc, int arg_num,
75000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	       struct arg_type_info *info)
76b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias{
77b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	int pid = proc->pid;
78b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias
79b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	if (arg_num == -1) {	/* return value */
80b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias		return ptrace(PTRACE_PEEKUSER, pid, PT_R10 * 4, 0);
81b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	} else if (arg_num < 6) {
82b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias		int pt_arg[6] =
83b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias			{
84b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias				PT_ORIG_R10, PT_R11, PT_R12, PT_R13, PT_MOF,
85b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias				PT_SRP
86b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias			};
87b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias		return ptrace(PTRACE_PEEKUSER, pid, pt_arg[arg_num] * 4, 0);
88b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	} else {
89b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias		return ptrace(PTRACE_PEEKDATA, pid,
90b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias			      proc->stack_pointer + 4 * (arg_num - 6), 0);
91b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	}
92b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias	return 0;
93b1dda4bc2c78429823a5ca7699f3207a7aea2371Edgar E. Iglesias}
94