static void entry_breakpoint_on_hit(struct breakpoint *a, struct process *proc) { struct entry_breakpoint *bp = (void *)a; if (proc == NULL || proc->leader == NULL) return; arch_addr_t dyn_addr = bp->dyn_addr; delete_breakpoint(proc, bp->super.addr); linkmap_init(proc, dyn_addr); arch_dynlink_done(proc); }
void open_pid(pid_t pid) { debug(DEBUG_PROCESS, "open_pid(pid=%d)", pid); /* If we are already tracing this guy, we should be seeing all * his children via normal tracing route. */ if (pid2proc(pid) != NULL) return; /* First, see if we can attach the requested PID itself. */ if (open_one_pid(pid)) { fprintf(stderr, "Cannot attach to pid %u: %s\n", pid, strerror(errno)); trace_fail_warning(pid); return; } /* Now attach to all tasks that belong to that PID. There's a * race between process_tasks and open_one_pid. So when we * fail in open_one_pid below, we just do another round. * Chances are that by then that PID will have gone away, and * that's why we have seen the failure. The processes that we * manage to open_one_pid are stopped, so we should eventually * reach a point where process_tasks doesn't give any new * processes (because there's nobody left to produce * them). */ size_t old_ntasks = 0; int have_all; while (1) { pid_t *tasks; size_t ntasks; size_t i; if (process_tasks(pid, &tasks, &ntasks) < 0) { fprintf(stderr, "Cannot obtain tasks of pid %u: %s\n", pid, strerror(errno)); break; } have_all = 1; for (i = 0; i < ntasks; ++i) if (pid2proc(tasks[i]) == NULL && open_one_pid(tasks[i])) have_all = 0; free(tasks); if (have_all && old_ntasks == ntasks) break; old_ntasks = ntasks; } struct Process *leader = pid2proc(pid)->leader; /* XXX Is there a way to figure out whether _start has * actually already been hit? */ arch_dynlink_done(leader); /* Done. Continue everyone. */ each_task(leader, NULL, start_one_pid, NULL); }