blob: b5532469d56f5bf8522bc61299c1056e30d0ea7b [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);
Juan Cespedes273ea6d1998-03-14 23:02:40 +010035
Petr Machatac7585b62011-07-08 22:58:12 +020036 breakpoints_init(proc, enable);
Joe Damatoab3b72c2010-10-31 00:21:53 -070037
Juan Cespedes273ea6d1998-03-14 23:02:40 +010038 return proc;
39}
40
Juan Cespedesf1350522008-12-16 18:19:58 +010041void
Juan Cespedes8d1b92b2009-07-03 10:39:34 +020042open_pid(pid_t pid) {
Juan Cespedesa8909f72009-04-28 20:02:41 +020043 Process *proc;
Ian Wienand2d45b1a2006-02-20 22:48:07 +010044 char *filename;
Juan Cespedes273ea6d1998-03-14 23:02:40 +010045
Ian Wienand2d45b1a2006-02-20 22:48:07 +010046 if (trace_pid(pid) < 0) {
47 fprintf(stderr, "Cannot attach to pid %u: %s\n", pid,
48 strerror(errno));
Juan Cespedes35d70631998-03-15 14:05:40 +010049 return;
50 }
51
Juan Cespedes273ea6d1998-03-14 23:02:40 +010052 filename = pid2name(pid);
53
54 if (!filename) {
Juan Cespedes8d1b92b2009-07-03 10:39:34 +020055 fprintf(stderr, "Cannot trace pid %u: %s\n", pid,
Ian Wienand2d45b1a2006-02-20 22:48:07 +010056 strerror(errno));
Juan Cespedes273ea6d1998-03-14 23:02:40 +010057 return;
58 }
Juan Cespedes273ea6d1998-03-14 23:02:40 +010059
Petr Machatac7585b62011-07-08 22:58:12 +020060 proc = open_program(filename, pid, 1);
Juan Cespedesaee09312007-08-31 18:49:48 +020061 continue_process(pid);
Ian Wienand9a2ad352006-02-20 22:44:45 +010062 proc->breakpoints_enabled = 1;
Juan Cespedes273ea6d1998-03-14 23:02:40 +010063}
Juan Cespedese74c80d2009-02-11 11:32:31 +010064
Petr Machatacebb8842011-07-09 11:14:11 +020065static enum pcb_status
66find_proc(Process * proc, void * data)
67{
68 pid_t pid = (pid_t)(uintptr_t)data;
69 return proc->pid == pid ? pcb_stop : pcb_cont;
70}
71
Juan Cespedesa8909f72009-04-28 20:02:41 +020072Process *
Juan Cespedese74c80d2009-02-11 11:32:31 +010073pid2proc(pid_t pid) {
Petr Machatacebb8842011-07-09 11:14:11 +020074 return each_process(NULL, &find_proc, (void *)(uintptr_t)pid);
75}
Juan Cespedese74c80d2009-02-11 11:32:31 +010076
Petr Machatacebb8842011-07-09 11:14:11 +020077
78static Process * list_of_processes = NULL;
79
80Process *
81each_process(Process * proc,
82 enum pcb_status (* cb)(Process * proc, void * data),
83 void * data)
84{
85 Process * it = proc ?: list_of_processes;
86 for (; it != NULL; ) {
87 /* Callback might call remove_process. */
88 Process * next = it->next;
89 if ((*cb) (it, data) == pcb_stop)
90 return it;
91 it = next;
92 }
93 return NULL;
94}
95void
96add_process(Process * proc)
97{
98 proc->next = list_of_processes;
99 list_of_processes = proc;
100}
101
102void
103remove_process(Process *proc)
104{
105 Process *tmp, *tmp2;
106
107 debug(DEBUG_FUNCTION, "remove_proc(pid=%d)", proc->pid);
108
109 if (list_of_processes == proc) {
110 tmp = list_of_processes;
111 list_of_processes = list_of_processes->next;
112 free(tmp);
113 return;
114 }
Juan Cespedese74c80d2009-02-11 11:32:31 +0100115 tmp = list_of_processes;
Petr Machatacebb8842011-07-09 11:14:11 +0200116 while (tmp->next) {
117 if (tmp->next == proc) {
118 tmp2 = tmp->next;
119 tmp->next = tmp->next->next;
120 free(tmp2);
121 return;
Juan Cespedese74c80d2009-02-11 11:32:31 +0100122 }
123 tmp = tmp->next;
124 }
Juan Cespedese74c80d2009-02-11 11:32:31 +0100125}