trace.c revision 2721e6adbc7399e1b621b896b4f5b864082fbf03
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/* Returns 1 if the sysnum may make the process exec other program 99 */ 100int 101exec_p(Process *proc, int sysnum) { 102 int i; 103 if (proc->personality 104 >= sizeof fork_exec_syscalls / sizeof(fork_exec_syscalls[0])) 105 return 0; 106 i = sizeof(fork_exec_syscalls[0]) / sizeof(int) - 1; 107 if (sysnum == fork_exec_syscalls[proc->personality][i]) 108 return 1; 109 return 0; 110} 111 112/* Check that we just hit an exec. 113 */ 114int 115was_exec(Process *proc, int status) { 116 if (!WIFSTOPPED (status)) 117 return 0; 118 119 if (WSTOPSIG (status) == SIGTRAP 120 && (status >> 16) == PTRACE_EVENT_EXEC) { 121 debug (1, "detected exec (PTRACE_EVENT_EXEC)"); 122 return 1; 123 } 124 125 if (WSTOPSIG (status) == SIGTRAP 126 && proc->callstack_depth > 0) { 127 /* Check whether this SIGTRAP is received just after 128 execve is called for this process. Ideally we'd 129 like to check that the exec succeeded, but e.g. on 130 s390 we have no way of knowing, because return 131 value is not set to -1 (as it should). Never mind, 132 reseting breakpoints for current process doesn't 133 hurt. */ 134 struct callstack_element *elem; 135 elem = &proc->callstack[proc->callstack_depth - 1]; 136 if (elem && elem->is_syscall && exec_p(proc, elem->c_un.syscall)) { 137 debug (1, "detected exec (callstack)"); 138 return 1; 139 } 140 } 141 142 return 0; 143} 144 145void 146trace_me(void) { 147 debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid()); 148 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) { 149 perror("PTRACE_TRACEME"); 150 exit(1); 151 } 152} 153 154int 155trace_pid(pid_t pid) { 156 debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid); 157 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) { 158 return -1; 159 } 160 161 /* man ptrace: PTRACE_ATTACH attaches to the process specified 162 in pid. The child is sent a SIGSTOP, but will not 163 necessarily have stopped by the completion of this call; 164 use wait() to wait for the child to stop. */ 165 if (waitpid (pid, NULL, 0) != pid) { 166 perror ("trace_pid: waitpid"); 167 exit (1); 168 } 169 170 return 0; 171} 172 173void 174trace_set_options(Process *proc, pid_t pid) { 175 if (proc->tracesysgood & 0x80) 176 return; 177 178 debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid); 179 180 long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | 181 PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | 182 PTRACE_O_TRACEEXEC; 183 if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 && 184 ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) { 185 perror("PTRACE_SETOPTIONS"); 186 return; 187 } 188 proc->tracesysgood |= 0x80; 189} 190 191void 192untrace_pid(pid_t pid) { 193 debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid); 194 ptrace(PTRACE_DETACH, pid, 1, 0); 195} 196 197void 198continue_after_signal(pid_t pid, int signum) { 199 Process *proc; 200 201 debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum); 202 203 proc = pid2proc(pid); 204 if (proc && proc->breakpoint_being_enabled) { 205#if defined __sparc__ || defined __ia64___ 206 ptrace(PTRACE_SYSCALL, pid, 0, signum); 207#else 208 ptrace(PTRACE_SINGLESTEP, pid, 0, signum); 209#endif 210 } else { 211 ptrace(PTRACE_SYSCALL, pid, 0, signum); 212 } 213} 214 215void 216continue_process(pid_t pid) { 217 /* We always trace syscalls to control fork(), clone(), execve()... */ 218 219 debug(DEBUG_PROCESS, "continue_process: pid=%d", pid); 220 221 ptrace(PTRACE_SYSCALL, pid, 0, 0); 222} 223 224void 225continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) { 226 enable_breakpoint(pid, sbp); 227 continue_process(pid); 228} 229 230void 231continue_after_breakpoint(Process *proc, Breakpoint *sbp) { 232 if (sbp->enabled) 233 disable_breakpoint(proc->pid, sbp); 234 set_instruction_pointer(proc, sbp->addr); 235 if (sbp->enabled == 0) { 236 continue_process(proc->pid); 237 } else { 238 debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr); 239 proc->breakpoint_being_enabled = sbp; 240#if defined __sparc__ || defined __ia64___ 241 /* we don't want to singlestep here */ 242 continue_process(proc->pid); 243#else 244 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0); 245#endif 246 } 247} 248 249/* Read a series of bytes starting at the process's memory address 250 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes 251 have been read. 252*/ 253int 254umovestr(Process *proc, void *addr, int len, void *laddr) { 255 union { 256 long a; 257 char c[sizeof(long)]; 258 } a; 259 int i; 260 int offset = 0; 261 262 while (offset < len) { 263 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0); 264 for (i = 0; i < sizeof(long); i++) { 265 if (a.c[i] && offset + (signed)i < len) { 266 *(char *)(laddr + offset + i) = a.c[i]; 267 } else { 268 *(char *)(laddr + offset + i) = '\0'; 269 return 0; 270 } 271 } 272 offset += sizeof(long); 273 } 274 *(char *)(laddr + offset) = '\0'; 275 return 0; 276} 277