trace.c revision 5570a7769869a4df25ef85f302f74a7feb6c0cd3
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 "ptrace.h" 8#include <asm/unistd.h> 9 10#include "ltrace.h" 11#include "options.h" 12 13/* Returns 1 if the sysnum may make a new child to be created 14 * (ie, with fork() or clone()) 15 * Returns 0 otherwise. 16 */ 17int fork_p(int sysnum) 18{ 19 return 0 20#if defined(__NR_fork) 21 || (sysnum == __NR_fork) 22#endif 23#if defined(__NR_clone) 24 || (sysnum == __NR_clone) 25#endif 26#if defined(__NR_vfork) 27 || (sysnum == __NR_vfork) 28#endif 29#if defined(__NR_clone2) 30 || (sysnum == __NR_clone2) 31#endif 32 ; 33} 34 35/* Returns 1 if the sysnum may make the process exec other program 36 */ 37int exec_p(int sysnum) 38{ 39 return (sysnum == __NR_execve); 40} 41 42void trace_me(void) 43{ 44 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) { 45 perror("PTRACE_TRACEME"); 46 exit(1); 47 } 48} 49 50int trace_pid(pid_t pid) 51{ 52 if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) { 53 return -1; 54 } 55 return 0; 56} 57 58void untrace_pid(pid_t pid) 59{ 60 ptrace(PTRACE_DETACH, pid, 1, 0); 61} 62 63void continue_after_signal(pid_t pid, int signum) 64{ 65 /* We should always trace syscalls to be able to control fork(), clone(), execve()... */ 66 ptrace(PTRACE_SYSCALL, pid, 0, signum); 67} 68 69void continue_process(pid_t pid) 70{ 71 continue_after_signal(pid, 0); 72} 73 74void continue_enabling_breakpoint(pid_t pid, struct breakpoint *sbp) 75{ 76 enable_breakpoint(pid, sbp); 77 continue_process(pid); 78} 79 80void continue_after_breakpoint(struct process *proc, struct breakpoint *sbp) 81{ 82 if (sbp->enabled) 83 disable_breakpoint(proc->pid, sbp); 84 85 set_instruction_pointer(proc, sbp->addr); 86 87 if (sbp->enabled == 0) { 88 continue_process(proc->pid); 89 } else { 90 proc->breakpoint_being_enabled = sbp; 91#ifdef __sparc__ || defined __ia64__ 92 /* we don't want to single step here */ 93 continue_process(proc->pid); 94#else 95 ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0); 96#endif 97 } 98} 99 100int umovestr(struct process *proc, void *addr, int len, void *laddr) 101{ 102 union { 103 long a; 104 char c[sizeof(long)]; 105 } a; 106 int i; 107 int offset = 0; 108 109 while (offset < len) { 110 a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0); 111 for (i = 0; i < sizeof(long); i++) { 112 if (a.c[i] && offset + i < len) { 113 *(char *)(laddr + offset + i) = a.c[i]; 114 } else { 115 *(char *)(laddr + offset + i) = '\0'; 116 return 0; 117 } 118 } 119 offset += sizeof(long); 120 } 121 *(char *)(laddr + offset) = '\0'; 122 return 0; 123} 124