blob: 1dae7e3b400da6622eb0d133068b717d9aa90bd4 [file] [log] [blame]
Arnaldo Carvalho de Melo234fbbf2009-10-26 19:23:18 -02001#include <linux/types.h>
2#include "event.h"
3#include "debug.h"
4#include "string.h"
5
6static pid_t event__synthesize_comm(pid_t pid, int full,
7 int (*process)(event_t *event))
8{
9 event_t ev;
10 char filename[PATH_MAX];
11 char bf[BUFSIZ];
12 FILE *fp;
13 size_t size = 0;
14 DIR *tasks;
15 struct dirent dirent, *next;
16 pid_t tgid = 0;
17
18 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
19
20 fp = fopen(filename, "r");
21 if (fp == NULL) {
22out_race:
23 /*
24 * We raced with a task exiting - just return:
25 */
26 pr_debug("couldn't open %s\n", filename);
27 return 0;
28 }
29
30 memset(&ev.comm, 0, sizeof(ev.comm));
31 while (!ev.comm.comm[0] || !ev.comm.pid) {
32 if (fgets(bf, sizeof(bf), fp) == NULL)
33 goto out_failure;
34
35 if (memcmp(bf, "Name:", 5) == 0) {
36 char *name = bf + 5;
37 while (*name && isspace(*name))
38 ++name;
39 size = strlen(name) - 1;
40 memcpy(ev.comm.comm, name, size++);
41 } else if (memcmp(bf, "Tgid:", 5) == 0) {
42 char *tgids = bf + 5;
43 while (*tgids && isspace(*tgids))
44 ++tgids;
45 tgid = ev.comm.pid = atoi(tgids);
46 }
47 }
48
49 ev.comm.header.type = PERF_RECORD_COMM;
50 size = ALIGN(size, sizeof(u64));
51 ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size);
52
53 if (!full) {
54 ev.comm.tid = pid;
55
56 process(&ev);
57 goto out_fclose;
58 }
59
60 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
61
62 tasks = opendir(filename);
63 if (tasks == NULL)
64 goto out_race;
65
66 while (!readdir_r(tasks, &dirent, &next) && next) {
67 char *end;
68 pid = strtol(dirent.d_name, &end, 10);
69 if (*end)
70 continue;
71
72 ev.comm.tid = pid;
73
74 process(&ev);
75 }
76 closedir(tasks);
77
78out_fclose:
79 fclose(fp);
80 return tgid;
81
82out_failure:
83 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
84 return -1;
85}
86
87static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
88 int (*process)(event_t *event))
89{
90 char filename[PATH_MAX];
91 FILE *fp;
92
93 snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
94
95 fp = fopen(filename, "r");
96 if (fp == NULL) {
97 /*
98 * We raced with a task exiting - just return:
99 */
100 pr_debug("couldn't open %s\n", filename);
101 return -1;
102 }
103
104 while (1) {
105 char bf[BUFSIZ], *pbf = bf;
106 event_t ev = {
107 .header = { .type = PERF_RECORD_MMAP },
108 };
109 int n;
110 size_t size;
111 if (fgets(bf, sizeof(bf), fp) == NULL)
112 break;
113
114 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
115 n = hex2u64(pbf, &ev.mmap.start);
116 if (n < 0)
117 continue;
118 pbf += n + 1;
119 n = hex2u64(pbf, &ev.mmap.len);
120 if (n < 0)
121 continue;
122 pbf += n + 3;
123 if (*pbf == 'x') { /* vm_exec */
124 char *execname = strchr(bf, '/');
125
126 /* Catch VDSO */
127 if (execname == NULL)
128 execname = strstr(bf, "[vdso]");
129
130 if (execname == NULL)
131 continue;
132
133 size = strlen(execname);
134 execname[size - 1] = '\0'; /* Remove \n */
135 memcpy(ev.mmap.filename, execname, size);
136 size = ALIGN(size, sizeof(u64));
137 ev.mmap.len -= ev.mmap.start;
138 ev.mmap.header.size = (sizeof(ev.mmap) -
139 (sizeof(ev.mmap.filename) - size));
140 ev.mmap.pid = tgid;
141 ev.mmap.tid = pid;
142
143 process(&ev);
144 }
145 }
146
147 fclose(fp);
148 return 0;
149}
150
151int event__synthesize_thread(pid_t pid, int (*process)(event_t *event))
152{
153 pid_t tgid = event__synthesize_comm(pid, 1, process);
154 if (tgid == -1)
155 return -1;
156 return event__synthesize_mmap_events(pid, tgid, process);
157}
158
159void event__synthesize_threads(int (*process)(event_t *event))
160{
161 DIR *proc;
162 struct dirent dirent, *next;
163
164 proc = opendir("/proc");
165
166 while (!readdir_r(proc, &dirent, &next) && next) {
167 char *end;
168 pid_t pid = strtol(dirent.d_name, &end, 10);
169
170 if (*end) /* only interested in proper numerical dirents */
171 continue;
172
173 event__synthesize_thread(pid, process);
174 }
175
176 closedir(proc);
177}