aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c181
1 files changed, 10 insertions, 171 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 9e1638cc19c..4a73d89ce5d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -109,6 +109,12 @@ static void write_output(void *buf, size_t size)
109 } 109 }
110} 110}
111 111
112static int process_synthesized_event(event_t *event)
113{
114 write_output(event, event->header.size);
115 return 0;
116}
117
112static void mmap_read(struct mmap_data *md) 118static void mmap_read(struct mmap_data *md)
113{ 119{
114 unsigned int head = mmap_read_head(md); 120 unsigned int head = mmap_read_head(md);
@@ -191,172 +197,6 @@ static void sig_atexit(void)
191 kill(getpid(), signr); 197 kill(getpid(), signr);
192} 198}
193 199
194static pid_t pid_synthesize_comm_event(pid_t pid, int full)
195{
196 struct comm_event comm_ev;
197 char filename[PATH_MAX];
198 char bf[BUFSIZ];
199 FILE *fp;
200 size_t size = 0;
201 DIR *tasks;
202 struct dirent dirent, *next;
203 pid_t tgid = 0;
204
205 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
206
207 fp = fopen(filename, "r");
208 if (fp == NULL) {
209out_race:
210 /*
211 * We raced with a task exiting - just return:
212 */
213 if (verbose)
214 fprintf(stderr, "couldn't open %s\n", filename);
215 return 0;
216 }
217
218 memset(&comm_ev, 0, sizeof(comm_ev));
219 while (!comm_ev.comm[0] || !comm_ev.pid) {
220 if (fgets(bf, sizeof(bf), fp) == NULL)
221 goto out_failure;
222
223 if (memcmp(bf, "Name:", 5) == 0) {
224 char *name = bf + 5;
225 while (*name && isspace(*name))
226 ++name;
227 size = strlen(name) - 1;
228 memcpy(comm_ev.comm, name, size++);
229 } else if (memcmp(bf, "Tgid:", 5) == 0) {
230 char *tgids = bf + 5;
231 while (*tgids && isspace(*tgids))
232 ++tgids;
233 tgid = comm_ev.pid = atoi(tgids);
234 }
235 }
236
237 comm_ev.header.type = PERF_RECORD_COMM;
238 size = ALIGN(size, sizeof(u64));
239 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
240
241 if (!full) {
242 comm_ev.tid = pid;
243
244 write_output(&comm_ev, comm_ev.header.size);
245 goto out_fclose;
246 }
247
248 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
249
250 tasks = opendir(filename);
251 if (tasks == NULL)
252 goto out_race;
253
254 while (!readdir_r(tasks, &dirent, &next) && next) {
255 char *end;
256 pid = strtol(dirent.d_name, &end, 10);
257 if (*end)
258 continue;
259
260 comm_ev.tid = pid;
261
262 write_output(&comm_ev, comm_ev.header.size);
263 }
264 closedir(tasks);
265
266out_fclose:
267 fclose(fp);
268 return tgid;
269
270out_failure:
271 fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
272 filename);
273 exit(EXIT_FAILURE);
274}
275
276static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
277{
278 char filename[PATH_MAX];
279 FILE *fp;
280
281 snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
282
283 fp = fopen(filename, "r");
284 if (fp == NULL) {
285 /*
286 * We raced with a task exiting - just return:
287 */
288 if (verbose)
289 fprintf(stderr, "couldn't open %s\n", filename);
290 return;
291 }
292 while (1) {
293 char bf[BUFSIZ], *pbf = bf;
294 struct mmap_event mmap_ev = {
295 .header = { .type = PERF_RECORD_MMAP },
296 };
297 int n;
298 size_t size;
299 if (fgets(bf, sizeof(bf), fp) == NULL)
300 break;
301
302 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
303 n = hex2u64(pbf, &mmap_ev.start);
304 if (n < 0)
305 continue;
306 pbf += n + 1;
307 n = hex2u64(pbf, &mmap_ev.len);
308 if (n < 0)
309 continue;
310 pbf += n + 3;
311 if (*pbf == 'x') { /* vm_exec */
312 char *execname = strchr(bf, '/');
313
314 /* Catch VDSO */
315 if (execname == NULL)
316 execname = strstr(bf, "[vdso]");
317
318 if (execname == NULL)
319 continue;
320
321 size = strlen(execname);
322 execname[size - 1] = '\0'; /* Remove \n */
323 memcpy(mmap_ev.filename, execname, size);
324 size = ALIGN(size, sizeof(u64));
325 mmap_ev.len -= mmap_ev.start;
326 mmap_ev.header.size = (sizeof(mmap_ev) -
327 (sizeof(mmap_ev.filename) - size));
328 mmap_ev.pid = tgid;
329 mmap_ev.tid = pid;
330
331 write_output(&mmap_ev, mmap_ev.header.size);
332 }
333 }
334
335 fclose(fp);
336}
337
338static void synthesize_all(void)
339{
340 DIR *proc;
341 struct dirent dirent, *next;
342
343 proc = opendir("/proc");
344
345 while (!readdir_r(proc, &dirent, &next) && next) {
346 char *end;
347 pid_t pid, tgid;
348
349 pid = strtol(dirent.d_name, &end, 10);
350 if (*end) /* only interested in proper numerical dirents */
351 continue;
352
353 tgid = pid_synthesize_comm_event(pid, 1);
354 pid_synthesize_mmap_samples(pid, tgid);
355 }
356
357 closedir(proc);
358}
359
360static int group_fd; 200static int group_fd;
361 201
362static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr) 202static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr)
@@ -608,11 +448,10 @@ static int __cmd_record(int argc, const char **argv)
608 if (file_new) 448 if (file_new)
609 perf_header__write(header, output); 449 perf_header__write(header, output);
610 450
611 if (!system_wide) { 451 if (!system_wide)
612 pid_t tgid = pid_synthesize_comm_event(pid, 0); 452 event__synthesize_thread(pid, process_synthesized_event);
613 pid_synthesize_mmap_samples(pid, tgid); 453 else
614 } else 454 event__synthesize_threads(process_synthesized_event);
615 synthesize_all();
616 455
617 if (target_pid == -1 && argc) { 456 if (target_pid == -1 && argc) {
618 pid = fork(); 457 pid = fork();