trace.c revision d7e4ca82e1cf20bb2605befb1da74dd1688c706e
1/*
2 * This file is part of ltrace.
3 * Copyright (C) 2013 Petr Machata, Red Hat Inc.
4 * Copyright (C) 2012 Edgar E. Iglesias, Axis Communications
5 * Copyright (C) 2010 Arnaud Patard, Mandriva SA
6 * Copyright (C) 2008,2009 Juan Cespedes
7 * Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
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/wait.h>
29#include <signal.h>
30#include <sys/ptrace.h>
31#include <asm/ptrace.h>
32#include <assert.h>
33
34#include "backend.h"
35#include "common.h"
36#include "debug.h"
37#include "mips.h"
38#include "proc.h"
39#include "type.h"
40
41#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
42# define PTRACE_PEEKUSER PTRACE_PEEKUSR
43#endif
44
45#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
46# define PTRACE_POKEUSER PTRACE_POKEUSR
47#endif
48
49
50/**
51   \addtogroup mips Mips specific functions.
52
53   These are the functions that it looks like I need to implement in
54   order to get ltrace to work on our target.
55
56   @{
57 */
58
59/**
60   \param proc The process that had an event.
61
62   Called by \c next_event() right after the return from wait.
63
64   Most targets just return here. A couple use proc->arch_ptr for a
65   private data area.
66 */
67void
68get_arch_dep(struct process *proc)
69{
70}
71
72/**
73   \param proc Process that had event.
74   \param status From \c wait()
75   \param sysnum 0-based syscall number.
76   \return 1 if syscall, 2 if sysret, 0 otherwise.
77
78   Called by \c next_event() after the call to get_arch_dep()
79
80   It seems that the ptrace call trips twice on a system call, once
81   just before the system call and once when it returns. Both times,
82   the pc points at the instruction just after the mips "syscall"
83   instruction.
84
85   There are several possiblities for system call sets, each is offset
86   by a base from the others. On our system, it looks like the base
87   for the system calls is 4000.
88 */
89int
90syscall_p(struct process *proc, int status, int *sysnum)
91{
92	if (WIFSTOPPED(status)
93			&& WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
94		/* get the user's pc (plus 8) */
95		long pc = (long)get_instruction_pointer(proc);
96		/* fetch the SWI instruction */
97		int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
98		int num = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 8, 0);
99
100		/*
101		   On a mips,  syscall looks like:
102		   24040fa1    li v0, 0x0fa1   # 4001 --> _exit syscall
103		   0000000c    syscall
104		 */
105		if(insn!=0x0000000c){
106			return 0;
107		}
108
109		*sysnum = (num & 0xFFFF) - 4000;
110		/* if it is a syscall, return 1 or 2 */
111		if (proc->callstack_depth > 0 &&
112				proc->callstack[proc->callstack_depth - 1].is_syscall &&
113				proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) {
114			return 2;
115		}
116
117		if (*sysnum >= 0) {
118			return 1;
119		}
120	}
121	return 0;
122}
123
124/* Based on GDB code.  */
125#define mips32_op(x) (x >> 26)
126#define itype_op(x) (x >> 26)
127#define itype_rs(x) ((x >> 21) & 0x1f)
128#define itype_rt(x) ((x >> 16) & 0x1f)
129#define itype_immediate(x) (x & 0xffff)
130
131#define jtype_op(x) (x >> 26)
132#define jtype_target(x) (x & 0x03ffffff)
133
134#define rtype_op(x) (x >> 26)
135#define rtype_rs(x) ((x >> 21) & 0x1f)
136#define rtype_rt(x) ((x >> 16) & 0x1f)
137#define rtype_rd(x) ((x >> 11) & 0x1f)
138#define rtype_shamt(x) ((x >> 6) & 0x1f)
139#define rtype_funct(x) (x & 0x3f)
140
141static int32_t
142mips32_relative_offset (uint32_t inst)
143{
144  return ((itype_immediate(inst) ^ 0x8000) - 0x8000) << 2;
145}
146
147int mips_next_pcs(struct process *proc, uint32_t pc, uint32_t *newpc)
148{
149	uint32_t inst, rx;
150	int op;
151	int rn;
152	int nr = 0;
153
154	inst = ptrace(PTRACE_PEEKTEXT, proc->pid, pc, 0);
155
156	if ((inst & 0xe0000000) != 0) {
157		/* Check for branches.  */
158		if (itype_op(inst) >> 2 == 5) {
159			/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
160			op = (itype_op(inst) & 0x03);
161			switch (op)
162			{
163			case 0:	/* BEQL */
164			case 1: /* BNEL */
165			case 2:	/* BLEZL */
166			case 3:	/* BGTZL */
167				newpc[nr++] = pc + 8;
168				newpc[nr++] = pc + 4 +
169					mips32_relative_offset(inst);
170				break;
171			default:
172				newpc[nr++] = pc + 4;
173				break;
174			}
175		} else if (itype_op(inst) == 17 && itype_rs(inst) == 8) {
176			/* Step over the branch.  */
177			newpc[nr++] = pc + 8;
178			newpc[nr++] = pc + mips32_relative_offset(inst) + 4;
179		} else {
180			newpc[nr++] = pc + 4;
181		}
182	} else {
183		/* Further subdivide into SPECIAL, REGIMM and other.  */
184		switch (op = itype_op(inst) & 0x07)
185		{
186		case 0:
187			op = rtype_funct(inst);
188			switch (op)
189			{
190			case 8:	/* JR  */
191			case 9:	/* JALR  */
192				rn = rtype_rs(inst);
193
194				rx = ptrace(PTRACE_PEEKUSER,proc->pid, rn, 0);
195				newpc[nr++] = rx;
196				break;
197			default:
198			case 12:	/* SYSCALL  */
199				newpc[nr++] = pc + 4;
200				break;
201			}
202			break;
203		case 1:
204			op = itype_rt(inst);
205			switch (op)
206			{
207				case 0:
208				case 1:
209				case 2:
210				case 3:
211				case 16:
212				case 17:
213				case 18:
214				case 19:
215					newpc[nr++] = pc + 8;
216					newpc[nr++] = pc + 4 +
217						mips32_relative_offset(inst);
218					break;
219				default:
220					newpc[nr++] = pc + 4;
221					break;
222			}
223			break;
224		case 2:	/* J  */
225		case 3:	/* JAL  */
226			rx = jtype_target(inst) << 2;
227			/* Upper four bits get never changed...  */
228			newpc[nr++] = rx + ((pc + 4) & ~0x0fffffff);
229			break;
230		case 4: /* BEQ  */
231			if (itype_rs(inst) == itype_rt(inst)) {
232				/* Compare the same reg for equality, always
233				 * follow the branch.  */
234				newpc[nr++] = pc + 4 +
235					mips32_relative_offset(inst);
236				break;
237			}
238			/* Fall through.  */
239		default:
240		case 5:
241		case 6:
242		case 7:
243			/* Step over the branch.  */
244			newpc[nr++] = pc + 8;
245			newpc[nr++] = pc + mips32_relative_offset(inst) + 4;
246			break;
247		}
248	}
249	if (nr <= 0 || nr > 2)
250		goto fail;
251	if (nr == 2) {
252		if (newpc[1] == 0)
253			goto fail;
254	}
255	if (newpc[0] == 0)
256		goto fail;
257
258	assert(nr == 1 || nr == 2);
259	return nr;
260
261fail:
262	printf("nr=%d pc=%x\n", nr, pc);
263	printf("pc=%x %x\n", newpc[0], newpc[1]);
264	return 0;
265}
266
267enum sw_singlestep_status
268arch_sw_singlestep(struct process *proc, struct breakpoint *bp,
269		   int (*add_cb)(arch_addr_t, struct sw_singlestep_data *),
270		   struct sw_singlestep_data *add_cb_data)
271{
272	uint32_t pc = (uint32_t) get_instruction_pointer(proc);
273	uint32_t newpcs[2];
274	int nr;
275
276	nr = mips_next_pcs(proc, pc, newpcs);
277
278	while (nr-- > 0) {
279		arch_addr_t baddr = (arch_addr_t) newpcs[nr];
280		/* Not sure what to do here. We've already got a bp?  */
281		if (dict_find(proc->leader->breakpoints, &baddr) != NULL) {
282			fprintf(stderr, "skip %p %p\n", baddr, add_cb_data);
283			continue;
284		}
285
286		if (add_cb(baddr, add_cb_data) < 0)
287			return SWS_FAIL;
288	}
289
290	ptrace(PTRACE_SYSCALL, proc->pid, 0, 0);
291	return SWS_OK;
292}
293
294/**
295   \param type Function/syscall call or return.
296   \param proc The process that had an event.
297   \param arg_num -1 for return value,
298   \return The argument to fetch.
299
300   A couple of assumptions.
301
302-  Type is LT_TOF_FUNCTIONR or LT_TOF_SYSCALLR if arg_num==-1. These
303   types are only used in calls for output_right(), which only uses -1
304   for arg_num.
305-  Type is LT_TOF_FUNCTION or LT_TOF_SYSCALL for args 0...4.
306-   I'm only displaying the first 4 args (Registers a0..a3). Good
307   enough for now.
308
309  Mips conventions seem to be:
310- syscall parameters: r4...r9
311- syscall return: if(!a3){ return v0;} else{ errno=v0;return -1;}
312- function call: r4..r7. Not sure how to get arg number 5.
313- function return: v0
314
315The argument registers are wiped by a call, so it is a mistake to ask
316for arguments on a return. If ltrace does this, we will need to cache
317arguments somewhere on the call.
318
319I'm not doing any floating point support here.
320
321*/
322long
323gimme_arg(enum tof type, struct process *proc, int arg_num,
324	  struct arg_type_info *info)
325{
326	long ret;
327	long addr;
328	debug(2,"type %d arg %d",type,arg_num);
329	if (arg_num == -1) {
330		if(type == LT_TOF_FUNCTIONR) {
331			return  ptrace(PTRACE_PEEKUSER,proc->pid,off_v0,0);
332		}
333		if (type == LT_TOF_SYSCALLR) {
334			unsigned a3=ptrace(PTRACE_PEEKUSER, proc->pid,off_a3,0);
335			unsigned v0=ptrace(PTRACE_PEEKUSER, proc->pid,off_v0,0);
336			if(!a3){
337				return v0;
338			}
339			return -1;
340		}
341	}
342	if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL) {
343		/* o32: float args are in f12 and f14 */
344		if ((info->type == ARGTYPE_FLOAT) && (arg_num < 2)) {
345			ret=ptrace(PTRACE_PEEKUSER,proc->pid,off_fpr0+12+arg_num*2,0);
346			debug(2,"ret = %#lx",ret);
347			return ret;
348		}
349		if(arg_num <4){
350			ret=ptrace(PTRACE_PEEKUSER,proc->pid,off_a0+arg_num,0);
351			debug(2,"ret = %#lx",ret);
352			return ret;
353		} else {
354			/* not sure it's going to work for something else than syscall */
355			addr=ptrace(PTRACE_PEEKUSER,proc->pid,off_sp,0);
356			if (addr == -1) {
357				debug(2,"ret = %#lx",addr);
358				return addr;
359			}
360			ret = addr + 4*arg_num;
361			ret=ptrace(PTRACE_PEEKTEXT,proc->pid,addr,0);
362			debug(2,"ret = %#lx",ret);
363			return ret;
364		}
365	}
366	if (type == LT_TOF_FUNCTIONR || type == LT_TOF_SYSCALLR){
367		addr=ptrace(PTRACE_PEEKUSER,proc->pid,off_sp,0);
368		if (addr == -1) {
369			debug(2,"ret = %#lx",addr);
370			return addr;
371		}
372		ret = addr + 4*arg_num;
373		ret=ptrace(PTRACE_PEEKTEXT,proc->pid,addr,0);
374		debug(2,"ret = %#lx",ret);
375		return ret;
376	}
377	fprintf(stderr, "gimme_arg called with wrong arguments\n");
378	return 0;
379}
380
381/**@}*/
382