proc.c revision cebb88491e68bdf4d466b03970c9ca77f65615f8
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
15#include "common.h"
16
17Process *
18open_program(char *filename, pid_t pid, int enable) {
19	Process *proc;
20	assert(pid != 0);
21	proc = calloc(sizeof(Process), 1);
22	if (!proc) {
23		perror("malloc");
24		exit(1);
25	}
26	proc->filename = strdup(filename);
27	proc->breakpoints_enabled = -1;
28	proc->pid = pid;
29#if defined(HAVE_LIBUNWIND)
30	proc->unwind_priv = _UPT_create(pid);
31	proc->unwind_as = unw_create_addr_space(&_UPT_accessors, 0);
32#endif /* defined(HAVE_LIBUNWIND) */
33
34	add_process(proc);
35
36	breakpoints_init(proc, enable);
37
38	return proc;
39}
40
41void
42open_pid(pid_t pid) {
43	Process *proc;
44	char *filename;
45
46	if (trace_pid(pid) < 0) {
47		fprintf(stderr, "Cannot attach to pid %u: %s\n", pid,
48			strerror(errno));
49		return;
50	}
51
52	filename = pid2name(pid);
53
54	if (!filename) {
55		fprintf(stderr, "Cannot trace pid %u: %s\n", pid,
56				strerror(errno));
57		return;
58	}
59
60	proc = open_program(filename, pid, 1);
61	continue_process(pid);
62	proc->breakpoints_enabled = 1;
63}
64
65static 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
72Process *
73pid2proc(pid_t pid) {
74	return each_process(NULL, &find_proc, (void *)(uintptr_t)pid);
75}
76
77
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	}
115	tmp = list_of_processes;
116	while (tmp->next) {
117		if (tmp->next == proc) {
118			tmp2 = tmp->next;
119			tmp->next = tmp->next->next;
120			free(tmp2);
121			return;
122		}
123		tmp = tmp->next;
124	}
125}
126