trace.c revision 8d1b92ba755f6d6229f5e230fc43d958b13836f8
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 return 0; 59} 60#endif 61 62void 63trace_me(void) { 64 debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid()); 65 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) { 66 perror("PTRACE_TRACEME"); 67 exit(1); 68 } 69} 70 71int 72trace_pid(pid_t pid) { 73 debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid); 74 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) { 75 return -1; 76 } 77 78 /* man ptrace: PTRACE_ATTACH attaches to the process specified 79 in pid. The child is sent a SIGSTOP, but will not 80 necessarily have stopped by the completion of this call; 81 use wait() to wait for the child to stop. */ 82 if (waitpid (pid, NULL, 0) != pid) { 83 perror ("trace_pid: waitpid"); 84 exit (1); 85 } 86 87 return 0; 88} 89 90void 91trace_set_options(Process *proc, pid_t pid) { 92 if (proc->tracesysgood & 0x80) 93 return; 94 95 debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid); 96 97 long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | 98 PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | 99 PTRACE_O_TRACEEXEC; 100 if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 && 101 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) { 102 perror("PTRACE_SETOPTIONS"); 103 return; 104 } 105 proc->tracesysgood |= 0x80; 106} 107 108void 109untrace_pid(pid_t pid) { 110 debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid); 111 ptrace(PTRACE_DETACH, pid, 1, 0); 112} 113 114void 115continue_after_signal(pid_t pid, int signum) { 116 Process *proc; 117 118 debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum); 119 120 proc = pid2proc(pid); 121 if (proc && proc->breakpoint_being_enabled) { 122#if defined __sparc__ || defined __ia64___ 123 ptrace(PTRACE_SYSCALL, pid, 0, signum); 124#else 125 ptrace(PTRACE_SINGLESTEP, pid, 0, signum); 126#endif 127 } else { 128 ptrace(PTRACE_SYSCALL, pid, 0, signum); 129 } 130} 131 132void 133continue_process(pid_t pid) { 134 /* We always trace syscalls to control fork(), clone(), execve()... */ 135 136 debug(DEBUG_PROCESS, "continue_process: pid=%d", pid); 137 138 ptrace(PTRACE_SYSCALL, pid, 0, 0); 139} 140 141void 142continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) { 143 enable_breakpoint(pid, sbp); 144 continue_process(pid); 145} 146 147void 148continue_after_breakpoint(Process *proc, Breakpoint *sbp) { 149 if (sbp->enabled) 150 disable_breakpoint(proc->pid, sbp); 151 set_instruction_pointer(proc, sbp->addr); 152 if (sbp->enabled == 0) { 153 continue_process(proc->pid); 154 } else { 155 debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr); 156 proc->breakpoint_being_enabled = sbp; 157#if defined __sparc__ || defined __ia64___ 158 /* we don't want to singlestep here */ 159 continue_process(proc->pid); 160#else 161 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0); 162#endif 163 } 164} 165 166/* Read a series of bytes starting at the process's memory address 167 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes 168 have been read. 169*/ 170int 171umovestr(Process *proc, void *addr, int len, void *laddr) { 172 union { 173 long a; 174 char c[sizeof(long)]; 175 } a; 176 int i; 177 int offset = 0; 178 179 while (offset < len) { 180 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0); 181 for (i = 0; i < sizeof(long); i++) { 182 if (a.c[i] && offset + (signed)i < len) { 183 *(char *)(laddr + offset + i) = a.c[i]; 184 } else { 185 *(char *)(laddr + offset + i) = '\0'; 186 return 0; 187 } 188 } 189 offset += sizeof(long); 190 } 191 *(char *)(laddr + offset) = '\0'; 192 return 0; 193} 194