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