xref: /openbmc/linux/tools/perf/util/trace-event-info.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
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