trace.c revision 1b9cfd6ad305ad909e8ff17139111a7c78f01464
1#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 11#include "ltrace.h" 12 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/* syscall tracing protocol: ArmLinux 22 on the way in, ip is 0 23 on the way out, ip is non-zero 24*/ 25#define off_r0 0 26#define off_ip 48 27#define off_pc 60 28 29/* Returns 1 if syscall, 2 if sysret, 0 otherwise. 30 */ 31int syscall_p(struct process * proc, int status, int * sysnum) 32{ 33 if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP) { 34 /* get the user's pc (plus 8) */ 35 int pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0); 36 /* fetch the SWI instruction */ 37 int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc-4, 0) ; 38 39 *sysnum = insn & 0xFFFF; 40 /* if it is a syscall, return 1 or 2 */ 41 if ((insn & 0xFFFF0000) == 0xef900000) { 42 return ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, 0) ? 2 : 1; 43 } 44 } 45 return 0; 46} 47 48 49void continue_after_breakpoint(struct process *proc, struct breakpoint * sbp, int delete_it) 50{ 51 delete_breakpoint(proc->pid, sbp); 52 ptrace(PTRACE_POKEUSER, proc->pid, off_pc, sbp->addr); 53 if (delete_it) { 54 continue_process(proc->pid); 55 } else { 56 proc->breakpoint_being_enabled = sbp; 57 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0); 58 } 59} 60 61long gimme_arg(enum tof type, struct process * proc, int arg_num) 62{ 63 if (arg_num==-1) { /* return value */ 64 return ptrace(PTRACE_PEEKUSER, proc->pid, off_r0, 0); 65 } 66 67 /* deal with the ARM calling conventions */ 68 if (type==LT_TOF_FUNCTION) { 69 if (arg_num<4) { 70 return ptrace(PTRACE_PEEKUSER, proc->pid, 4*arg_num, 0); 71 } else { 72 return ptrace(PTRACE_PEEKDATA, proc->pid, proc->stack_pointer+4*(arg_num-4), 0); 73 } 74 } else if (type==LT_TOF_SYSCALL) { 75 if (arg_num<5) { 76 return ptrace(PTRACE_PEEKUSER, proc->pid, 4*arg_num, 0); 77 } else { 78 return ptrace(PTRACE_PEEKDATA, proc->pid, proc->stack_pointer+4*(arg_num-5), 0); 79 } 80 } else { 81 fprintf(stderr, "gimme_arg called with wrong arguments\n"); 82 exit(1); 83 } 84 85 return 0; 86} 87 88int umovestr(struct process * proc, void * addr, int len, void * laddr) 89{ 90 long a; 91 int i; 92 int offset=0; 93 94 while(offset<len) { 95 a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr+offset, 0); 96 for(i=0; i<sizeof(long); i++) { 97 if (((char*)&a)[i] && offset+i < len) { 98 *(char *)(laddr+offset+i) = ((char*)&a)[i]; 99 } else { 100 *(char *)(laddr+offset+i) = '\0'; 101 return 0; 102 } 103 } 104 offset += sizeof(long); 105 } 106 *(char *)(laddr+offset) = '\0'; 107 return 0; 108} 109