blob: cd7b3549f0e2e2d3e074fb4922876cdf5c3ce29f [file] [log] [blame]
Joe Damatoab3b72c2010-10-31 00:21:53 -07001#include "config.h"
2
3#if defined(HAVE_LIBUNWIND)
4#include <libunwind.h>
5#include <libunwind-ptrace.h>
6#endif /* defined(HAVE_LIBUNWIND) */
7
Juan Cespedes273ea6d1998-03-14 23:02:40 +01008#include <sys/types.h>
9#include <string.h>
10#include <stdio.h>
11#include <errno.h>
12#include <stdlib.h>
Petr Machata1b17dbf2011-07-08 19:22:52 +020013#include <assert.h>
Juan Cespedes273ea6d1998-03-14 23:02:40 +010014
Juan Cespedesf7281232009-06-25 16:11:21 +020015#include "common.h"
Juan Cespedes273ea6d1998-03-14 23:02:40 +010016
Juan Cespedesa8909f72009-04-28 20:02:41 +020017Process *
Petr Machatac7585b62011-07-08 22:58:12 +020018open_program(char *filename, pid_t pid, int enable) {
Juan Cespedesa8909f72009-04-28 20:02:41 +020019 Process *proc;
Petr Machata1b17dbf2011-07-08 19:22:52 +020020 assert(pid != 0);
Juan Cespedesa8909f72009-04-28 20:02:41 +020021 proc = calloc(sizeof(Process), 1);
Juan Cespedes273ea6d1998-03-14 23:02:40 +010022 if (!proc) {
23 perror("malloc");
24 exit(1);
25 }
Juan Cespedese0660df2009-05-21 18:14:39 +020026 proc->filename = strdup(filename);
Juan Cespedes273ea6d1998-03-14 23:02:40 +010027 proc->breakpoints_enabled = -1;
Petr Machata1b17dbf2011-07-08 19:22:52 +020028 proc->pid = pid;
Joe Damatoab3b72c2010-10-31 00:21:53 -070029#if defined(HAVE_LIBUNWIND)
Petr Machata1b17dbf2011-07-08 19:22:52 +020030 proc->unwind_priv = _UPT_create(pid);
31 proc->unwind_as = unw_create_addr_space(&_UPT_accessors, 0);
Joe Damatoab3b72c2010-10-31 00:21:53 -070032#endif /* defined(HAVE_LIBUNWIND) */
Joe Damatoab3b72c2010-10-31 00:21:53 -070033
Petr Machatacebb8842011-07-09 11:14:11 +020034 add_process(proc);
Petr Machata9a5420c2011-07-09 11:21:23 +020035 assert(proc->leader != NULL);
Juan Cespedes273ea6d1998-03-14 23:02:40 +010036
Petr Machata9a5420c2011-07-09 11:21:23 +020037 if (proc->leader == proc)
38 breakpoints_init(proc, enable);
Joe Damatoab3b72c2010-10-31 00:21:53 -070039
Juan Cespedes273ea6d1998-03-14 23:02:40 +010040 return proc;
41}
42
Petr Machata3c516d52011-08-18 03:53:18 +020043static int
Petr Machata9a5420c2011-07-09 11:21:23 +020044open_one_pid(pid_t pid)
45{
Juan Cespedesa8909f72009-04-28 20:02:41 +020046 Process *proc;
Ian Wienand2d45b1a2006-02-20 22:48:07 +010047 char *filename;
Petr Machata9a5420c2011-07-09 11:21:23 +020048 debug(DEBUG_PROCESS, "open_one_pid(pid=%d)", pid);
49
Petr Machata3c516d52011-08-18 03:53:18 +020050 if (trace_pid(pid) < 0)
51 return 0;
Juan Cespedes35d70631998-03-15 14:05:40 +010052
Juan Cespedes273ea6d1998-03-14 23:02:40 +010053 filename = pid2name(pid);
Petr Machata3c516d52011-08-18 03:53:18 +020054 if (filename == NULL)
55 return 0;
Juan Cespedes273ea6d1998-03-14 23:02:40 +010056
Petr Machatac7585b62011-07-08 22:58:12 +020057 proc = open_program(filename, pid, 1);
Petr Machata602330f2011-07-09 11:15:34 +020058 trace_set_options(proc, pid);
Juan Cespedesaee09312007-08-31 18:49:48 +020059 continue_process(pid);
Ian Wienand9a2ad352006-02-20 22:44:45 +010060 proc->breakpoints_enabled = 1;
Petr Machata3c516d52011-08-18 03:53:18 +020061
62 return 1;
Juan Cespedes273ea6d1998-03-14 23:02:40 +010063}
Juan Cespedese74c80d2009-02-11 11:32:31 +010064
Petr Machata9a5420c2011-07-09 11:21:23 +020065void
66open_pid(pid_t pid)
67{
68 debug(DEBUG_PROCESS, "open_pid(pid=%d)", pid);
Petr Machata3c516d52011-08-18 03:53:18 +020069 /* If we are already tracing this guy, we should be seeing all
70 * his children via normal tracing route. */
71 if (pid2proc(pid) != NULL)
72 return;
Petr Machata9a5420c2011-07-09 11:21:23 +020073
Petr Machata3c516d52011-08-18 03:53:18 +020074 /* First, see if we can attach the requested PID itself. */
75 if (!open_one_pid(pid)) {
76 fprintf(stderr, "Cannot attach to pid %u: %s\n",
77 pid, strerror(errno));
78 return;
Petr Machata9a5420c2011-07-09 11:21:23 +020079 }
80
Petr Machata3c516d52011-08-18 03:53:18 +020081 /* Now attach to all tasks that belong to that PID. There's a
82 * race between process_tasks and open_one_pid. So when we
83 * fail in open_one_pid below, we just do another round.
84 * Chances are that by then that PID will have gone away, and
85 * that's why we have seen the failure. The processes that we
86 * manage to open_one_pid are stopped, so we should eventually
87 * reach a point where process_tasks doesn't give any new
88 * processes (because there's nobody left to produce
89 * them). */
90 int have_all;
91 do {
92 pid_t *tasks;
93 size_t ntasks;
94 size_t i;
95 if (process_tasks(pid, &tasks, &ntasks) < 0) {
96 fprintf(stderr, "Cannot obtain tasks of pid %u: %s\n",
97 pid, strerror(errno));
98 return;
99 }
Petr Machata9a5420c2011-07-09 11:21:23 +0200100
Petr Machata3c516d52011-08-18 03:53:18 +0200101 have_all = 1;
102 for (i = 0; i < ntasks; ++i)
103 if (pid2proc(tasks[i]) == NULL
104 && !open_one_pid(tasks[i]))
105 have_all = 0;
106
Petr Machata9a5420c2011-07-09 11:21:23 +0200107 free(tasks);
Petr Machata3c516d52011-08-18 03:53:18 +0200108
109 } while (have_all == 0);
Petr Machata9a5420c2011-07-09 11:21:23 +0200110}
111
Petr Machatacebb8842011-07-09 11:14:11 +0200112static enum pcb_status
113find_proc(Process * proc, void * data)
114{
115 pid_t pid = (pid_t)(uintptr_t)data;
116 return proc->pid == pid ? pcb_stop : pcb_cont;
117}
118
Juan Cespedesa8909f72009-04-28 20:02:41 +0200119Process *
Juan Cespedese74c80d2009-02-11 11:32:31 +0100120pid2proc(pid_t pid) {
Petr Machatacebb8842011-07-09 11:14:11 +0200121 return each_process(NULL, &find_proc, (void *)(uintptr_t)pid);
122}
Juan Cespedese74c80d2009-02-11 11:32:31 +0100123
Petr Machatacebb8842011-07-09 11:14:11 +0200124
125static Process * list_of_processes = NULL;
126
127Process *
128each_process(Process * proc,
129 enum pcb_status (* cb)(Process * proc, void * data),
130 void * data)
131{
132 Process * it = proc ?: list_of_processes;
133 for (; it != NULL; ) {
134 /* Callback might call remove_process. */
135 Process * next = it->next;
136 if ((*cb) (it, data) == pcb_stop)
137 return it;
138 it = next;
139 }
140 return NULL;
141}
Petr Machata9a5420c2011-07-09 11:21:23 +0200142
143Process *
144each_task(Process * it, enum pcb_status (* cb)(Process * proc, void * data),
145 void * data)
146{
147 if (it != NULL) {
148 Process * leader = it->leader;
149 for (; it != NULL && it->leader == leader; ) {
150 /* Callback might call remove_process. */
151 Process * next = it->next;
152 if ((*cb) (it, data) == pcb_stop)
153 return it;
154 it = next;
155 }
156 }
157 return NULL;
158}
159
Petr Machatacebb8842011-07-09 11:14:11 +0200160void
161add_process(Process * proc)
162{
Petr Machata9a5420c2011-07-09 11:21:23 +0200163 Process ** leaderp = &list_of_processes;
164 if (proc->pid) {
165 pid_t tgid = process_leader(proc->pid);
166 if (tgid == proc->pid)
167 proc->leader = proc;
168 else {
169 Process * leader = pid2proc(tgid);
170 proc->leader = leader;
171 if (leader != NULL)
172 // NULL: sub-task added before leader?
173 leaderp = &leader->next;
174 }
175 }
176 proc->next = *leaderp;
177 *leaderp = proc;
178}
179
180static enum pcb_status
181clear_leader(Process * proc, void * data)
182{
183 debug(DEBUG_FUNCTION, "detach_task %d from leader %d",
184 proc->pid, proc->leader->pid);
185 proc->leader = NULL;
186 return pcb_cont;
Petr Machatacebb8842011-07-09 11:14:11 +0200187}
188
Petr Machata69a03e62011-07-09 11:29:12 +0200189static enum ecb_status
190event_for_proc(Event * event, void * data)
191{
192 if (event->proc == data)
193 return ecb_deque;
194 else
195 return ecb_cont;
196}
197
198static void
199delete_events_for(Process * proc)
200{
201 Event * event;
202 while ((event = each_qd_event(&event_for_proc, proc)) != NULL)
203 free(event);
204}
205
Petr Machatacebb8842011-07-09 11:14:11 +0200206void
207remove_process(Process *proc)
208{
209 Process *tmp, *tmp2;
210
211 debug(DEBUG_FUNCTION, "remove_proc(pid=%d)", proc->pid);
212
Petr Machata9a5420c2011-07-09 11:21:23 +0200213 if (proc->leader == proc)
214 each_task(proc, &clear_leader, NULL);
215
Petr Machatacebb8842011-07-09 11:14:11 +0200216 if (list_of_processes == proc) {
217 tmp = list_of_processes;
218 list_of_processes = list_of_processes->next;
Petr Machata69a03e62011-07-09 11:29:12 +0200219 delete_events_for(tmp);
Petr Machatacebb8842011-07-09 11:14:11 +0200220 free(tmp);
221 return;
222 }
Juan Cespedese74c80d2009-02-11 11:32:31 +0100223 tmp = list_of_processes;
Petr Machatacebb8842011-07-09 11:14:11 +0200224 while (tmp->next) {
225 if (tmp->next == proc) {
226 tmp2 = tmp->next;
227 tmp->next = tmp->next->next;
Petr Machata69a03e62011-07-09 11:29:12 +0200228 delete_events_for(tmp2);
Petr Machatacebb8842011-07-09 11:14:11 +0200229 free(tmp2);
230 return;
Juan Cespedese74c80d2009-02-11 11:32:31 +0100231 }
232 tmp = tmp->next;
233 }
Juan Cespedese74c80d2009-02-11 11:32:31 +0100234}
Petr Machata4007d742011-07-09 11:29:42 +0200235
236void
237install_event_handler(Process * proc, Event_Handler * handler)
238{
Petr Machata75dcf7d2011-10-06 14:30:19 +0200239 debug(DEBUG_FUNCTION, "install_event_handler(pid=%d, %p)", proc->pid, handler);
Petr Machata4007d742011-07-09 11:29:42 +0200240 assert(proc->event_handler == NULL);
241 proc->event_handler = handler;
242}
243
244void
245destroy_event_handler(Process * proc)
246{
247 Event_Handler * handler = proc->event_handler;
Petr Machata75dcf7d2011-10-06 14:30:19 +0200248 debug(DEBUG_FUNCTION, "destroy_event_handler(pid=%d, %p)", proc->pid, handler);
Petr Machata4007d742011-07-09 11:29:42 +0200249 assert(handler != NULL);
250 handler->destroy(handler);
251 free(handler);
252 proc->event_handler = NULL;
253}