blob: 106b6a054898ab346f65a5d7165548012238474c [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>
Petr Machata1974dbc2011-08-19 18:58:01 +020014#include <error.h>
Juan Cespedes273ea6d1998-03-14 23:02:40 +010015
Juan Cespedesf7281232009-06-25 16:11:21 +020016#include "common.h"
Juan Cespedes273ea6d1998-03-14 23:02:40 +010017
Juan Cespedesa8909f72009-04-28 20:02:41 +020018Process *
Petr Machatac7585b62011-07-08 22:58:12 +020019open_program(char *filename, pid_t pid, int enable) {
Juan Cespedesa8909f72009-04-28 20:02:41 +020020 Process *proc;
Petr Machata1b17dbf2011-07-08 19:22:52 +020021 assert(pid != 0);
Juan Cespedesa8909f72009-04-28 20:02:41 +020022 proc = calloc(sizeof(Process), 1);
Juan Cespedes273ea6d1998-03-14 23:02:40 +010023 if (!proc) {
24 perror("malloc");
25 exit(1);
26 }
Petr Machata1974dbc2011-08-19 18:58:01 +020027
Juan Cespedese0660df2009-05-21 18:14:39 +020028 proc->filename = strdup(filename);
Juan Cespedes273ea6d1998-03-14 23:02:40 +010029 proc->breakpoints_enabled = -1;
Petr Machata1b17dbf2011-07-08 19:22:52 +020030 proc->pid = pid;
Joe Damatoab3b72c2010-10-31 00:21:53 -070031#if defined(HAVE_LIBUNWIND)
Petr Machata1b17dbf2011-07-08 19:22:52 +020032 proc->unwind_priv = _UPT_create(pid);
33 proc->unwind_as = unw_create_addr_space(&_UPT_accessors, 0);
Joe Damatoab3b72c2010-10-31 00:21:53 -070034#endif /* defined(HAVE_LIBUNWIND) */
Joe Damatoab3b72c2010-10-31 00:21:53 -070035
Petr Machatacebb8842011-07-09 11:14:11 +020036 add_process(proc);
Petr Machata1974dbc2011-08-19 18:58:01 +020037 if (proc->leader == NULL) {
38 free(proc);
39 return NULL;
40 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010041
Petr Machata9a5420c2011-07-09 11:21:23 +020042 if (proc->leader == proc)
Petr Machata1974dbc2011-08-19 18:58:01 +020043 if (breakpoints_init(proc, enable)) {
44 fprintf(stderr, "failed to init breakpoints %d\n",
45 proc->pid);
46 remove_process(proc);
47 return NULL;
48 }
Joe Damatoab3b72c2010-10-31 00:21:53 -070049
Juan Cespedes273ea6d1998-03-14 23:02:40 +010050 return proc;
51}
52
Petr Machata3c516d52011-08-18 03:53:18 +020053static int
Petr Machata9a5420c2011-07-09 11:21:23 +020054open_one_pid(pid_t pid)
55{
Juan Cespedesa8909f72009-04-28 20:02:41 +020056 Process *proc;
Ian Wienand2d45b1a2006-02-20 22:48:07 +010057 char *filename;
Petr Machata9a5420c2011-07-09 11:21:23 +020058 debug(DEBUG_PROCESS, "open_one_pid(pid=%d)", pid);
59
Petr Machata1974dbc2011-08-19 18:58:01 +020060 /* Get the filename first. Should the trace_pid fail, we can
61 * easily free it, untracing is more work. */
62 if ((filename = pid2name(pid)) == NULL
63 || trace_pid(pid) < 0) {
64 free(filename);
65 return -1;
66 }
Juan Cespedes35d70631998-03-15 14:05:40 +010067
Petr Machata1974dbc2011-08-19 18:58:01 +020068 proc = open_program(filename, pid, 0);
69 if (proc == NULL)
70 return -1;
Petr Machata602330f2011-07-09 11:15:34 +020071 trace_set_options(proc, pid);
Petr Machata3c516d52011-08-18 03:53:18 +020072
Petr Machata1974dbc2011-08-19 18:58:01 +020073 return 0;
74}
75
76enum pcb_status
77start_one_pid(Process * proc, void * data)
78{
79 continue_process(proc->pid);
80 proc->breakpoints_enabled = 1;
81 return pcb_cont;
Juan Cespedes273ea6d1998-03-14 23:02:40 +010082}
Juan Cespedese74c80d2009-02-11 11:32:31 +010083
Petr Machata9a5420c2011-07-09 11:21:23 +020084void
85open_pid(pid_t pid)
86{
87 debug(DEBUG_PROCESS, "open_pid(pid=%d)", pid);
Petr Machata3c516d52011-08-18 03:53:18 +020088 /* If we are already tracing this guy, we should be seeing all
89 * his children via normal tracing route. */
90 if (pid2proc(pid) != NULL)
91 return;
Petr Machata9a5420c2011-07-09 11:21:23 +020092
Petr Machata3c516d52011-08-18 03:53:18 +020093 /* First, see if we can attach the requested PID itself. */
Petr Machata1974dbc2011-08-19 18:58:01 +020094 if (open_one_pid(pid)) {
Petr Machata3c516d52011-08-18 03:53:18 +020095 fprintf(stderr, "Cannot attach to pid %u: %s\n",
96 pid, strerror(errno));
97 return;
Petr Machata9a5420c2011-07-09 11:21:23 +020098 }
99
Petr Machata3c516d52011-08-18 03:53:18 +0200100 /* Now attach to all tasks that belong to that PID. There's a
101 * race between process_tasks and open_one_pid. So when we
102 * fail in open_one_pid below, we just do another round.
103 * Chances are that by then that PID will have gone away, and
104 * that's why we have seen the failure. The processes that we
105 * manage to open_one_pid are stopped, so we should eventually
106 * reach a point where process_tasks doesn't give any new
107 * processes (because there's nobody left to produce
108 * them). */
Petr Machata1974dbc2011-08-19 18:58:01 +0200109 size_t old_ntasks = 0;
Petr Machata3c516d52011-08-18 03:53:18 +0200110 int have_all;
Petr Machata1974dbc2011-08-19 18:58:01 +0200111 while (1) {
Petr Machata3c516d52011-08-18 03:53:18 +0200112 pid_t *tasks;
113 size_t ntasks;
114 size_t i;
Petr Machata1974dbc2011-08-19 18:58:01 +0200115
Petr Machata3c516d52011-08-18 03:53:18 +0200116 if (process_tasks(pid, &tasks, &ntasks) < 0) {
117 fprintf(stderr, "Cannot obtain tasks of pid %u: %s\n",
118 pid, strerror(errno));
Petr Machatafed1e8d2012-02-07 02:06:29 +0100119 break;
Petr Machata3c516d52011-08-18 03:53:18 +0200120 }
Petr Machata9a5420c2011-07-09 11:21:23 +0200121
Petr Machata3c516d52011-08-18 03:53:18 +0200122 have_all = 1;
123 for (i = 0; i < ntasks; ++i)
124 if (pid2proc(tasks[i]) == NULL
Petr Machata1974dbc2011-08-19 18:58:01 +0200125 && open_one_pid(tasks[i]))
Petr Machata3c516d52011-08-18 03:53:18 +0200126 have_all = 0;
127
Petr Machata9a5420c2011-07-09 11:21:23 +0200128 free(tasks);
Petr Machata3c516d52011-08-18 03:53:18 +0200129
Petr Machata1974dbc2011-08-19 18:58:01 +0200130 if (have_all && old_ntasks == ntasks)
131 break;
132 old_ntasks = ntasks;
133 }
134
135 /* Done. Now initialize breakpoints and then continue
136 * everyone. */
137 Process * leader;
Petr Machata1974dbc2011-08-19 18:58:01 +0200138 leader = pid2proc(pid)->leader;
139 enable_all_breakpoints(leader);
140
141 each_task(pid2proc(pid)->leader, start_one_pid, NULL);
Petr Machata9a5420c2011-07-09 11:21:23 +0200142}
143
Petr Machatacebb8842011-07-09 11:14:11 +0200144static enum pcb_status
145find_proc(Process * proc, void * data)
146{
147 pid_t pid = (pid_t)(uintptr_t)data;
148 return proc->pid == pid ? pcb_stop : pcb_cont;
149}
150
Juan Cespedesa8909f72009-04-28 20:02:41 +0200151Process *
Juan Cespedese74c80d2009-02-11 11:32:31 +0100152pid2proc(pid_t pid) {
Petr Machatacebb8842011-07-09 11:14:11 +0200153 return each_process(NULL, &find_proc, (void *)(uintptr_t)pid);
154}
Juan Cespedese74c80d2009-02-11 11:32:31 +0100155
Petr Machatacebb8842011-07-09 11:14:11 +0200156static Process * list_of_processes = NULL;
157
Petr Machatacbe29c62011-09-27 02:27:58 +0200158static void
159unlist_process(Process * proc)
160{
161 Process *tmp;
162
163 if (list_of_processes == proc) {
164 list_of_processes = list_of_processes->next;
165 return;
166 }
167
168 for (tmp = list_of_processes; ; tmp = tmp->next) {
169 /* If the following assert fails, the process wasn't
170 * in the list. */
171 assert(tmp->next != NULL);
172
173 if (tmp->next == proc) {
174 tmp->next = tmp->next->next;
175 return;
176 }
177 }
178}
179
Petr Machatacebb8842011-07-09 11:14:11 +0200180Process *
181each_process(Process * proc,
182 enum pcb_status (* cb)(Process * proc, void * data),
183 void * data)
184{
185 Process * it = proc ?: list_of_processes;
186 for (; it != NULL; ) {
187 /* Callback might call remove_process. */
188 Process * next = it->next;
189 if ((*cb) (it, data) == pcb_stop)
190 return it;
191 it = next;
192 }
193 return NULL;
194}
Petr Machata9a5420c2011-07-09 11:21:23 +0200195
196Process *
197each_task(Process * it, enum pcb_status (* cb)(Process * proc, void * data),
198 void * data)
199{
200 if (it != NULL) {
201 Process * leader = it->leader;
202 for (; it != NULL && it->leader == leader; ) {
203 /* Callback might call remove_process. */
204 Process * next = it->next;
205 if ((*cb) (it, data) == pcb_stop)
206 return it;
207 it = next;
208 }
209 }
210 return NULL;
211}
212
Petr Machatacebb8842011-07-09 11:14:11 +0200213void
214add_process(Process * proc)
215{
Petr Machata9a5420c2011-07-09 11:21:23 +0200216 Process ** leaderp = &list_of_processes;
217 if (proc->pid) {
218 pid_t tgid = process_leader(proc->pid);
Petr Machata1974dbc2011-08-19 18:58:01 +0200219 if (tgid == 0)
220 /* Must have been terminated before we managed
221 * to fully attach. */
222 return;
Petr Machata9a5420c2011-07-09 11:21:23 +0200223 if (tgid == proc->pid)
224 proc->leader = proc;
225 else {
226 Process * leader = pid2proc(tgid);
227 proc->leader = leader;
228 if (leader != NULL)
Petr Machata9a5420c2011-07-09 11:21:23 +0200229 leaderp = &leader->next;
230 }
231 }
232 proc->next = *leaderp;
233 *leaderp = proc;
234}
235
Petr Machatacbe29c62011-09-27 02:27:58 +0200236void
237change_process_leader(Process * proc, Process * leader)
238{
239 Process ** leaderp = &list_of_processes;
240 if (proc->leader == leader)
241 return;
242
243 assert(leader != NULL);
244 unlist_process(proc);
245 if (proc != leader)
246 leaderp = &leader->next;
247
248 proc->leader = leader;
249 proc->next = *leaderp;
250 *leaderp = proc;
251}
252
Petr Machata9a5420c2011-07-09 11:21:23 +0200253static enum pcb_status
254clear_leader(Process * proc, void * data)
255{
256 debug(DEBUG_FUNCTION, "detach_task %d from leader %d",
257 proc->pid, proc->leader->pid);
258 proc->leader = NULL;
259 return pcb_cont;
Petr Machatacebb8842011-07-09 11:14:11 +0200260}
261
Petr Machata69a03e62011-07-09 11:29:12 +0200262static enum ecb_status
263event_for_proc(Event * event, void * data)
264{
265 if (event->proc == data)
266 return ecb_deque;
267 else
268 return ecb_cont;
269}
270
271static void
272delete_events_for(Process * proc)
273{
274 Event * event;
275 while ((event = each_qd_event(&event_for_proc, proc)) != NULL)
276 free(event);
277}
278
Petr Machatacebb8842011-07-09 11:14:11 +0200279void
280remove_process(Process *proc)
281{
Petr Machatacebb8842011-07-09 11:14:11 +0200282 debug(DEBUG_FUNCTION, "remove_proc(pid=%d)", proc->pid);
283
Petr Machata9a5420c2011-07-09 11:21:23 +0200284 if (proc->leader == proc)
285 each_task(proc, &clear_leader, NULL);
286
Petr Machatacbe29c62011-09-27 02:27:58 +0200287 unlist_process(proc);
288 delete_events_for(proc);
289 free(proc);
Juan Cespedese74c80d2009-02-11 11:32:31 +0100290}
Petr Machata4007d742011-07-09 11:29:42 +0200291
292void
293install_event_handler(Process * proc, Event_Handler * handler)
294{
Petr Machata75dcf7d2011-10-06 14:30:19 +0200295 debug(DEBUG_FUNCTION, "install_event_handler(pid=%d, %p)", proc->pid, handler);
Petr Machata4007d742011-07-09 11:29:42 +0200296 assert(proc->event_handler == NULL);
297 proc->event_handler = handler;
298}
299
300void
301destroy_event_handler(Process * proc)
302{
303 Event_Handler * handler = proc->event_handler;
Petr Machata75dcf7d2011-10-06 14:30:19 +0200304 debug(DEBUG_FUNCTION, "destroy_event_handler(pid=%d, %p)", proc->pid, handler);
Petr Machata4007d742011-07-09 11:29:42 +0200305 assert(handler != NULL);
Petr Machatacbe29c62011-09-27 02:27:58 +0200306 if (handler->destroy != NULL)
307 handler->destroy(handler);
Petr Machata4007d742011-07-09 11:29:42 +0200308 free(handler);
309 proc->event_handler = NULL;
310}