proc.c revision 61196a4a81e77322bf1f3dc609007f5d35a5103a
1#include "config.h" 2 3#if defined(HAVE_LIBUNWIND) 4#include <libunwind.h> 5#include <libunwind-ptrace.h> 6#endif /* defined(HAVE_LIBUNWIND) */ 7 8#include <sys/types.h> 9#include <string.h> 10#include <stdio.h> 11#include <errno.h> 12#include <stdlib.h> 13#include <assert.h> 14#include <error.h> 15 16#include "common.h" 17#include "breakpoint.h" 18 19Process * 20open_program(char *filename, pid_t pid, int enable) { 21 Process *proc; 22 assert(pid != 0); 23 proc = calloc(sizeof(Process), 1); 24 if (!proc) { 25 perror("malloc"); 26 exit(1); 27 } 28 29 proc->filename = strdup(filename); 30 proc->pid = pid; 31#if defined(HAVE_LIBUNWIND) 32 proc->unwind_priv = _UPT_create(pid); 33 proc->unwind_as = unw_create_addr_space(&_UPT_accessors, 0); 34#endif /* defined(HAVE_LIBUNWIND) */ 35 36 add_process(proc); 37 if (proc->leader == NULL) { 38 free(proc); 39 return NULL; 40 } 41 42 if (proc->leader == proc) { 43 trace_set_options(proc, proc->pid); 44 if (breakpoints_init(proc, enable)) { 45 fprintf(stderr, "failed to init breakpoints %d\n", 46 proc->pid); 47 remove_process(proc); 48 return NULL; 49 } 50 } 51 52 return proc; 53} 54 55static int 56open_one_pid(pid_t pid) 57{ 58 Process *proc; 59 char *filename; 60 debug(DEBUG_PROCESS, "open_one_pid(pid=%d)", pid); 61 62 /* Get the filename first. Should the trace_pid fail, we can 63 * easily free it, untracing is more work. */ 64 if ((filename = pid2name(pid)) == NULL 65 || trace_pid(pid) < 0) { 66 free(filename); 67 return -1; 68 } 69 70 proc = open_program(filename, pid, 0); 71 if (proc == NULL) 72 return -1; 73 trace_set_options(proc, pid); 74 75 return 0; 76} 77 78static enum pcb_status 79start_one_pid(Process * proc, void * data) 80{ 81 continue_process(proc->pid); 82 return pcb_cont; 83} 84 85void 86open_pid(pid_t pid) 87{ 88 debug(DEBUG_PROCESS, "open_pid(pid=%d)", pid); 89 /* If we are already tracing this guy, we should be seeing all 90 * his children via normal tracing route. */ 91 if (pid2proc(pid) != NULL) 92 return; 93 94 /* First, see if we can attach the requested PID itself. */ 95 if (open_one_pid(pid)) { 96 fprintf(stderr, "Cannot attach to pid %u: %s\n", 97 pid, strerror(errno)); 98 trace_fail_warning(pid); 99 return; 100 } 101 102 /* Now attach to all tasks that belong to that PID. There's a 103 * race between process_tasks and open_one_pid. So when we 104 * fail in open_one_pid below, we just do another round. 105 * Chances are that by then that PID will have gone away, and 106 * that's why we have seen the failure. The processes that we 107 * manage to open_one_pid are stopped, so we should eventually 108 * reach a point where process_tasks doesn't give any new 109 * processes (because there's nobody left to produce 110 * them). */ 111 size_t old_ntasks = 0; 112 int have_all; 113 while (1) { 114 pid_t *tasks; 115 size_t ntasks; 116 size_t i; 117 118 if (process_tasks(pid, &tasks, &ntasks) < 0) { 119 fprintf(stderr, "Cannot obtain tasks of pid %u: %s\n", 120 pid, strerror(errno)); 121 break; 122 } 123 124 have_all = 1; 125 for (i = 0; i < ntasks; ++i) 126 if (pid2proc(tasks[i]) == NULL 127 && open_one_pid(tasks[i])) 128 have_all = 0; 129 130 free(tasks); 131 132 if (have_all && old_ntasks == ntasks) 133 break; 134 old_ntasks = ntasks; 135 } 136 137 /* Done. Now initialize breakpoints and then continue 138 * everyone. */ 139 Process * leader; 140 leader = pid2proc(pid)->leader; 141 enable_all_breakpoints(leader); 142 143 each_task(pid2proc(pid)->leader, start_one_pid, NULL); 144} 145 146static enum pcb_status 147find_proc(Process * proc, void * data) 148{ 149 pid_t pid = (pid_t)(uintptr_t)data; 150 return proc->pid == pid ? pcb_stop : pcb_cont; 151} 152 153Process * 154pid2proc(pid_t pid) { 155 return each_process(NULL, &find_proc, (void *)(uintptr_t)pid); 156} 157 158static Process * list_of_processes = NULL; 159 160static void 161unlist_process(Process * proc) 162{ 163 Process *tmp; 164 165 if (list_of_processes == proc) { 166 list_of_processes = list_of_processes->next; 167 return; 168 } 169 170 for (tmp = list_of_processes; ; tmp = tmp->next) { 171 /* If the following assert fails, the process wasn't 172 * in the list. */ 173 assert(tmp->next != NULL); 174 175 if (tmp->next == proc) { 176 tmp->next = tmp->next->next; 177 return; 178 } 179 } 180} 181 182Process * 183each_process(Process * proc, 184 enum pcb_status (* cb)(Process * proc, void * data), 185 void * data) 186{ 187 Process * it = proc ?: list_of_processes; 188 for (; it != NULL; ) { 189 /* Callback might call remove_process. */ 190 Process * next = it->next; 191 if ((*cb) (it, data) == pcb_stop) 192 return it; 193 it = next; 194 } 195 return NULL; 196} 197 198Process * 199each_task(Process * it, enum pcb_status (* cb)(Process * proc, void * data), 200 void * data) 201{ 202 if (it != NULL) { 203 Process * leader = it->leader; 204 for (; it != NULL && it->leader == leader; ) { 205 /* Callback might call remove_process. */ 206 Process * next = it->next; 207 if ((*cb) (it, data) == pcb_stop) 208 return it; 209 it = next; 210 } 211 } 212 return NULL; 213} 214 215void 216add_process(Process * proc) 217{ 218 Process ** leaderp = &list_of_processes; 219 if (proc->pid) { 220 pid_t tgid = process_leader(proc->pid); 221 if (tgid == 0) 222 /* Must have been terminated before we managed 223 * to fully attach. */ 224 return; 225 if (tgid == proc->pid) 226 proc->leader = proc; 227 else { 228 Process * leader = pid2proc(tgid); 229 proc->leader = leader; 230 if (leader != NULL) 231 leaderp = &leader->next; 232 } 233 } 234 proc->next = *leaderp; 235 *leaderp = proc; 236} 237 238void 239change_process_leader(Process * proc, Process * leader) 240{ 241 Process ** leaderp = &list_of_processes; 242 if (proc->leader == leader) 243 return; 244 245 assert(leader != NULL); 246 unlist_process(proc); 247 if (proc != leader) 248 leaderp = &leader->next; 249 250 proc->leader = leader; 251 proc->next = *leaderp; 252 *leaderp = proc; 253} 254 255static enum pcb_status 256clear_leader(Process * proc, void * data) 257{ 258 debug(DEBUG_FUNCTION, "detach_task %d from leader %d", 259 proc->pid, proc->leader->pid); 260 proc->leader = NULL; 261 return pcb_cont; 262} 263 264static enum ecb_status 265event_for_proc(Event * event, void * data) 266{ 267 if (event->proc == data) 268 return ecb_deque; 269 else 270 return ecb_cont; 271} 272 273static void 274delete_events_for(Process * proc) 275{ 276 Event * event; 277 while ((event = each_qd_event(&event_for_proc, proc)) != NULL) 278 free(event); 279} 280 281void 282remove_process(Process *proc) 283{ 284 debug(DEBUG_FUNCTION, "remove_proc(pid=%d)", proc->pid); 285 286 if (proc->leader == proc) 287 each_task(proc, &clear_leader, NULL); 288 289 unlist_process(proc); 290 delete_events_for(proc); 291 free(proc); 292} 293 294void 295install_event_handler(Process * proc, Event_Handler * handler) 296{ 297 debug(DEBUG_FUNCTION, "install_event_handler(pid=%d, %p)", proc->pid, handler); 298 assert(proc->event_handler == NULL); 299 proc->event_handler = handler; 300} 301 302void 303destroy_event_handler(Process * proc) 304{ 305 Event_Handler * handler = proc->event_handler; 306 debug(DEBUG_FUNCTION, "destroy_event_handler(pid=%d, %p)", proc->pid, handler); 307 assert(handler != NULL); 308 if (handler->destroy != NULL) 309 handler->destroy(handler); 310 free(handler); 311 proc->event_handler = NULL; 312} 313