trace.c revision 9a2ad351a1c3215dc596ff3e2e3fd4bc24445a6b
1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <errno.h> 5#include <unistd.h> 6#include <sys/types.h> 7#include "ptrace.h" 8#include <asm/unistd.h> 9 10#include "ltrace.h" 11#include "options.h" 12#include "sysdep.h" 13 14static int fork_exec_syscalls[][5] = { 15{ 16#ifdef __NR_fork 17 __NR_fork, 18#else 19 -1, 20#endif 21#ifdef __NR_clone 22 __NR_clone, 23#else 24 -1, 25#endif 26#ifdef __NR_clone2 27 __NR_clone2, 28#else 29 -1, 30#endif 31#ifdef __NR_vfork 32 __NR_vfork, 33#else 34 -1, 35#endif 36#ifdef __NR_execve 37 __NR_execve, 38#else 39 -1, 40#endif 41} 42#ifdef FORK_EXEC_SYSCALLS 43FORK_EXEC_SYSCALLS 44#endif 45}; 46 47/* Returns 1 if the sysnum may make a new child to be created 48 * (ie, with fork() or clone()) 49 * Returns 0 otherwise. 50 */ 51int 52fork_p(struct process * proc, int sysnum) { 53 int i; 54 if (proc->personality 55 >= sizeof fork_exec_syscalls / sizeof (fork_exec_syscalls [0])) 56 return 0; 57 for (i = 0; i < sizeof (fork_exec_syscalls[0]) / sizeof (int) - 1; ++i) 58 if (sysnum == fork_exec_syscalls[proc->personality][i]) 59 return 1; 60 return 0; 61} 62 63/* Returns 1 if the sysnum may make the process exec other program 64 */ 65int 66exec_p(struct process * proc, int sysnum) { 67 int i; 68 if (proc->personality 69 >= sizeof fork_exec_syscalls / sizeof (fork_exec_syscalls [0])) 70 return 0; 71 i = sizeof (fork_exec_syscalls[0]) / sizeof (int) - 1; 72 if (sysnum == fork_exec_syscalls[proc->personality][i]) 73 return 1; 74 return 0; 75} 76 77void 78trace_me(void) { 79 if (ptrace(PTRACE_TRACEME, 0, 1, 0)<0) { 80 perror("PTRACE_TRACEME"); 81 exit(1); 82 } 83} 84 85int 86trace_pid(pid_t pid) { 87 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) { 88 return -1; 89 } 90 return 0; 91} 92 93void 94trace_set_options(struct process * proc, pid_t pid) { 95#ifndef PTRACE_SETOPTIONS 96 #define PTRACE_SETOPTIONS 0x4200 97#endif 98#ifndef PTRACE_OLDSETOPTIONS 99 #define PTRACE_OLDSETOPTIONS 21 100#endif 101#ifndef PTRACE_O_TRACESYSGOOD 102 #define PTRACE_O_TRACESYSGOOD 0x00000001 103#endif 104 if (proc->tracesysgood & 0x80) 105 return; 106 if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0 && 107 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) { 108 perror("PTRACE_SETOPTIONS"); 109 return; 110 } 111 proc->tracesysgood |= 0x80; 112} 113 114void 115untrace_pid(pid_t pid) { 116 ptrace(PTRACE_DETACH, pid, 1, 0); 117} 118 119void 120continue_after_signal(pid_t pid, int signum) { 121 /* We should always trace syscalls to be able to control fork(), clone(), execve()... */ 122 ptrace(PTRACE_SYSCALL, pid, 0, signum); 123} 124 125void 126continue_process(pid_t pid) { 127 continue_after_signal(pid, 0); 128} 129 130void 131continue_enabling_breakpoint(pid_t pid, struct breakpoint * sbp) { 132 enable_breakpoint(pid, sbp); 133 continue_process(pid); 134} 135 136void 137continue_after_breakpoint(struct process *proc, struct breakpoint * sbp) { 138 if (sbp->enabled) disable_breakpoint(proc->pid, sbp); 139 set_instruction_pointer(proc, sbp->addr); 140 if (sbp->enabled == 0) { 141 continue_process(proc->pid); 142 } else { 143 proc->breakpoint_being_enabled = sbp; 144#if defined __sparc__ || defined __ia64___ 145 /* we don't want to singlestep here */ 146 continue_process(proc->pid); 147#else 148 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0); 149#endif 150 } 151} 152 153int 154umovestr(struct process * proc, void * addr, int len, void * laddr) { 155 union { long a; char c[sizeof(long)]; } a; 156 int i; 157 int offset=0; 158 159 while(offset<len) { 160 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr+offset, 0); 161 for(i=0; i<sizeof(long); i++) { 162 if (a.c[i] && offset+i < len) { 163 *(char *)(laddr+offset+i) = a.c[i]; 164 } else { 165 *(char *)(laddr+offset+i) = '\0'; 166 return 0; 167 } 168 } 169 offset += sizeof(long); 170 } 171 *(char *)(laddr+offset) = '\0'; 172 return 0; 173} 174