Home | History | Annotate | Download | only in mips
      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  */
     67 void
     68 get_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  */
     89 int
     90 syscall_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 
    141 static int32_t
    142 mips32_relative_offset (uint32_t inst)
    143 {
    144   return ((itype_immediate(inst) ^ 0x8000) - 0x8000) << 2;
    145 }
    146 
    147 int 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 
    261 fail:
    262 	printf("nr=%d pc=%x\n", nr, pc);
    263 	printf("pc=%x %x\n", newpc[0], newpc[1]);
    264 	return 0;
    265 }
    266 
    267 enum sw_singlestep_status
    268 arch_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_HAS_KEY(proc->leader->breakpoints, &baddr)) {
    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 
    315 The argument registers are wiped by a call, so it is a mistake to ask
    316 for arguments on a return. If ltrace does this, we will need to cache
    317 arguments somewhere on the call.
    318 
    319 I'm not doing any floating point support here.
    320 
    321 */
    322 long
    323 gimme_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