trace.c revision 85f7d7616f2736de79f6b7f77bceedbc97c83406
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 "ltrace.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 43static int fork_exec_syscalls[][5] = { 44 { 45#ifdef __NR_fork 46 __NR_fork, 47#else 48 -1, 49#endif 50#ifdef __NR_clone 51 __NR_clone, 52#else 53 -1, 54#endif 55#ifdef __NR_clone2 56 __NR_clone2, 57#else 58 -1, 59#endif 60#ifdef __NR_vfork 61 __NR_vfork, 62#else 63 -1, 64#endif 65#ifdef __NR_execve 66 __NR_execve, 67#else 68 -1, 69#endif 70 } 71#ifdef FORK_EXEC_SYSCALLS 72 FORK_EXEC_SYSCALLS 73#endif 74}; 75 76#ifdef ARCH_HAVE_UMOVELONG 77extern int arch_umovelong (Process *, void *, long *, arg_type_info *); 78int 79umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { 80 return arch_umovelong (proc, addr, result, info); 81} 82#else 83/* Read a single long from the process's memory address 'addr' */ 84int 85umovelong (Process *proc, void *addr, long *result, arg_type_info *info) { 86 long pointed_to; 87 88 errno = 0; 89 pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0); 90 if (pointed_to == -1 && errno) 91 return -errno; 92 93 *result = pointed_to; 94 return 0; 95} 96#endif 97 98 99/* Returns 1 if the sysnum may make a new child to be created 100 * (ie, with fork() or clone()) 101 * Returns 0 otherwise. 102 */ 103int 104fork_p(Process *proc, int sysnum) { 105 unsigned int i; 106 if (proc->personality 107 >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0])) 108 return 0; 109 for (i = 0; i < sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1; ++i) 110 if (sysnum == fork_exec_syscalls[proc->personality][i]) 111 return 1; 112 return 0; 113} 114 115/* Returns 1 if the sysnum may make the process exec other program 116 */ 117int 118exec_p(Process *proc, int sysnum) { 119 int i; 120 if (proc->personality 121 >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0])) 122 return 0; 123 i = sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1; 124 if (sysnum == fork_exec_syscalls[proc->personality][i]) 125 return 1; 126 return 0; 127} 128 129/* Check that we just hit an exec. 130 */ 131int 132was_exec(Process *proc, int status) { 133 if (!WIFSTOPPED (status)) 134 return 0; 135 136 if (WSTOPSIG (status) == SIGTRAP 137 && (status >> 16) == PTRACE_EVENT_EXEC) { 138 debug (1, "detected exec (PTRACE_EVENT_EXEC)"); 139 return 1; 140 } 141 142 if (WSTOPSIG (status) == SIGTRAP 143 && proc->callstack_depth > 0) { 144 /* Check whether this SIGTRAP is received just after 145 execve is called for this process. Ideally we'd 146 like to check that the exec succeeded, but e.g. on 147 s390 we have no way of knowing, because return 148 value is not set to -1 (as it should). Never mind, 149 reseting breakpoints for current process doesn't 150 hurt. */ 151 struct callstack_element *elem; 152 elem = &proc->callstack[proc->callstack_depth - 1]; 153 if (elem && elem->is_syscall && exec_p(proc, elem->c_un.syscall)) { 154 debug (1, "detected exec (callstack)"); 155 return 1; 156 } 157 } 158 159 return 0; 160} 161 162void 163trace_me(void) { 164 debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid()); 165 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) { 166 perror("PTRACE_TRACEME"); 167 exit(1); 168 } 169} 170 171int 172trace_pid(pid_t pid) { 173 debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid); 174 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) { 175 return -1; 176 } 177 178 /* man ptrace: PTRACE_ATTACH attaches to the process specified 179 in pid. The child is sent a SIGSTOP, but will not 180 necessarily have stopped by the completion of this call; 181 use wait() to wait for the child to stop. */ 182 if (waitpid (pid, NULL, 0) != pid) { 183 perror ("trace_pid: waitpid"); 184 exit (1); 185 } 186 187 return 0; 188} 189 190void 191trace_set_options(Process *proc, pid_t pid) { 192 if (proc->tracesysgood & 0x80) 193 return; 194 195 debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid); 196 197 long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | 198 PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | 199 PTRACE_O_TRACEEXEC; 200 if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 && 201 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) { 202 perror("PTRACE_SETOPTIONS"); 203 return; 204 } 205 proc->tracesysgood |= 0x80; 206} 207 208void 209untrace_pid(pid_t pid) { 210 debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid); 211 ptrace(PTRACE_DETACH, pid, 1, 0); 212} 213 214void 215continue_after_signal(pid_t pid, int signum) { 216 Process *proc; 217 218 debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum); 219 220 proc = pid2proc(pid); 221 if (proc && proc->breakpoint_being_enabled) { 222#if defined __sparc__ || defined __ia64___ 223 ptrace(PTRACE_SYSCALL, pid, 0, signum); 224#else 225 ptrace(PTRACE_SINGLESTEP, pid, 0, signum); 226#endif 227 } else { 228 ptrace(PTRACE_SYSCALL, pid, 0, signum); 229 } 230} 231 232void 233continue_process(pid_t pid) { 234 /* We always trace syscalls to control fork(), clone(), execve()... */ 235 236 debug(DEBUG_PROCESS, "continue_process: pid=%d", pid); 237 238 ptrace(PTRACE_SYSCALL, pid, 0, 0); 239} 240 241void 242continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) { 243 enable_breakpoint(pid, sbp); 244 continue_process(pid); 245} 246 247void 248continue_after_breakpoint(Process *proc, Breakpoint *sbp) { 249 if (sbp->enabled) 250 disable_breakpoint(proc->pid, sbp); 251 set_instruction_pointer(proc, sbp->addr); 252 if (sbp->enabled == 0) { 253 continue_process(proc->pid); 254 } else { 255 debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr); 256 proc->breakpoint_being_enabled = sbp; 257#if defined __sparc__ || defined __ia64___ 258 /* we don't want to singlestep here */ 259 continue_process(proc->pid); 260#else 261 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0); 262#endif 263 } 264} 265 266/* Read a series of bytes starting at the process's memory address 267 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes 268 have been read. 269*/ 270int 271umovestr(Process *proc, void *addr, int len, void *laddr) { 272 union { 273 long a; 274 char c[sizeof(long)]; 275 } a; 276 int i; 277 int offset = 0; 278 279 while (offset < len) { 280 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0); 281 for (i = 0; i < sizeof(long); i++) { 282 if (a.c[i] && offset + (signed)i < len) { 283 *(char *)(laddr + offset + i) = a.c[i]; 284 } else { 285 *(char *)(laddr + offset + i) = '\0'; 286 return 0; 287 } 288 } 289 offset += sizeof(long); 290 } 291 *(char *)(laddr + offset) = '\0'; 292 return 0; 293} 294