blob: c65f9ec1d9afde05461f9536d42f3285daa30bb2 [file] [log] [blame]
Eric Vaitl1228a912006-12-28 16:16:56 +01001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <sys/types.h>
6#include <sys/wait.h>
7#include <signal.h>
8#include <sys/ptrace.h>
9#include <asm/ptrace.h>
10#include "debug.h"
11#include "ltrace.h"
12#include "mipsel.h"
13#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
14# define PTRACE_PEEKUSER PTRACE_PEEKUSR
15#endif
16
17#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
18# define PTRACE_POKEUSER PTRACE_POKEUSR
19#endif
20
21
22/**
23 \addtogroup mipsel Mipsel specific functions.
24
25 These are the functions that it looks like I need to implement in
26 order to get ltrace to work on our target.
27
28 @{
29 */
30
31/**
32 \param proc The process that had an event.
33
34 Called by \c wait_for_something() right after the return from wait.
35
36 Most targets just return here. A couple use proc->arch_ptr for a
37 private data area.
38 */
Juan Cespedesf1350522008-12-16 18:19:58 +010039void
40get_arch_dep(struct process *proc) {
Eric Vaitl1228a912006-12-28 16:16:56 +010041}
42
43/**
44 \param proc Process that had event.
45 \param status From \c wait()
46 \param sysnum 0-based syscall number.
47 \return 1 if syscall, 2 if sysret, 0 otherwise.
48
49 Called by \c wait_for_something() after the call to get_arch_dep()
50
51 It seems that the ptrace call trips twice on a system call, once
52 just before the system call and once when it returns. Both times,
53 the pc points at the instruction just after the mipsel "syscall"
54 instruction.
55
56 There are several possiblities for system call sets, each is offset
57 by a base from the others. On our system, it looks like the base
58 for the system calls is 4000.
59 */
Juan Cespedesf1350522008-12-16 18:19:58 +010060int
61syscall_p(struct process *proc, int status, int *sysnum) {
Eric Vaitl1228a912006-12-28 16:16:56 +010062 if (WIFSTOPPED(status)
63 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
64 /* get the user's pc (plus 8) */
65 long pc = (long)get_instruction_pointer(proc);
66 /* fetch the SWI instruction */
67 int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
68 int num = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 8, 0);
69
70/*
71 On a mipsel, syscall looks like:
72 24040fa1 li v0, 0x0fa1 # 4001 --> _exit syscall
73 0000000c syscall
74 */
75 if(insn!=0x0000000c){
76 return 0;
77 }
78
79 *sysnum = (num & 0xFFFF) - 4000;
80 /* if it is a syscall, return 1 or 2 */
81 if (proc->callstack_depth > 0 &&
82 proc->callstack[proc->callstack_depth - 1].is_syscall) {
83 return 2;
84 }
85
86 if (*sysnum >= 0) {
87 return 1;
88 }
89 }
90 return 0;
91}
92/**
93 \param type Function/syscall call or return.
94 \param proc The process that had an event.
95 \param arg_num -1 for return value,
96 \return The argument to fetch.
97
98 A couple of assumptions.
99
100- Type is LT_TOF_FUNCTIONR or LT_TOF_SYSCALLR if arg_num==-1. These
101 types are only used in calls for output_right(), which only uses -1
102 for arg_num.
103- Type is LT_TOF_FUNCTION or LT_TOF_SYSCALL for args 0...4.
104- I'm only displaying the first 4 args (Registers a0..a3). Good
105 enough for now.
106
107 Mipsel conventions seem to be:
108- syscall parameters: r4...r9
109- syscall return: if(!a3){ return v0;} else{ errno=v0;return -1;}
110- function call: r4..r7. Not sure how to get arg number 5.
111- function return: v0
112
113The argument registers are wiped by a call, so it is a mistake to ask
114for arguments on a return. If ltrace does this, we will need to cache
115arguments somewhere on the call.
116
117I'm not doing any floating point support here.
118
119*/
Juan Cespedesf1350522008-12-16 18:19:58 +0100120long
121gimme_arg(enum tof type, struct process *proc, int arg_num, arg_type_info *info) {
Eric Vaitl1228a912006-12-28 16:16:56 +0100122 long ret;
123 debug(2,"type %d arg %d",type,arg_num);
124 if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL){
125 if(arg_num <4){
126 ret=ptrace(PTRACE_PEEKUSER,proc->pid,off_a0+arg_num,0);
127 debug(2,"ret = %#lx",ret);
128 return ret;
129 } else {
130 // If we need this, I think we can look at [sp+16] for arg_num==4.
131 CP;
132 return 0;
133 }
134 }
135 if(arg_num>=0){
136 fprintf(stderr,"args on return?");
137 }
138 if(type == LT_TOF_FUNCTIONR) {
139 return ptrace(PTRACE_PEEKUSER,proc->pid,off_v0,0);
140 }
141 if (type == LT_TOF_SYSCALLR) {
142 unsigned a3=ptrace(PTRACE_PEEKUSER, proc->pid,off_a3,0);
143 unsigned v0=ptrace(PTRACE_PEEKUSER, proc->pid,off_v0,0);
144 if(!a3){
145 return v0;
146 }
147 return -1;
148 }
149 fprintf(stderr, "gimme_arg called with wrong arguments\n");
150 return 0;
151}
152
153/**
154 \param type Type of call/return
155 \param proc Process to work with.
156
157 Called by \c output_left(), which is called on a syscall or
158 function.
159
160 The other architectures stub this out, but seems to be the place to
161 stash off the arguments on a call so we have them on the return.
162
163*/
Juan Cespedesf1350522008-12-16 18:19:58 +0100164void
165save_register_args(enum tof type, struct process *proc) {
Eric Vaitl1228a912006-12-28 16:16:56 +0100166}
167
168/**@}*/