trace.c revision 97f13e3fca546aa292ba5d8aa6011338e64f2f7a
1#include "config.h" 2 3#include <string.h> 4#include <sys/types.h> 5#include <sys/wait.h> 6#include <signal.h> 7#include <sys/ptrace.h> 8#include <asm/ptrace.h> 9 10#include "proc.h" 11#include "common.h" 12#include "output.h" 13#include "ptrace.h" 14 15#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR)) 16# define PTRACE_PEEKUSER PTRACE_PEEKUSR 17#endif 18 19#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR)) 20# define PTRACE_POKEUSER PTRACE_POKEUSR 21#endif 22 23#define off_r0 ((void *)0) 24#define off_r7 ((void *)28) 25#define off_ip ((void *)48) 26#define off_pc ((void *)60) 27 28void 29get_arch_dep(Process *proc) { 30 proc_archdep *a; 31 32 if (!proc->arch_ptr) 33 proc->arch_ptr = (void *)malloc(sizeof(proc_archdep)); 34 a = (proc_archdep *) (proc->arch_ptr); 35 a->valid = (ptrace(PTRACE_GETREGS, proc->pid, 0, &a->regs) >= 0); 36} 37 38/* Returns 0 if not a syscall, 39 * 1 if syscall entry, 2 if syscall exit, 40 * 3 if arch-specific syscall entry, 4 if arch-specific syscall exit, 41 * -1 on error. 42 */ 43int 44syscall_p(Process *proc, int status, int *sysnum) { 45 if (WIFSTOPPED(status) 46 && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 47 /* get the user's pc (plus 8) */ 48 unsigned pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0); 49 pc = pc - 4; 50 /* fetch the SWI instruction */ 51 unsigned insn = ptrace(PTRACE_PEEKTEXT, proc->pid, 52 (void *)pc, 0); 53 int ip = ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, 0); 54 55 if (insn == 0xef000000 || insn == 0x0f000000 56 || (insn & 0xffff0000) == 0xdf000000) { 57 /* EABI syscall */ 58 *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, off_r7, 0); 59 } else if ((insn & 0xfff00000) == 0xef900000) { 60 /* old ABI syscall */ 61 *sysnum = insn & 0xfffff; 62 } else { 63 /* TODO: handle swi<cond> variations */ 64 /* one possible reason for getting in here is that we 65 * are coming from a signal handler, so the current 66 * PC does not point to the instruction just after the 67 * "swi" one. */ 68 output_line(proc, "unexpected instruction 0x%x at %p", 69 insn, pc); 70 return 0; 71 } 72 if ((*sysnum & 0xf0000) == 0xf0000) { 73 /* arch-specific syscall */ 74 *sysnum &= ~0xf0000; 75 return ip ? 4 : 3; 76 } 77 /* ARM syscall convention: on syscall entry, ip is zero; 78 * on syscall exit, ip is non-zero */ 79 return ip ? 2 : 1; 80 } 81 return 0; 82} 83 84long 85gimme_arg(enum tof type, Process *proc, int arg_num, struct arg_type_info *info) 86{ 87 proc_archdep *a = (proc_archdep *) proc->arch_ptr; 88 89 if (arg_num == -1) { /* return value */ 90 return ptrace(PTRACE_PEEKUSER, proc->pid, off_r0, 0); 91 } 92 93 /* deal with the ARM calling conventions */ 94 if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) { 95 if (arg_num < 4) { 96 if (a->valid && type == LT_TOF_FUNCTION) 97 return a->regs.uregs[arg_num]; 98 if (a->valid && type == LT_TOF_FUNCTIONR) 99 return a->func_arg[arg_num]; 100 return ptrace(PTRACE_PEEKUSER, proc->pid, 101 (void *)(4 * arg_num), 0); 102 } else { 103 return ptrace(PTRACE_PEEKDATA, proc->pid, 104 proc->stack_pointer + 4 * (arg_num - 4), 105 0); 106 } 107 } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) { 108 if (arg_num < 5) { 109 if (a->valid && type == LT_TOF_SYSCALL) 110 return a->regs.uregs[arg_num]; 111 if (a->valid && type == LT_TOF_SYSCALLR) 112 return a->sysc_arg[arg_num]; 113 return ptrace(PTRACE_PEEKUSER, proc->pid, 114 (void *)(4 * arg_num), 0); 115 } else { 116 return ptrace(PTRACE_PEEKDATA, proc->pid, 117 proc->stack_pointer + 4 * (arg_num - 5), 118 0); 119 } 120 } else { 121 fprintf(stderr, "gimme_arg called with wrong arguments\n"); 122 exit(1); 123 } 124 125 return 0; 126} 127