trace.c revision dfa3fa3879b12ca7307b42a3feb79f42e60a90b0
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 <sys/wait.h> 8#include "ptrace.h" 9#include <asm/unistd.h> 10 11#include "common.h" 12 13/* If the system headers did not provide the constants, hard-code the normal 14 values. */ 15#ifndef PTRACE_EVENT_FORK 16 17#define PTRACE_OLDSETOPTIONS 21 18#define PTRACE_SETOPTIONS 0x4200 19#define PTRACE_GETEVENTMSG 0x4201 20 21/* options set using PTRACE_SETOPTIONS */ 22#define PTRACE_O_TRACESYSGOOD 0x00000001 23#define PTRACE_O_TRACEFORK 0x00000002 24#define PTRACE_O_TRACEVFORK 0x00000004 25#define PTRACE_O_TRACECLONE 0x00000008 26#define PTRACE_O_TRACEEXEC 0x00000010 27#define PTRACE_O_TRACEVFORKDONE 0x00000020 28#define PTRACE_O_TRACEEXIT 0x00000040 29 30/* Wait extended result codes for the above trace options. */ 31#define PTRACE_EVENT_FORK 1 32#define PTRACE_EVENT_VFORK 2 33#define PTRACE_EVENT_CLONE 3 34#define PTRACE_EVENT_EXEC 4 35#define PTRACE_EVENT_VFORK_DONE 5 36#define PTRACE_EVENT_EXIT 6 37 38#endif /* PTRACE_EVENT_FORK */ 39 40#ifdef ARCH_HAVE_UMOVELONG 41extern int arch_umovelong (Process *, void *, long *, arg_type_info *); 42int 43umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { 44 return arch_umovelong (proc, addr, result, info); 45} 46#else 47/* Read a single long from the process's memory address 'addr' */ 48int 49umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { 50 long pointed_to; 51 52 errno = 0; 53 pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0); 54 if (pointed_to == -1 && errno) 55 return -errno; 56 57 *result = pointed_to; 58 if (info) { 59 switch(info->type) { 60 case ARGTYPE_INT: 61 *result &= 0x00000000ffffffffUL; 62 default: 63 break; 64 }; 65 } 66 return 0; 67} 68#endif 69 70void 71trace_me(void) { 72 debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid()); 73 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) { 74 perror("PTRACE_TRACEME"); 75 exit(1); 76 } 77} 78 79int 80trace_pid(pid_t pid) { 81 debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid); 82 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) { 83 return -1; 84 } 85 86 /* man ptrace: PTRACE_ATTACH attaches to the process specified 87 in pid. The child is sent a SIGSTOP, but will not 88 necessarily have stopped by the completion of this call; 89 use wait() to wait for the child to stop. */ 90 if (waitpid (pid, NULL, 0) != pid) { 91 perror ("trace_pid: waitpid"); 92 exit (1); 93 } 94 95 return 0; 96} 97 98void 99trace_set_options(Process *proc, pid_t pid) { 100 if (proc->tracesysgood & 0x80) 101 return; 102 103 debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid); 104 105 long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | 106 PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | 107 PTRACE_O_TRACEEXEC; 108 if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 && 109 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) { 110 perror("PTRACE_SETOPTIONS"); 111 return; 112 } 113 proc->tracesysgood |= 0x80; 114} 115 116void 117untrace_pid(pid_t pid) { 118 debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid); 119 ptrace(PTRACE_DETACH, pid, 1, 0); 120} 121 122void 123continue_after_signal(pid_t pid, int signum) { 124 Process *proc; 125 126 debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum); 127 128 proc = pid2proc(pid); 129 if (proc && proc->breakpoint_being_enabled) { 130#if defined __sparc__ || defined __ia64___ || defined __mips__ 131 ptrace(PTRACE_SYSCALL, pid, 0, signum); 132#else 133 ptrace(PTRACE_SINGLESTEP, pid, 0, signum); 134#endif 135 } else { 136 ptrace(PTRACE_SYSCALL, pid, 0, signum); 137 } 138} 139 140void 141continue_process(pid_t pid) { 142 /* We always trace syscalls to control fork(), clone(), execve()... */ 143 144 debug(DEBUG_PROCESS, "continue_process: pid=%d", pid); 145 146 ptrace(PTRACE_SYSCALL, pid, 0, 0); 147} 148 149void 150continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) { 151 enable_breakpoint(pid, sbp); 152 continue_process(pid); 153} 154 155void 156continue_after_breakpoint(Process *proc, Breakpoint *sbp) { 157 if (sbp->enabled) 158 disable_breakpoint(proc->pid, sbp); 159 set_instruction_pointer(proc, sbp->addr); 160 if (sbp->enabled == 0) { 161 continue_process(proc->pid); 162 } else { 163 debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr); 164 proc->breakpoint_being_enabled = sbp; 165#if defined __sparc__ || defined __ia64___ || defined __mips__ 166 /* we don't want to singlestep here */ 167 continue_process(proc->pid); 168#else 169 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0); 170#endif 171 } 172} 173 174size_t 175umovebytes(Process *proc, void *addr, void *laddr, size_t len) { 176 177 union { 178 long a; 179 char c[sizeof(long)]; 180 } a; 181 int i; 182 int offset = 0, started = 0; 183 size_t bytes_read = 0; 184 185 while (offset < len) { 186 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0); 187 if (a.a == -1 && errno) { 188 if (started && errno == EIO) 189 return bytes_read; 190 else 191 return -1; 192 } 193 started = 1; 194 195 if (len - offset >= sizeof(long)) { 196 memcpy(laddr + offset, &a.c[0], sizeof(long)); 197 bytes_read += sizeof(long); 198 } 199 else { 200 memcpy(laddr + offset, &a.c[0], len - offset); 201 bytes_read += (len - offset); 202 } 203 offset += sizeof(long); 204 } 205 206 return bytes_read; 207} 208 209/* Read a series of bytes starting at the process's memory address 210 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes 211 have been read. 212*/ 213int 214umovestr(Process *proc, void *addr, int len, void *laddr) { 215 union { 216 long a; 217 char c[sizeof(long)]; 218 } a; 219 int i; 220 int offset = 0; 221 222 while (offset < len) { 223 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0); 224 for (i = 0; i < sizeof(long); i++) { 225 if (a.c[i] && offset + (signed)i < len) { 226 *(char *)(laddr + offset + i) = a.c[i]; 227 } else { 228 *(char *)(laddr + offset + i) = '\0'; 229 return 0; 230 } 231 } 232 offset += sizeof(long); 233 } 234 *(char *)(laddr + offset) = '\0'; 235 return 0; 236} 237