1e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata/*
2e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This file is part of ltrace.
3693dfad9c1b121cf079a3082866daa2225df1797Petr Machata * Copyright (C) 2013 Petr Machata, Red Hat Inc.
4e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2012 Edgar E. Iglesias, Axis Communications
5e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2010 Arnaud Patard, Mandriva SA
6e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2008,2009 Juan Cespedes
7e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
8e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata *
9e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is free software; you can redistribute it and/or
10e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * modify it under the terms of the GNU General Public License as
11e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * published by the Free Software Foundation; either version 2 of the
12e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * License, or (at your option) any later version.
13e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata *
14e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is distributed in the hope that it will be useful, but
15e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
16e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * General Public License for more details.
18e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata *
19e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * You should have received a copy of the GNU General Public License
20e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * along with this program; if not, write to the Free Software
21e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 02110-1301 USA
23e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata */
24e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata
251228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#include "config.h"
261228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
271228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#include <sys/types.h>
281228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#include <sys/wait.h>
291228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#include <signal.h>
301228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#include <sys/ptrace.h>
311228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#include <asm/ptrace.h>
32addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#include <assert.h>
333b3b0d3a24c1b6c374cc2338d9791518fffa29bePetr Machata
343b3b0d3a24c1b6c374cc2338d9791518fffa29bePetr Machata#include "backend.h"
35f728123bd75a65a6a1536e198c3c30719e494e71Juan Cespedes#include "common.h"
363b3b0d3a24c1b6c374cc2338d9791518fffa29bePetr Machata#include "debug.h"
3732ea1b1eaad1a07a120811bca9dd9f3524cc9256Oliver Spornitz#include "mips.h"
383b3b0d3a24c1b6c374cc2338d9791518fffa29bePetr Machata#include "proc.h"
39000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#include "type.h"
403b3b0d3a24c1b6c374cc2338d9791518fffa29bePetr Machata
411228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
421228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl# define PTRACE_PEEKUSER PTRACE_PEEKUSR
431228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#endif
441228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
451228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
461228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl# define PTRACE_POKEUSER PTRACE_POKEUSR
471228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#endif
481228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
491228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
501228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl/**
5132ea1b1eaad1a07a120811bca9dd9f3524cc9256Oliver Spornitz   \addtogroup mips Mips specific functions.
521228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
531228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   These are the functions that it looks like I need to implement in
54fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes   order to get ltrace to work on our target.
551228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
561228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   @{
571228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl */
581228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
591228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl/**
60fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes   \param proc The process that had an event.
611228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
62e2023f721b66db48cc8a0f4ab6519460093c2cf1Juan Cespedes   Called by \c next_event() right after the return from wait.
631228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
641228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   Most targets just return here. A couple use proc->arch_ptr for a
651228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   private data area.
661228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl */
67f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
68929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataget_arch_dep(struct process *proc)
69929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{
701228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl}
711228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
721228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl/**
73fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes   \param proc Process that had event.
741228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   \param status From \c wait()
75fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes   \param sysnum 0-based syscall number.
761228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   \return 1 if syscall, 2 if sysret, 0 otherwise.
771228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
78e2023f721b66db48cc8a0f4ab6519460093c2cf1Juan Cespedes   Called by \c next_event() after the call to get_arch_dep()
791228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
801228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   It seems that the ptrace call trips twice on a system call, once
811228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   just before the system call and once when it returns. Both times,
8232ea1b1eaad1a07a120811bca9dd9f3524cc9256Oliver Spornitz   the pc points at the instruction just after the mips "syscall"
831228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   instruction.
841228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
851228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   There are several possiblities for system call sets, each is offset
861228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   by a base from the others. On our system, it looks like the base
871228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   for the system calls is 4000.
881228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl */
89f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesint
90929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatasyscall_p(struct process *proc, int status, int *sysnum)
91929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{
921228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl	if (WIFSTOPPED(status)
933e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes			&& WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
943e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		/* get the user's pc (plus 8) */
953e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		long pc = (long)get_instruction_pointer(proc);
963e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		/* fetch the SWI instruction */
973e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
983e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		int num = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 8, 0);
993e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes
1003e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		/*
10132ea1b1eaad1a07a120811bca9dd9f3524cc9256Oliver Spornitz		   On a mips,  syscall looks like:
1023e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		   24040fa1    li v0, 0x0fa1   # 4001 --> _exit syscall
1033e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		   0000000c    syscall
1043e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		 */
1053e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		if(insn!=0x0000000c){
1063e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes			return 0;
1073e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		}
1083e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes
1093e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		*sysnum = (num & 0xFFFF) - 4000;
1103e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		/* if it is a syscall, return 1 or 2 */
1113e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		if (proc->callstack_depth > 0 &&
1123e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes				proc->callstack[proc->callstack_depth - 1].is_syscall &&
1133e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes				proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) {
1143e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes			return 2;
1153e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		}
1163e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes
1173e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		if (*sysnum >= 0) {
1183e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes			return 1;
1193e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		}
1203e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes	}
1211228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl	return 0;
1221228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl}
123addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
124addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias/* Based on GDB code.  */
125addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define mips32_op(x) (x >> 26)
126addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define itype_op(x) (x >> 26)
127addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define itype_rs(x) ((x >> 21) & 0x1f)
128addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define itype_rt(x) ((x >> 16) & 0x1f)
129addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define itype_immediate(x) (x & 0xffff)
130addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
131addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define jtype_op(x) (x >> 26)
132addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define jtype_target(x) (x & 0x03ffffff)
133addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
134addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define rtype_op(x) (x >> 26)
135addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define rtype_rs(x) ((x >> 21) & 0x1f)
136addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define rtype_rt(x) ((x >> 16) & 0x1f)
137addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define rtype_rd(x) ((x >> 11) & 0x1f)
138addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define rtype_shamt(x) ((x >> 6) & 0x1f)
139addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias#define rtype_funct(x) (x & 0x3f)
140addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
141addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesiasstatic int32_t
142addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesiasmips32_relative_offset (uint32_t inst)
143addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias{
1440b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias  return ((itype_immediate(inst) ^ 0x8000) - 0x8000) << 2;
145addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias}
146addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
147929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataint mips_next_pcs(struct process *proc, uint32_t pc, uint32_t *newpc)
148addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias{
149addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	uint32_t inst, rx;
150addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	int op;
151addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	int rn;
152addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	int nr = 0;
153addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
154addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	inst = ptrace(PTRACE_PEEKTEXT, proc->pid, pc, 0);
155addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
156addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	if ((inst & 0xe0000000) != 0) {
157addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		/* Check for branches.  */
1580b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias		if (itype_op(inst) >> 2 == 5) {
159addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
1600b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias			op = (itype_op(inst) & 0x03);
161addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			switch (op)
162addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			{
163addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			case 0:	/* BEQL */
164addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			case 1: /* BNEL */
165addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			case 2:	/* BLEZL */
166addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			case 3:	/* BGTZL */
167addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				newpc[nr++] = pc + 8;
168addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				newpc[nr++] = pc + 4 +
1690b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias					mips32_relative_offset(inst);
170addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				break;
171addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			default:
172addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				newpc[nr++] = pc + 4;
173addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				break;
174addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			}
1750b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias		} else if (itype_op(inst) == 17 && itype_rs(inst) == 8) {
176addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			/* Step over the branch.  */
177addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			newpc[nr++] = pc + 8;
1780b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias			newpc[nr++] = pc + mips32_relative_offset(inst) + 4;
179addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		} else {
180addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			newpc[nr++] = pc + 4;
181addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		}
182addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	} else {
183addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		/* Further subdivide into SPECIAL, REGIMM and other.  */
1840b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias		switch (op = itype_op(inst) & 0x07)
185addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		{
186addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		case 0:
1870b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias			op = rtype_funct(inst);
188addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			switch (op)
189addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			{
190addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			case 8:	/* JR  */
191addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			case 9:	/* JALR  */
1920b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias				rn = rtype_rs(inst);
193addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
194addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				rx = ptrace(PTRACE_PEEKUSER,proc->pid, rn, 0);
195addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				newpc[nr++] = rx;
196addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				break;
197addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			default:
198addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			case 12:	/* SYSCALL  */
199addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				newpc[nr++] = pc + 4;
200addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				break;
201addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			}
202addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			break;
203addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		case 1:
2040b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias			op = itype_rt(inst);
205addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			switch (op)
206addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			{
207addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				case 0:
208addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				case 1:
209addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				case 2:
210addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				case 3:
211addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				case 16:
212addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				case 17:
213addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				case 18:
214addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				case 19:
215addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias					newpc[nr++] = pc + 8;
216addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias					newpc[nr++] = pc + 4 +
217addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias						mips32_relative_offset(inst);
218addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias					break;
219addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias				default:
220addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias					newpc[nr++] = pc + 4;
221addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias					break;
222addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			}
223addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			break;
224addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		case 2:	/* J  */
225addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		case 3:	/* JAL  */
2260b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias			rx = jtype_target(inst) << 2;
227addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			/* Upper four bits get never changed...  */
228addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			newpc[nr++] = rx + ((pc + 4) & ~0x0fffffff);
229addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			break;
230c44ef1ea84927851ddd74abff9a6374a62978caeEdgar E. Iglesias		case 4: /* BEQ  */
231c44ef1ea84927851ddd74abff9a6374a62978caeEdgar E. Iglesias			if (itype_rs(inst) == itype_rt(inst)) {
232c44ef1ea84927851ddd74abff9a6374a62978caeEdgar E. Iglesias				/* Compare the same reg for equality, always
233c44ef1ea84927851ddd74abff9a6374a62978caeEdgar E. Iglesias				 * follow the branch.  */
234c44ef1ea84927851ddd74abff9a6374a62978caeEdgar E. Iglesias				newpc[nr++] = pc + 4 +
235c44ef1ea84927851ddd74abff9a6374a62978caeEdgar E. Iglesias					mips32_relative_offset(inst);
236c44ef1ea84927851ddd74abff9a6374a62978caeEdgar E. Iglesias				break;
237c44ef1ea84927851ddd74abff9a6374a62978caeEdgar E. Iglesias			}
238c44ef1ea84927851ddd74abff9a6374a62978caeEdgar E. Iglesias			/* Fall through.  */
239addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		default:
240addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		case 5:
241addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		case 6:
242addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		case 7:
243addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			/* Step over the branch.  */
244addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			newpc[nr++] = pc + 8;
2450b02a93aff5808b7640299faedfeb697485fd170Edgar E. Iglesias			newpc[nr++] = pc + mips32_relative_offset(inst) + 4;
246addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			break;
247addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		}
248addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	}
249addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	if (nr <= 0 || nr > 2)
250addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		goto fail;
251addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	if (nr == 2) {
252addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		if (newpc[1] == 0)
253addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			goto fail;
254addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	}
255addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	if (newpc[0] == 0)
256addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		goto fail;
257addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
258addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	assert(nr == 1 || nr == 2);
259addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	return nr;
260addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
261addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesiasfail:
262addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	printf("nr=%d pc=%x\n", nr, pc);
263addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	printf("pc=%x %x\n", newpc[0], newpc[1]);
264addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	return 0;
265addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias}
266addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
267693dfad9c1b121cf079a3082866daa2225df1797Petr Machataenum sw_singlestep_status
268693dfad9c1b121cf079a3082866daa2225df1797Petr Machataarch_sw_singlestep(struct process *proc, struct breakpoint *bp,
269693dfad9c1b121cf079a3082866daa2225df1797Petr Machata		   int (*add_cb)(arch_addr_t, struct sw_singlestep_data *),
270693dfad9c1b121cf079a3082866daa2225df1797Petr Machata		   struct sw_singlestep_data *add_cb_data)
271addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias{
272addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	uint32_t pc = (uint32_t) get_instruction_pointer(proc);
273addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	uint32_t newpcs[2];
274addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	int nr;
275addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
276addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	nr = mips_next_pcs(proc, pc, newpcs);
277addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
278addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	while (nr-- > 0) {
279addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		arch_addr_t baddr = (arch_addr_t) newpcs[nr];
280addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		/* Not sure what to do here. We've already got a bp?  */
281273890e09616b8fe0b9b015ea8edda12c52d4ba2Petr Machata		if (DICT_HAS_KEY(proc->leader->breakpoints, &baddr)) {
282addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			fprintf(stderr, "skip %p %p\n", baddr, add_cb_data);
283addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias			continue;
284addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		}
285addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
286addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias		if (add_cb(baddr, add_cb_data) < 0)
287693dfad9c1b121cf079a3082866daa2225df1797Petr Machata			return SWS_FAIL;
288addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	}
289addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
290addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias	ptrace(PTRACE_SYSCALL, proc->pid, 0, 0);
291693dfad9c1b121cf079a3082866daa2225df1797Petr Machata	return SWS_OK;
292addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias}
293addae05da54ac16c55133e1c384d74e03346f634Edgar E. Iglesias
2941228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl/**
2951228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   \param type Function/syscall call or return.
2961228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   \param proc The process that had an event.
297fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes   \param arg_num -1 for return value,
298fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes   \return The argument to fetch.
2991228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
300fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes   A couple of assumptions.
3011228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
3021228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl-  Type is LT_TOF_FUNCTIONR or LT_TOF_SYSCALLR if arg_num==-1. These
3031228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   types are only used in calls for output_right(), which only uses -1
3041228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   for arg_num.
305fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes-  Type is LT_TOF_FUNCTION or LT_TOF_SYSCALL for args 0...4.
3061228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl-   I'm only displaying the first 4 args (Registers a0..a3). Good
3071228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl   enough for now.
3081228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
30932ea1b1eaad1a07a120811bca9dd9f3524cc9256Oliver Spornitz  Mips conventions seem to be:
3101228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl- syscall parameters: r4...r9
3111228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl- syscall return: if(!a3){ return v0;} else{ errno=v0;return -1;}
312fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes- function call: r4..r7. Not sure how to get arg number 5.
3131228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl- function return: v0
3141228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
3151228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric VaitlThe argument registers are wiped by a call, so it is a mistake to ask
3161228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitlfor arguments on a return. If ltrace does this, we will need to cache
3171228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitlarguments somewhere on the call.
3181228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
319fea4a1285dc7bea02b0203845ad43117f091fc3eJuan CespedesI'm not doing any floating point support here.
3201228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
3211228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl*/
322f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedeslong
323929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatagimme_arg(enum tof type, struct process *proc, int arg_num,
324929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata	  struct arg_type_info *info)
325000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
3263e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes	long ret;
3278a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard	long addr;
3283e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes	debug(2,"type %d arg %d",type,arg_num);
3298a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard	if (arg_num == -1) {
3308a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		if(type == LT_TOF_FUNCTIONR) {
3318a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			return  ptrace(PTRACE_PEEKUSER,proc->pid,off_v0,0);
3328a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		}
3338a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		if (type == LT_TOF_SYSCALLR) {
3348a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			unsigned a3=ptrace(PTRACE_PEEKUSER, proc->pid,off_a3,0);
3358a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			unsigned v0=ptrace(PTRACE_PEEKUSER, proc->pid,off_v0,0);
3368a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			if(!a3){
3378a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard				return v0;
3388a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			}
3398a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			return -1;
3408a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		}
3418a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard	}
3428a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard	if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL) {
3438a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		/* o32: float args are in f12 and f14 */
3448a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		if ((info->type == ARGTYPE_FLOAT) && (arg_num < 2)) {
3458a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			ret=ptrace(PTRACE_PEEKUSER,proc->pid,off_fpr0+12+arg_num*2,0);
3468a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			debug(2,"ret = %#lx",ret);
3478a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			return ret;
3488a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		}
3493e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		if(arg_num <4){
3503e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes			ret=ptrace(PTRACE_PEEKUSER,proc->pid,off_a0+arg_num,0);
3513e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes			debug(2,"ret = %#lx",ret);
3523e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes			return ret;
3533e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		} else {
3548a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			/* not sure it's going to work for something else than syscall */
3558a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			addr=ptrace(PTRACE_PEEKUSER,proc->pid,off_sp,0);
3568a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			if (addr == -1) {
3578a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard				debug(2,"ret = %#lx",addr);
3588a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard				return addr;
3598a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			}
3608a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			ret = addr + 4*arg_num;
3618a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			ret=ptrace(PTRACE_PEEKTEXT,proc->pid,addr,0);
3628a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			debug(2,"ret = %#lx",ret);
3638a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			return ret;
3643e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		}
365fea4a1285dc7bea02b0203845ad43117f091fc3eJuan Cespedes	}
3668a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard	if (type == LT_TOF_FUNCTIONR || type == LT_TOF_SYSCALLR){
3678a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		addr=ptrace(PTRACE_PEEKUSER,proc->pid,off_sp,0);
3688a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		if (addr == -1) {
3698a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			debug(2,"ret = %#lx",addr);
3708a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard			return addr;
3713e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes		}
3728a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		ret = addr + 4*arg_num;
3738a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		ret=ptrace(PTRACE_PEEKTEXT,proc->pid,addr,0);
3748a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		debug(2,"ret = %#lx",ret);
3758a115b6cedaf530e4589e6dc190bfb70b2c2619aArnaud Patard		return ret;
3763e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes	}
3773e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes	fprintf(stderr, "gimme_arg called with wrong arguments\n");
3781228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl	return 0;
3791228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl}
3801228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl
3811228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl/**@}*/
382