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