15a8e0ff9SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
252050943SSteven Rostedt /*
352050943SSteven Rostedt * Copyright (C) 2008,2009, Steven Rostedt <srostedt@redhat.com>
452050943SSteven Rostedt */
552050943SSteven Rostedt #include <dirent.h>
6659d8cfbSUlrich Drepper #include <mntent.h>
752050943SSteven Rostedt #include <stdio.h>
852050943SSteven Rostedt #include <stdlib.h>
952050943SSteven Rostedt #include <string.h>
1052050943SSteven Rostedt #include <stdarg.h>
1152050943SSteven Rostedt #include <sys/types.h>
1252050943SSteven Rostedt #include <sys/stat.h>
1352050943SSteven Rostedt #include <sys/wait.h>
1452050943SSteven Rostedt #include <fcntl.h>
1552050943SSteven Rostedt #include <unistd.h>
1652050943SSteven Rostedt #include <errno.h>
171ef2ed10SFrederic Weisbecker #include <stdbool.h>
1869aad6f1SArnaldo Carvalho de Melo #include <linux/list.h>
19e2561368SArnaldo Carvalho de Melo #include <linux/kernel.h>
207f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h>
2120f2be1dSJiri Olsa #include <internal/lib.h> // page_size
229b7c7728SIan Rogers #include <sys/param.h>
2352050943SSteven Rostedt
2452050943SSteven Rostedt #include "trace-event.h"
259b7c7728SIan Rogers #include "tracepoint.h"
26592d5a6bSJiri Olsa #include <api/fs/tracing_path.h>
2769aad6f1SArnaldo Carvalho de Melo #include "evsel.h"
2884f5d36fSJiri Olsa #include "debug.h"
295b7a29fbSIan Rogers #include "util.h"
3052050943SSteven Rostedt
31cd4ceb63SNamhyung Kim #define VERSION "0.6"
329b7c7728SIan Rogers #define MAX_EVENT_LENGTH 512
3352050943SSteven Rostedt
3452050943SSteven Rostedt static int output_fd;
3552050943SSteven Rostedt
369b7c7728SIan Rogers struct tracepoint_path {
379b7c7728SIan Rogers char *system;
389b7c7728SIan Rogers char *name;
399b7c7728SIan Rogers struct tracepoint_path *next;
409b7c7728SIan Rogers };
4152050943SSteven Rostedt
42259032bfSSonny Rao /* unfortunately, you can not stat debugfs or proc files for size */
record_file(const char * file,ssize_t hdr_sz)438755d5e2SNamhyung Kim static int record_file(const char *file, ssize_t hdr_sz)
4452050943SSteven Rostedt {
4552050943SSteven Rostedt unsigned long long size = 0;
46259032bfSSonny Rao char buf[BUFSIZ], *sizep;
47259032bfSSonny Rao off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR);
48259032bfSSonny Rao int r, fd;
498755d5e2SNamhyung Kim int err = -EIO;
50259032bfSSonny Rao
51259032bfSSonny Rao fd = open(file, O_RDONLY);
527f42b950SNamhyung Kim if (fd < 0) {
537f42b950SNamhyung Kim pr_debug("Can't read '%s'", file);
547f42b950SNamhyung Kim return -errno;
557f42b950SNamhyung Kim }
56259032bfSSonny Rao
57259032bfSSonny Rao /* put in zeros for file size, then fill true size later */
588755d5e2SNamhyung Kim if (hdr_sz) {
598755d5e2SNamhyung Kim if (write(output_fd, &size, hdr_sz) != hdr_sz)
608755d5e2SNamhyung Kim goto out;
618755d5e2SNamhyung Kim }
6252050943SSteven Rostedt
6352050943SSteven Rostedt do {
6452050943SSteven Rostedt r = read(fd, buf, BUFSIZ);
6552050943SSteven Rostedt if (r > 0) {
6652050943SSteven Rostedt size += r;
678755d5e2SNamhyung Kim if (write(output_fd, buf, r) != r)
688755d5e2SNamhyung Kim goto out;
6952050943SSteven Rostedt }
7052050943SSteven Rostedt } while (r > 0);
7152050943SSteven Rostedt
72259032bfSSonny Rao /* ugh, handle big-endian hdr_size == 4 */
73259032bfSSonny Rao sizep = (char*)&size;
745b7a29fbSIan Rogers if (host_is_bigendian())
75259032bfSSonny Rao sizep += sizeof(u64) - hdr_sz;
7652050943SSteven Rostedt
777f42b950SNamhyung Kim if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) {
787f42b950SNamhyung Kim pr_debug("writing file size failed\n");
797f42b950SNamhyung Kim goto out;
807f42b950SNamhyung Kim }
818755d5e2SNamhyung Kim
828755d5e2SNamhyung Kim err = 0;
838755d5e2SNamhyung Kim out:
848755d5e2SNamhyung Kim close(fd);
858755d5e2SNamhyung Kim return err;
8652050943SSteven Rostedt }
8752050943SSteven Rostedt
record_header_files(void)88077f159dSNamhyung Kim static int record_header_files(void)
8952050943SSteven Rostedt {
9040c3c0c9SArnaldo Carvalho de Melo char *path = get_events_file("header_page");
91259032bfSSonny Rao struct stat st;
928755d5e2SNamhyung Kim int err = -EIO;
9352050943SSteven Rostedt
947f42b950SNamhyung Kim if (!path) {
957f42b950SNamhyung Kim pr_debug("can't get tracing/events/header_page");
967f42b950SNamhyung Kim return -ENOMEM;
977f42b950SNamhyung Kim }
98454f8c7dSNamhyung Kim
997f42b950SNamhyung Kim if (stat(path, &st) < 0) {
1007f42b950SNamhyung Kim pr_debug("can't read '%s'", path);
1017f42b950SNamhyung Kim goto out;
1027f42b950SNamhyung Kim }
10352050943SSteven Rostedt
1048755d5e2SNamhyung Kim if (write(output_fd, "header_page", 12) != 12) {
1058755d5e2SNamhyung Kim pr_debug("can't write header_page\n");
1068755d5e2SNamhyung Kim goto out;
1078755d5e2SNamhyung Kim }
1088755d5e2SNamhyung Kim
1098755d5e2SNamhyung Kim if (record_file(path, 8) < 0) {
1108755d5e2SNamhyung Kim pr_debug("can't record header_page file\n");
1118755d5e2SNamhyung Kim goto out;
1128755d5e2SNamhyung Kim }
1138755d5e2SNamhyung Kim
11440c3c0c9SArnaldo Carvalho de Melo put_events_file(path);
11552050943SSteven Rostedt
11640c3c0c9SArnaldo Carvalho de Melo path = get_events_file("header_event");
1177f42b950SNamhyung Kim if (!path) {
1187f42b950SNamhyung Kim pr_debug("can't get tracing/events/header_event");
1197f42b950SNamhyung Kim err = -ENOMEM;
1207f42b950SNamhyung Kim goto out;
1217f42b950SNamhyung Kim }
122454f8c7dSNamhyung Kim
1237f42b950SNamhyung Kim if (stat(path, &st) < 0) {
1247f42b950SNamhyung Kim pr_debug("can't read '%s'", path);
1257f42b950SNamhyung Kim goto out;
1267f42b950SNamhyung Kim }
12752050943SSteven Rostedt
1288755d5e2SNamhyung Kim if (write(output_fd, "header_event", 13) != 13) {
1298755d5e2SNamhyung Kim pr_debug("can't write header_event\n");
1308755d5e2SNamhyung Kim goto out;
1318755d5e2SNamhyung Kim }
1328755d5e2SNamhyung Kim
1338755d5e2SNamhyung Kim if (record_file(path, 8) < 0) {
1348755d5e2SNamhyung Kim pr_debug("can't record header_event file\n");
1358755d5e2SNamhyung Kim goto out;
1368755d5e2SNamhyung Kim }
1378755d5e2SNamhyung Kim
1388755d5e2SNamhyung Kim err = 0;
1398755d5e2SNamhyung Kim out:
14040c3c0c9SArnaldo Carvalho de Melo put_events_file(path);
1418755d5e2SNamhyung Kim return err;
14252050943SSteven Rostedt }
14352050943SSteven Rostedt
name_in_tp_list(char * sys,struct tracepoint_path * tps)1441ef2ed10SFrederic Weisbecker static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
1451ef2ed10SFrederic Weisbecker {
1461ef2ed10SFrederic Weisbecker while (tps) {
1471ef2ed10SFrederic Weisbecker if (!strcmp(sys, tps->name))
1481ef2ed10SFrederic Weisbecker return true;
1491ef2ed10SFrederic Weisbecker tps = tps->next;
1501ef2ed10SFrederic Weisbecker }
1511ef2ed10SFrederic Weisbecker
1521ef2ed10SFrederic Weisbecker return false;
1531ef2ed10SFrederic Weisbecker }
1541ef2ed10SFrederic Weisbecker
155d2e31d7eSIan Rogers #define for_each_event_tps(dir, dent, tps) \
15643d41debSTaeung Song while ((dent = readdir(dir))) \
15743d41debSTaeung Song if (dent->d_type == DT_DIR && \
15843d41debSTaeung Song (strcmp(dent->d_name, ".")) && \
15943d41debSTaeung Song (strcmp(dent->d_name, ".."))) \
16043d41debSTaeung Song
copy_event_system(const char * sys,struct tracepoint_path * tps)1615a6fd27aSNamhyung Kim static int copy_event_system(const char *sys, struct tracepoint_path *tps)
16252050943SSteven Rostedt {
16352050943SSteven Rostedt struct dirent *dent;
16452050943SSteven Rostedt struct stat st;
16552050943SSteven Rostedt char *format;
16652050943SSteven Rostedt DIR *dir;
16752050943SSteven Rostedt int count = 0;
16852050943SSteven Rostedt int ret;
1695a6fd27aSNamhyung Kim int err;
17052050943SSteven Rostedt
17152050943SSteven Rostedt dir = opendir(sys);
1727f42b950SNamhyung Kim if (!dir) {
1737f42b950SNamhyung Kim pr_debug("can't read directory '%s'", sys);
1747f42b950SNamhyung Kim return -errno;
1757f42b950SNamhyung Kim }
17652050943SSteven Rostedt
177d2e31d7eSIan Rogers for_each_event_tps(dir, dent, tps) {
17843d41debSTaeung Song if (!name_in_tp_list(dent->d_name, tps))
17952050943SSteven Rostedt continue;
18043d41debSTaeung Song
181d400a68dSAndy Shevchenko if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
1825a6fd27aSNamhyung Kim err = -ENOMEM;
1835a6fd27aSNamhyung Kim goto out;
1845a6fd27aSNamhyung Kim }
18552050943SSteven Rostedt ret = stat(format, &st);
18652050943SSteven Rostedt free(format);
18752050943SSteven Rostedt if (ret < 0)
18852050943SSteven Rostedt continue;
18952050943SSteven Rostedt count++;
19052050943SSteven Rostedt }
19152050943SSteven Rostedt
1928755d5e2SNamhyung Kim if (write(output_fd, &count, 4) != 4) {
1938755d5e2SNamhyung Kim err = -EIO;
1948755d5e2SNamhyung Kim pr_debug("can't write count\n");
1958755d5e2SNamhyung Kim goto out;
1968755d5e2SNamhyung Kim }
19752050943SSteven Rostedt
19852050943SSteven Rostedt rewinddir(dir);
199d2e31d7eSIan Rogers for_each_event_tps(dir, dent, tps) {
20043d41debSTaeung Song if (!name_in_tp_list(dent->d_name, tps))
20152050943SSteven Rostedt continue;
20243d41debSTaeung Song
203d400a68dSAndy Shevchenko if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
2045a6fd27aSNamhyung Kim err = -ENOMEM;
2055a6fd27aSNamhyung Kim goto out;
2065a6fd27aSNamhyung Kim }
20752050943SSteven Rostedt ret = stat(format, &st);
20852050943SSteven Rostedt
2098755d5e2SNamhyung Kim if (ret >= 0) {
2108755d5e2SNamhyung Kim err = record_file(format, 8);
2118755d5e2SNamhyung Kim if (err) {
2128755d5e2SNamhyung Kim free(format);
2138755d5e2SNamhyung Kim goto out;
2148755d5e2SNamhyung Kim }
2158755d5e2SNamhyung Kim }
21652050943SSteven Rostedt free(format);
21752050943SSteven Rostedt }
2185a6fd27aSNamhyung Kim err = 0;
2195a6fd27aSNamhyung Kim out:
2209967411eSXiao Guangrong closedir(dir);
2215a6fd27aSNamhyung Kim return err;
22252050943SSteven Rostedt }
22352050943SSteven Rostedt
record_ftrace_files(struct tracepoint_path * tps)224077f159dSNamhyung Kim static int record_ftrace_files(struct tracepoint_path *tps)
22552050943SSteven Rostedt {
22652050943SSteven Rostedt char *path;
2278755d5e2SNamhyung Kim int ret;
22852050943SSteven Rostedt
22940c3c0c9SArnaldo Carvalho de Melo path = get_events_file("ftrace");
2307f42b950SNamhyung Kim if (!path) {
2317f42b950SNamhyung Kim pr_debug("can't get tracing/events/ftrace");
2327f42b950SNamhyung Kim return -ENOMEM;
2337f42b950SNamhyung Kim }
23452050943SSteven Rostedt
2358755d5e2SNamhyung Kim ret = copy_event_system(path, tps);
23652050943SSteven Rostedt
23752050943SSteven Rostedt put_tracing_file(path);
2388755d5e2SNamhyung Kim
2398755d5e2SNamhyung Kim return ret;
24052050943SSteven Rostedt }
24152050943SSteven Rostedt
system_in_tp_list(char * sys,struct tracepoint_path * tps)2421ef2ed10SFrederic Weisbecker static bool system_in_tp_list(char *sys, struct tracepoint_path *tps)
2431ef2ed10SFrederic Weisbecker {
2441ef2ed10SFrederic Weisbecker while (tps) {
2451ef2ed10SFrederic Weisbecker if (!strcmp(sys, tps->system))
2461ef2ed10SFrederic Weisbecker return true;
2471ef2ed10SFrederic Weisbecker tps = tps->next;
2481ef2ed10SFrederic Weisbecker }
2491ef2ed10SFrederic Weisbecker
2501ef2ed10SFrederic Weisbecker return false;
2511ef2ed10SFrederic Weisbecker }
2521ef2ed10SFrederic Weisbecker
record_event_files(struct tracepoint_path * tps)253077f159dSNamhyung Kim static int record_event_files(struct tracepoint_path *tps)
25452050943SSteven Rostedt {
25552050943SSteven Rostedt struct dirent *dent;
25652050943SSteven Rostedt struct stat st;
25752050943SSteven Rostedt char *path;
25852050943SSteven Rostedt char *sys;
25952050943SSteven Rostedt DIR *dir;
26052050943SSteven Rostedt int count = 0;
26152050943SSteven Rostedt int ret;
2625a6fd27aSNamhyung Kim int err;
26352050943SSteven Rostedt
26452050943SSteven Rostedt path = get_tracing_file("events");
2657f42b950SNamhyung Kim if (!path) {
2667f42b950SNamhyung Kim pr_debug("can't get tracing/events");
2677f42b950SNamhyung Kim return -ENOMEM;
2687f42b950SNamhyung Kim }
26952050943SSteven Rostedt
27052050943SSteven Rostedt dir = opendir(path);
2717f42b950SNamhyung Kim if (!dir) {
2727f42b950SNamhyung Kim err = -errno;
2737f42b950SNamhyung Kim pr_debug("can't read directory '%s'", path);
2747f42b950SNamhyung Kim goto out;
2757f42b950SNamhyung Kim }
27652050943SSteven Rostedt
277d2e31d7eSIan Rogers for_each_event_tps(dir, dent, tps) {
27843d41debSTaeung Song if (strcmp(dent->d_name, "ftrace") == 0 ||
2791ef2ed10SFrederic Weisbecker !system_in_tp_list(dent->d_name, tps))
28052050943SSteven Rostedt continue;
28143d41debSTaeung Song
28252050943SSteven Rostedt count++;
28352050943SSteven Rostedt }
28452050943SSteven Rostedt
2858755d5e2SNamhyung Kim if (write(output_fd, &count, 4) != 4) {
2868755d5e2SNamhyung Kim err = -EIO;
2878755d5e2SNamhyung Kim pr_debug("can't write count\n");
2888755d5e2SNamhyung Kim goto out;
2898755d5e2SNamhyung Kim }
29052050943SSteven Rostedt
29152050943SSteven Rostedt rewinddir(dir);
292d2e31d7eSIan Rogers for_each_event_tps(dir, dent, tps) {
29343d41debSTaeung Song if (strcmp(dent->d_name, "ftrace") == 0 ||
2941ef2ed10SFrederic Weisbecker !system_in_tp_list(dent->d_name, tps))
29552050943SSteven Rostedt continue;
29643d41debSTaeung Song
297d400a68dSAndy Shevchenko if (asprintf(&sys, "%s/%s", path, dent->d_name) < 0) {
2985a6fd27aSNamhyung Kim err = -ENOMEM;
2995a6fd27aSNamhyung Kim goto out;
3005a6fd27aSNamhyung Kim }
30152050943SSteven Rostedt ret = stat(sys, &st);
30252050943SSteven Rostedt if (ret >= 0) {
3038755d5e2SNamhyung Kim ssize_t size = strlen(dent->d_name) + 1;
3048755d5e2SNamhyung Kim
3058755d5e2SNamhyung Kim if (write(output_fd, dent->d_name, size) != size ||
3068755d5e2SNamhyung Kim copy_event_system(sys, tps) < 0) {
3078755d5e2SNamhyung Kim err = -EIO;
3088755d5e2SNamhyung Kim free(sys);
3098755d5e2SNamhyung Kim goto out;
3108755d5e2SNamhyung Kim }
31152050943SSteven Rostedt }
31252050943SSteven Rostedt free(sys);
31352050943SSteven Rostedt }
3145a6fd27aSNamhyung Kim err = 0;
3155a6fd27aSNamhyung Kim out:
3169967411eSXiao Guangrong closedir(dir);
31752050943SSteven Rostedt put_tracing_file(path);
3185a6fd27aSNamhyung Kim
3195a6fd27aSNamhyung Kim return err;
32052050943SSteven Rostedt }
32152050943SSteven Rostedt
record_proc_kallsyms(void)322077f159dSNamhyung Kim static int record_proc_kallsyms(void)
32352050943SSteven Rostedt {
3246e5259e9SArnaldo Carvalho de Melo unsigned long long size = 0;
3256e5259e9SArnaldo Carvalho de Melo /*
3266e5259e9SArnaldo Carvalho de Melo * Just to keep older perf.data file parsers happy, record a zero
3276e5259e9SArnaldo Carvalho de Melo * sized kallsyms file, i.e. do the same thing that was done when
3286e5259e9SArnaldo Carvalho de Melo * /proc/kallsyms (or something specified via --kallsyms, in a
3296e5259e9SArnaldo Carvalho de Melo * different path) couldn't be read.
3306e5259e9SArnaldo Carvalho de Melo */
3316e5259e9SArnaldo Carvalho de Melo return write(output_fd, &size, 4) != 4 ? -EIO : 0;
33252050943SSteven Rostedt }
33352050943SSteven Rostedt
record_ftrace_printk(void)334077f159dSNamhyung Kim static int record_ftrace_printk(void)
33552050943SSteven Rostedt {
336259032bfSSonny Rao unsigned int size;
3376706ccf8SLi Zefan char *path;
33852050943SSteven Rostedt struct stat st;
3398755d5e2SNamhyung Kim int ret, err = 0;
34052050943SSteven Rostedt
34152050943SSteven Rostedt path = get_tracing_file("printk_formats");
3427f42b950SNamhyung Kim if (!path) {
3437f42b950SNamhyung Kim pr_debug("can't get tracing/printk_formats");
3447f42b950SNamhyung Kim return -ENOMEM;
3457f42b950SNamhyung Kim }
346454f8c7dSNamhyung Kim
34752050943SSteven Rostedt ret = stat(path, &st);
34852050943SSteven Rostedt if (ret < 0) {
34952050943SSteven Rostedt /* not found */
35052050943SSteven Rostedt size = 0;
3518755d5e2SNamhyung Kim if (write(output_fd, &size, 4) != 4)
3528755d5e2SNamhyung Kim err = -EIO;
3536706ccf8SLi Zefan goto out;
35452050943SSteven Rostedt }
3558755d5e2SNamhyung Kim err = record_file(path, 4);
356259032bfSSonny Rao
3576706ccf8SLi Zefan out:
3586706ccf8SLi Zefan put_tracing_file(path);
3598755d5e2SNamhyung Kim return err;
36052050943SSteven Rostedt }
36152050943SSteven Rostedt
record_saved_cmdline(void)362cd4ceb63SNamhyung Kim static int record_saved_cmdline(void)
363cd4ceb63SNamhyung Kim {
364a72f6426SChris Phlipot unsigned long long size;
365cd4ceb63SNamhyung Kim char *path;
366cd4ceb63SNamhyung Kim struct stat st;
367cd4ceb63SNamhyung Kim int ret, err = 0;
368cd4ceb63SNamhyung Kim
369cd4ceb63SNamhyung Kim path = get_tracing_file("saved_cmdlines");
370cd4ceb63SNamhyung Kim if (!path) {
371cd4ceb63SNamhyung Kim pr_debug("can't get tracing/saved_cmdline");
372cd4ceb63SNamhyung Kim return -ENOMEM;
373cd4ceb63SNamhyung Kim }
374cd4ceb63SNamhyung Kim
375cd4ceb63SNamhyung Kim ret = stat(path, &st);
376cd4ceb63SNamhyung Kim if (ret < 0) {
377cd4ceb63SNamhyung Kim /* not found */
378cd4ceb63SNamhyung Kim size = 0;
379cd4ceb63SNamhyung Kim if (write(output_fd, &size, 8) != 8)
380cd4ceb63SNamhyung Kim err = -EIO;
381cd4ceb63SNamhyung Kim goto out;
382cd4ceb63SNamhyung Kim }
383cd4ceb63SNamhyung Kim err = record_file(path, 8);
384cd4ceb63SNamhyung Kim
385cd4ceb63SNamhyung Kim out:
386cd4ceb63SNamhyung Kim put_tracing_file(path);
387cd4ceb63SNamhyung Kim return err;
388cd4ceb63SNamhyung Kim }
389cd4ceb63SNamhyung Kim
3907f42b950SNamhyung Kim static void
put_tracepoints_path(struct tracepoint_path * tps)3917f42b950SNamhyung Kim put_tracepoints_path(struct tracepoint_path *tps)
3927f42b950SNamhyung Kim {
3937f42b950SNamhyung Kim while (tps) {
3947f42b950SNamhyung Kim struct tracepoint_path *t = tps;
3957f42b950SNamhyung Kim
3967f42b950SNamhyung Kim tps = tps->next;
39774cf249dSArnaldo Carvalho de Melo zfree(&t->name);
39874cf249dSArnaldo Carvalho de Melo zfree(&t->system);
3997f42b950SNamhyung Kim free(t);
4007f42b950SNamhyung Kim }
4017f42b950SNamhyung Kim }
4027f42b950SNamhyung Kim
tracepoint_id_to_path(u64 config)4039b7c7728SIan Rogers static struct tracepoint_path *tracepoint_id_to_path(u64 config)
4049b7c7728SIan Rogers {
4059b7c7728SIan Rogers struct tracepoint_path *path = NULL;
4069b7c7728SIan Rogers DIR *sys_dir, *evt_dir;
4079b7c7728SIan Rogers struct dirent *sys_dirent, *evt_dirent;
4089b7c7728SIan Rogers char id_buf[24];
4099b7c7728SIan Rogers int fd;
4109b7c7728SIan Rogers u64 id;
4119b7c7728SIan Rogers char evt_path[MAXPATHLEN];
4129b7c7728SIan Rogers char *dir_path;
4139b7c7728SIan Rogers
4149b7c7728SIan Rogers sys_dir = tracing_events__opendir();
4159b7c7728SIan Rogers if (!sys_dir)
4169b7c7728SIan Rogers return NULL;
4179b7c7728SIan Rogers
4189b7c7728SIan Rogers for_each_subsystem(sys_dir, sys_dirent) {
4199b7c7728SIan Rogers dir_path = get_events_file(sys_dirent->d_name);
4209b7c7728SIan Rogers if (!dir_path)
4219b7c7728SIan Rogers continue;
4229b7c7728SIan Rogers evt_dir = opendir(dir_path);
4239b7c7728SIan Rogers if (!evt_dir)
4249b7c7728SIan Rogers goto next;
4259b7c7728SIan Rogers
4269b7c7728SIan Rogers for_each_event(dir_path, evt_dir, evt_dirent) {
4279b7c7728SIan Rogers
4289b7c7728SIan Rogers scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
4299b7c7728SIan Rogers evt_dirent->d_name);
4309b7c7728SIan Rogers fd = open(evt_path, O_RDONLY);
4319b7c7728SIan Rogers if (fd < 0)
4329b7c7728SIan Rogers continue;
4339b7c7728SIan Rogers if (read(fd, id_buf, sizeof(id_buf)) < 0) {
4349b7c7728SIan Rogers close(fd);
4359b7c7728SIan Rogers continue;
4369b7c7728SIan Rogers }
4379b7c7728SIan Rogers close(fd);
4389b7c7728SIan Rogers id = atoll(id_buf);
4399b7c7728SIan Rogers if (id == config) {
4409b7c7728SIan Rogers put_events_file(dir_path);
4419b7c7728SIan Rogers closedir(evt_dir);
4429b7c7728SIan Rogers closedir(sys_dir);
4439b7c7728SIan Rogers path = zalloc(sizeof(*path));
4449b7c7728SIan Rogers if (!path)
4459b7c7728SIan Rogers return NULL;
4469b7c7728SIan Rogers if (asprintf(&path->system, "%.*s",
4479b7c7728SIan Rogers MAX_EVENT_LENGTH, sys_dirent->d_name) < 0) {
4489b7c7728SIan Rogers free(path);
4499b7c7728SIan Rogers return NULL;
4509b7c7728SIan Rogers }
4519b7c7728SIan Rogers if (asprintf(&path->name, "%.*s",
4529b7c7728SIan Rogers MAX_EVENT_LENGTH, evt_dirent->d_name) < 0) {
4539b7c7728SIan Rogers zfree(&path->system);
4549b7c7728SIan Rogers free(path);
4559b7c7728SIan Rogers return NULL;
4569b7c7728SIan Rogers }
4579b7c7728SIan Rogers return path;
4589b7c7728SIan Rogers }
4599b7c7728SIan Rogers }
4609b7c7728SIan Rogers closedir(evt_dir);
4619b7c7728SIan Rogers next:
4629b7c7728SIan Rogers put_events_file(dir_path);
4639b7c7728SIan Rogers }
4649b7c7728SIan Rogers
4659b7c7728SIan Rogers closedir(sys_dir);
4669b7c7728SIan Rogers return NULL;
4679b7c7728SIan Rogers }
4689b7c7728SIan Rogers
tracepoint_id_to_name(u64 config)469*220f88b5SYang Jihong char *tracepoint_id_to_name(u64 config)
470*220f88b5SYang Jihong {
471*220f88b5SYang Jihong struct tracepoint_path *path = tracepoint_id_to_path(config);
472*220f88b5SYang Jihong char *buf = NULL;
473*220f88b5SYang Jihong
474*220f88b5SYang Jihong if (path && asprintf(&buf, "%s:%s", path->system, path->name) < 0)
475*220f88b5SYang Jihong buf = NULL;
476*220f88b5SYang Jihong
477*220f88b5SYang Jihong put_tracepoints_path(path);
478*220f88b5SYang Jihong return buf;
479*220f88b5SYang Jihong }
480*220f88b5SYang Jihong
tracepoint_name_to_path(const char * name)4819b7c7728SIan Rogers static struct tracepoint_path *tracepoint_name_to_path(const char *name)
4829b7c7728SIan Rogers {
4839b7c7728SIan Rogers struct tracepoint_path *path = zalloc(sizeof(*path));
4849b7c7728SIan Rogers char *str = strchr(name, ':');
4859b7c7728SIan Rogers
4869b7c7728SIan Rogers if (path == NULL || str == NULL) {
4879b7c7728SIan Rogers free(path);
4889b7c7728SIan Rogers return NULL;
4899b7c7728SIan Rogers }
4909b7c7728SIan Rogers
4919b7c7728SIan Rogers path->system = strndup(name, str - name);
4929b7c7728SIan Rogers path->name = strdup(str+1);
4939b7c7728SIan Rogers
4949b7c7728SIan Rogers if (path->system == NULL || path->name == NULL) {
4959b7c7728SIan Rogers zfree(&path->system);
4969b7c7728SIan Rogers zfree(&path->name);
4979b7c7728SIan Rogers zfree(&path);
4989b7c7728SIan Rogers }
4999b7c7728SIan Rogers
5009b7c7728SIan Rogers return path;
5019b7c7728SIan Rogers }
5029b7c7728SIan Rogers
5031ef2ed10SFrederic Weisbecker static struct tracepoint_path *
get_tracepoints_path(struct list_head * pattrs)50469aad6f1SArnaldo Carvalho de Melo get_tracepoints_path(struct list_head *pattrs)
5051ef2ed10SFrederic Weisbecker {
5061ef2ed10SFrederic Weisbecker struct tracepoint_path path, *ppath = &path;
50732dcd021SJiri Olsa struct evsel *pos;
50869aad6f1SArnaldo Carvalho de Melo int nr_tracepoints = 0;
5091ef2ed10SFrederic Weisbecker
510b27c4eceSJiri Olsa list_for_each_entry(pos, pattrs, core.node) {
5111fc632ceSJiri Olsa if (pos->core.attr.type != PERF_TYPE_TRACEPOINT)
5121ef2ed10SFrederic Weisbecker continue;
513e2561368SArnaldo Carvalho de Melo ++nr_tracepoints;
514e7c93f09SNamhyung Kim
515e7c93f09SNamhyung Kim if (pos->name) {
516e7c93f09SNamhyung Kim ppath->next = tracepoint_name_to_path(pos->name);
517e7c93f09SNamhyung Kim if (ppath->next)
518e7c93f09SNamhyung Kim goto next;
519e7c93f09SNamhyung Kim
520e7c93f09SNamhyung Kim if (strchr(pos->name, ':') == NULL)
521e7c93f09SNamhyung Kim goto try_id;
522e7c93f09SNamhyung Kim
523e7c93f09SNamhyung Kim goto error;
524e7c93f09SNamhyung Kim }
525e7c93f09SNamhyung Kim
526e7c93f09SNamhyung Kim try_id:
5271fc632ceSJiri Olsa ppath->next = tracepoint_id_to_path(pos->core.attr.config);
5287f42b950SNamhyung Kim if (!ppath->next) {
529e7c93f09SNamhyung Kim error:
5307f42b950SNamhyung Kim pr_debug("No memory to alloc tracepoints list\n");
531fa99ce82SLi Bin put_tracepoints_path(path.next);
5327f42b950SNamhyung Kim return NULL;
5337f42b950SNamhyung Kim }
534e7c93f09SNamhyung Kim next:
5351ef2ed10SFrederic Weisbecker ppath = ppath->next;
5361ef2ed10SFrederic Weisbecker }
5371ef2ed10SFrederic Weisbecker
538e2561368SArnaldo Carvalho de Melo return nr_tracepoints > 0 ? path.next : NULL;
5391ef2ed10SFrederic Weisbecker }
540e2561368SArnaldo Carvalho de Melo
have_tracepoints(struct list_head * pattrs)54169aad6f1SArnaldo Carvalho de Melo bool have_tracepoints(struct list_head *pattrs)
54263e0c771STom Zanussi {
54332dcd021SJiri Olsa struct evsel *pos;
544db620b1cSTom Zanussi
545b27c4eceSJiri Olsa list_for_each_entry(pos, pattrs, core.node)
5461fc632ceSJiri Olsa if (pos->core.attr.type == PERF_TYPE_TRACEPOINT)
547db620b1cSTom Zanussi return true;
548db620b1cSTom Zanussi
549db620b1cSTom Zanussi return false;
55063e0c771STom Zanussi }
55163e0c771STom Zanussi
tracing_data_header(void)5528755d5e2SNamhyung Kim static int tracing_data_header(void)
55352050943SSteven Rostedt {
55429208e57SJiri Olsa char buf[20];
5558755d5e2SNamhyung Kim ssize_t size;
556e2561368SArnaldo Carvalho de Melo
55729208e57SJiri Olsa /* just guessing this is someone's birthday.. ;) */
55852050943SSteven Rostedt buf[0] = 23;
55952050943SSteven Rostedt buf[1] = 8;
56052050943SSteven Rostedt buf[2] = 68;
56152050943SSteven Rostedt memcpy(buf + 3, "tracing", 7);
56252050943SSteven Rostedt
5638755d5e2SNamhyung Kim if (write(output_fd, buf, 10) != 10)
5648755d5e2SNamhyung Kim return -1;
56552050943SSteven Rostedt
5668755d5e2SNamhyung Kim size = strlen(VERSION) + 1;
5678755d5e2SNamhyung Kim if (write(output_fd, VERSION, size) != size)
5688755d5e2SNamhyung Kim return -1;
56952050943SSteven Rostedt
57052050943SSteven Rostedt /* save endian */
5715b7a29fbSIan Rogers if (host_is_bigendian())
57252050943SSteven Rostedt buf[0] = 1;
57352050943SSteven Rostedt else
57452050943SSteven Rostedt buf[0] = 0;
57552050943SSteven Rostedt
5768755d5e2SNamhyung Kim if (write(output_fd, buf, 1) != 1)
5778755d5e2SNamhyung Kim return -1;
57852050943SSteven Rostedt
57952050943SSteven Rostedt /* save size of long */
58052050943SSteven Rostedt buf[0] = sizeof(long);
5818755d5e2SNamhyung Kim if (write(output_fd, buf, 1) != 1)
5828755d5e2SNamhyung Kim return -1;
58352050943SSteven Rostedt
58452050943SSteven Rostedt /* save page_size */
5858755d5e2SNamhyung Kim if (write(output_fd, &page_size, 4) != 4)
5868755d5e2SNamhyung Kim return -1;
5878755d5e2SNamhyung Kim
5888755d5e2SNamhyung Kim return 0;
58929208e57SJiri Olsa }
59052050943SSteven Rostedt
tracing_data_get(struct list_head * pattrs,int fd,bool temp)59129208e57SJiri Olsa struct tracing_data *tracing_data_get(struct list_head *pattrs,
59229208e57SJiri Olsa int fd, bool temp)
59329208e57SJiri Olsa {
59429208e57SJiri Olsa struct tracepoint_path *tps;
59529208e57SJiri Olsa struct tracing_data *tdata;
5968755d5e2SNamhyung Kim int err;
59729208e57SJiri Olsa
59829208e57SJiri Olsa output_fd = fd;
59929208e57SJiri Olsa
60029208e57SJiri Olsa tps = get_tracepoints_path(pattrs);
60129208e57SJiri Olsa if (!tps)
60229208e57SJiri Olsa return NULL;
60329208e57SJiri Olsa
6045a6fd27aSNamhyung Kim tdata = malloc(sizeof(*tdata));
6055a6fd27aSNamhyung Kim if (!tdata)
6065a6fd27aSNamhyung Kim return NULL;
6075a6fd27aSNamhyung Kim
60829208e57SJiri Olsa tdata->temp = temp;
60929208e57SJiri Olsa tdata->size = 0;
61029208e57SJiri Olsa
61129208e57SJiri Olsa if (temp) {
61229208e57SJiri Olsa int temp_fd;
61329208e57SJiri Olsa
61429208e57SJiri Olsa snprintf(tdata->temp_file, sizeof(tdata->temp_file),
61529208e57SJiri Olsa "/tmp/perf-XXXXXX");
6167f42b950SNamhyung Kim if (!mkstemp(tdata->temp_file)) {
6177f42b950SNamhyung Kim pr_debug("Can't make temp file");
618faedbf3fSSanskriti Sharma free(tdata);
6197f42b950SNamhyung Kim return NULL;
6207f42b950SNamhyung Kim }
62129208e57SJiri Olsa
62229208e57SJiri Olsa temp_fd = open(tdata->temp_file, O_RDWR);
6237f42b950SNamhyung Kim if (temp_fd < 0) {
6247f42b950SNamhyung Kim pr_debug("Can't read '%s'", tdata->temp_file);
625faedbf3fSSanskriti Sharma free(tdata);
6267f42b950SNamhyung Kim return NULL;
6277f42b950SNamhyung Kim }
62829208e57SJiri Olsa
62929208e57SJiri Olsa /*
63029208e57SJiri Olsa * Set the temp file the default output, so all the
63129208e57SJiri Olsa * tracing data are stored into it.
63229208e57SJiri Olsa */
63329208e57SJiri Olsa output_fd = temp_fd;
63429208e57SJiri Olsa }
63529208e57SJiri Olsa
6368755d5e2SNamhyung Kim err = tracing_data_header();
6378755d5e2SNamhyung Kim if (err)
6388755d5e2SNamhyung Kim goto out;
639077f159dSNamhyung Kim err = record_header_files();
6408755d5e2SNamhyung Kim if (err)
6418755d5e2SNamhyung Kim goto out;
642077f159dSNamhyung Kim err = record_ftrace_files(tps);
6438755d5e2SNamhyung Kim if (err)
6448755d5e2SNamhyung Kim goto out;
645077f159dSNamhyung Kim err = record_event_files(tps);
6468755d5e2SNamhyung Kim if (err)
6478755d5e2SNamhyung Kim goto out;
648077f159dSNamhyung Kim err = record_proc_kallsyms();
6498755d5e2SNamhyung Kim if (err)
6508755d5e2SNamhyung Kim goto out;
651077f159dSNamhyung Kim err = record_ftrace_printk();
652cd4ceb63SNamhyung Kim if (err)
653cd4ceb63SNamhyung Kim goto out;
654cd4ceb63SNamhyung Kim err = record_saved_cmdline();
655e2561368SArnaldo Carvalho de Melo
6568755d5e2SNamhyung Kim out:
65729208e57SJiri Olsa /*
65829208e57SJiri Olsa * All tracing data are stored by now, we can restore
65929208e57SJiri Olsa * the default output file in case we used temp file.
66029208e57SJiri Olsa */
66129208e57SJiri Olsa if (temp) {
66229208e57SJiri Olsa tdata->size = lseek(output_fd, 0, SEEK_CUR);
66329208e57SJiri Olsa close(output_fd);
66429208e57SJiri Olsa output_fd = fd;
66552050943SSteven Rostedt }
6669215545eSTom Zanussi
66704662523SArnaldo Carvalho de Melo if (err)
66804662523SArnaldo Carvalho de Melo zfree(&tdata);
6698755d5e2SNamhyung Kim
67029208e57SJiri Olsa put_tracepoints_path(tps);
67129208e57SJiri Olsa return tdata;
67229208e57SJiri Olsa }
67329208e57SJiri Olsa
tracing_data_put(struct tracing_data * tdata)6748755d5e2SNamhyung Kim int tracing_data_put(struct tracing_data *tdata)
6759215545eSTom Zanussi {
6768755d5e2SNamhyung Kim int err = 0;
6778755d5e2SNamhyung Kim
67829208e57SJiri Olsa if (tdata->temp) {
6798755d5e2SNamhyung Kim err = record_file(tdata->temp_file, 0);
68029208e57SJiri Olsa unlink(tdata->temp_file);
68129208e57SJiri Olsa }
6829215545eSTom Zanussi
68329208e57SJiri Olsa free(tdata);
6848755d5e2SNamhyung Kim return err;
68529208e57SJiri Olsa }
6869215545eSTom Zanussi
read_tracing_data(int fd,struct list_head * pattrs)68729208e57SJiri Olsa int read_tracing_data(int fd, struct list_head *pattrs)
68829208e57SJiri Olsa {
6898755d5e2SNamhyung Kim int err;
69029208e57SJiri Olsa struct tracing_data *tdata;
6919215545eSTom Zanussi
69229208e57SJiri Olsa /*
69329208e57SJiri Olsa * We work over the real file, so we can write data
69429208e57SJiri Olsa * directly, no temp file is needed.
69529208e57SJiri Olsa */
69629208e57SJiri Olsa tdata = tracing_data_get(pattrs, fd, false);
69729208e57SJiri Olsa if (!tdata)
69829208e57SJiri Olsa return -ENOMEM;
69929208e57SJiri Olsa
7008755d5e2SNamhyung Kim err = tracing_data_put(tdata);
7018755d5e2SNamhyung Kim return err;
7029215545eSTom Zanussi }
703