diff options
Diffstat (limited to 'tools/perf/util/trace-event-info.c')
| -rw-r--r-- | tools/perf/util/trace-event-info.c | 380 | 
1 files changed, 242 insertions, 138 deletions
| diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index a8d81c35ef6..3917eb9a847 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -38,52 +38,20 @@  #include "../perf.h"  #include "trace-event.h" -#include "debugfs.h" +#include <lk/debugfs.h>  #include "evsel.h"  #define VERSION "0.5" -#define TRACE_CTRL	"tracing_on" -#define TRACE		"trace" -#define AVAILABLE	"available_tracers" -#define CURRENT		"current_tracer" -#define ITER_CTRL	"trace_options" -#define MAX_LATENCY	"tracing_max_latency" - -unsigned int page_size; - -static const char *output_file = "trace.info";  static int output_fd; -struct event_list { -	struct event_list *next; -	const char *event; -}; - -struct events { -	struct events *sibling; -	struct events *children; -	struct events *next; -	char *name; -}; - - -static void *malloc_or_die(unsigned int size) -{ -	void *data; - -	data = malloc(size); -	if (!data) -		die("malloc"); -	return data; -}  static const char *find_debugfs(void)  { -	const char *path = debugfs_mount(NULL); +	const char *path = perf_debugfs_mount(NULL);  	if (!path) -		die("Your kernel not support debugfs filesystem"); +		pr_debug("Your kernel does not support the debugfs filesystem");  	return path;  } @@ -102,8 +70,12 @@ static const char *find_tracing_dir(void)  		return tracing;  	debugfs = find_debugfs(); +	if (!debugfs) +		return NULL; -	tracing = malloc_or_die(strlen(debugfs) + 9); +	tracing = malloc(strlen(debugfs) + 9); +	if (!tracing) +		return NULL;  	sprintf(tracing, "%s/tracing", debugfs); @@ -120,7 +92,9 @@ static char *get_tracing_file(const char *name)  	if (!tracing)  		return NULL; -	file = malloc_or_die(strlen(tracing) + strlen(name) + 2); +	file = malloc(strlen(tracing) + strlen(name) + 2); +	if (!file) +		return NULL;  	sprintf(file, "%s/%s", tracing, name);  	return file; @@ -131,24 +105,6 @@ static void put_tracing_file(char *file)  	free(file);  } -static ssize_t calc_data_size; - -static ssize_t write_or_die(const void *buf, size_t len) -{ -	int ret; - -	if (calc_data_size) { -		calc_data_size += len; -		return len; -	} - -	ret = write(output_fd, buf, len); -	if (ret < 0) -		die("writing to '%s'", output_file); - -	return ret; -} -  int bigendian(void)  {  	unsigned char str[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0}; @@ -159,59 +115,106 @@ int bigendian(void)  }  /* unfortunately, you can not stat debugfs or proc files for size */ -static void record_file(const char *file, size_t hdr_sz) +static int record_file(const char *file, ssize_t hdr_sz)  {  	unsigned long long size = 0;  	char buf[BUFSIZ], *sizep;  	off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR);  	int r, fd; +	int err = -EIO;  	fd = open(file, O_RDONLY); -	if (fd < 0) -		die("Can't read '%s'", file); +	if (fd < 0) { +		pr_debug("Can't read '%s'", file); +		return -errno; +	}  	/* put in zeros for file size, then fill true size later */ -	if (hdr_sz) -		write_or_die(&size, hdr_sz); +	if (hdr_sz) { +		if (write(output_fd, &size, hdr_sz) != hdr_sz) +			goto out; +	}  	do {  		r = read(fd, buf, BUFSIZ);  		if (r > 0) {  			size += r; -			write_or_die(buf, r); +			if (write(output_fd, buf, r) != r) +				goto out;  		}  	} while (r > 0); -	close(fd);  	/* ugh, handle big-endian hdr_size == 4 */  	sizep = (char*)&size;  	if (bigendian())  		sizep += sizeof(u64) - hdr_sz; -	if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) -		die("writing to %s", output_file); +	if (hdr_sz && pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) { +		pr_debug("writing file size failed\n"); +		goto out; +	} + +	err = 0; +out: +	close(fd); +	return err;  } -static void read_header_files(void) +static int read_header_files(void)  {  	char *path;  	struct stat st; +	int err = -EIO;  	path = get_tracing_file("events/header_page"); -	if (stat(path, &st) < 0) -		die("can't read '%s'", path); +	if (!path) { +		pr_debug("can't get tracing/events/header_page"); +		return -ENOMEM; +	} + +	if (stat(path, &st) < 0) { +		pr_debug("can't read '%s'", path); +		goto out; +	} + +	if (write(output_fd, "header_page", 12) != 12) { +		pr_debug("can't write header_page\n"); +		goto out; +	} + +	if (record_file(path, 8) < 0) { +		pr_debug("can't record header_page file\n"); +		goto out; +	} -	write_or_die("header_page", 12); -	record_file(path, 8);  	put_tracing_file(path);  	path = get_tracing_file("events/header_event"); -	if (stat(path, &st) < 0) -		die("can't read '%s'", path); +	if (!path) { +		pr_debug("can't get tracing/events/header_event"); +		err = -ENOMEM; +		goto out; +	} + +	if (stat(path, &st) < 0) { +		pr_debug("can't read '%s'", path); +		goto out; +	} + +	if (write(output_fd, "header_event", 13) != 13) { +		pr_debug("can't write header_event\n"); +		goto out; +	} + +	if (record_file(path, 8) < 0) { +		pr_debug("can't record header_event file\n"); +		goto out; +	} -	write_or_die("header_event", 13); -	record_file(path, 8); +	err = 0; +out:  	put_tracing_file(path); +	return err;  }  static bool name_in_tp_list(char *sys, struct tracepoint_path *tps) @@ -225,7 +228,7 @@ static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)  	return false;  } -static void copy_event_system(const char *sys, struct tracepoint_path *tps) +static int copy_event_system(const char *sys, struct tracepoint_path *tps)  {  	struct dirent *dent;  	struct stat st; @@ -233,10 +236,13 @@ static void copy_event_system(const char *sys, struct tracepoint_path *tps)  	DIR *dir;  	int count = 0;  	int ret; +	int err;  	dir = opendir(sys); -	if (!dir) -		die("can't read directory '%s'", sys); +	if (!dir) { +		pr_debug("can't read directory '%s'", sys); +		return -errno; +	}  	while ((dent = readdir(dir))) {  		if (dent->d_type != DT_DIR || @@ -244,7 +250,11 @@ static void copy_event_system(const char *sys, struct tracepoint_path *tps)  		    strcmp(dent->d_name, "..") == 0 ||  		    !name_in_tp_list(dent->d_name, tps))  			continue; -		format = malloc_or_die(strlen(sys) + strlen(dent->d_name) + 10); +		format = malloc(strlen(sys) + strlen(dent->d_name) + 10); +		if (!format) { +			err = -ENOMEM; +			goto out; +		}  		sprintf(format, "%s/%s/format", sys, dent->d_name);  		ret = stat(format, &st);  		free(format); @@ -253,7 +263,11 @@ static void copy_event_system(const char *sys, struct tracepoint_path *tps)  		count++;  	} -	write_or_die(&count, 4); +	if (write(output_fd, &count, 4) != 4) { +		err = -EIO; +		pr_debug("can't write count\n"); +		goto out; +	}  	rewinddir(dir);  	while ((dent = readdir(dir))) { @@ -262,27 +276,45 @@ static void copy_event_system(const char *sys, struct tracepoint_path *tps)  		    strcmp(dent->d_name, "..") == 0 ||  		    !name_in_tp_list(dent->d_name, tps))  			continue; -		format = malloc_or_die(strlen(sys) + strlen(dent->d_name) + 10); +		format = malloc(strlen(sys) + strlen(dent->d_name) + 10); +		if (!format) { +			err = -ENOMEM; +			goto out; +		}  		sprintf(format, "%s/%s/format", sys, dent->d_name);  		ret = stat(format, &st); -		if (ret >= 0) -			record_file(format, 8); - +		if (ret >= 0) { +			err = record_file(format, 8); +			if (err) { +				free(format); +				goto out; +			} +		}  		free(format);  	} +	err = 0; +out:  	closedir(dir); +	return err;  } -static void read_ftrace_files(struct tracepoint_path *tps) +static int read_ftrace_files(struct tracepoint_path *tps)  {  	char *path; +	int ret;  	path = get_tracing_file("events/ftrace"); +	if (!path) { +		pr_debug("can't get tracing/events/ftrace"); +		return -ENOMEM; +	} -	copy_event_system(path, tps); +	ret = copy_event_system(path, tps);  	put_tracing_file(path); + +	return ret;  }  static bool system_in_tp_list(char *sys, struct tracepoint_path *tps) @@ -296,7 +328,7 @@ static bool system_in_tp_list(char *sys, struct tracepoint_path *tps)  	return false;  } -static void read_event_files(struct tracepoint_path *tps) +static int read_event_files(struct tracepoint_path *tps)  {  	struct dirent *dent;  	struct stat st; @@ -305,12 +337,20 @@ static void read_event_files(struct tracepoint_path *tps)  	DIR *dir;  	int count = 0;  	int ret; +	int err;  	path = get_tracing_file("events"); +	if (!path) { +		pr_debug("can't get tracing/events"); +		return -ENOMEM; +	}  	dir = opendir(path); -	if (!dir) -		die("can't read directory '%s'", path); +	if (!dir) { +		err = -errno; +		pr_debug("can't read directory '%s'", path); +		goto out; +	}  	while ((dent = readdir(dir))) {  		if (dent->d_type != DT_DIR || @@ -322,7 +362,11 @@ static void read_event_files(struct tracepoint_path *tps)  		count++;  	} -	write_or_die(&count, 4); +	if (write(output_fd, &count, 4) != 4) { +		err = -EIO; +		pr_debug("can't write count\n"); +		goto out; +	}  	rewinddir(dir);  	while ((dent = readdir(dir))) { @@ -332,56 +376,90 @@ static void read_event_files(struct tracepoint_path *tps)  		    strcmp(dent->d_name, "ftrace") == 0 ||  		    !system_in_tp_list(dent->d_name, tps))  			continue; -		sys = malloc_or_die(strlen(path) + strlen(dent->d_name) + 2); +		sys = malloc(strlen(path) + strlen(dent->d_name) + 2); +		if (!sys) { +			err = -ENOMEM; +			goto out; +		}  		sprintf(sys, "%s/%s", path, dent->d_name);  		ret = stat(sys, &st);  		if (ret >= 0) { -			write_or_die(dent->d_name, strlen(dent->d_name) + 1); -			copy_event_system(sys, tps); +			ssize_t size = strlen(dent->d_name) + 1; + +			if (write(output_fd, dent->d_name, size) != size || +			    copy_event_system(sys, tps) < 0) { +				err = -EIO; +				free(sys); +				goto out; +			}  		}  		free(sys);  	} - +	err = 0; +out:  	closedir(dir);  	put_tracing_file(path); + +	return err;  } -static void read_proc_kallsyms(void) +static int read_proc_kallsyms(void)  {  	unsigned int size;  	const char *path = "/proc/kallsyms";  	struct stat st; -	int ret; +	int ret, err = 0;  	ret = stat(path, &st);  	if (ret < 0) {  		/* not found */  		size = 0; -		write_or_die(&size, 4); -		return; +		if (write(output_fd, &size, 4) != 4) +			err = -EIO; +		return err;  	} -	record_file(path, 4); +	return record_file(path, 4);  } -static void read_ftrace_printk(void) +static int read_ftrace_printk(void)  {  	unsigned int size;  	char *path;  	struct stat st; -	int ret; +	int ret, err = 0;  	path = get_tracing_file("printk_formats"); +	if (!path) { +		pr_debug("can't get tracing/printk_formats"); +		return -ENOMEM; +	} +  	ret = stat(path, &st);  	if (ret < 0) {  		/* not found */  		size = 0; -		write_or_die(&size, 4); +		if (write(output_fd, &size, 4) != 4) +			err = -EIO;  		goto out;  	} -	record_file(path, 4); +	err = record_file(path, 4);  out:  	put_tracing_file(path); +	return err; +} + +static void +put_tracepoints_path(struct tracepoint_path *tps) +{ +	while (tps) { +		struct tracepoint_path *t = tps; + +		tps = tps->next; +		free(t->name); +		free(t->system); +		free(t); +	}  }  static struct tracepoint_path * @@ -396,27 +474,17 @@ get_tracepoints_path(struct list_head *pattrs)  			continue;  		++nr_tracepoints;  		ppath->next = tracepoint_id_to_path(pos->attr.config); -		if (!ppath->next) -			die("%s\n", "No memory to alloc tracepoints list"); +		if (!ppath->next) { +			pr_debug("No memory to alloc tracepoints list\n"); +			put_tracepoints_path(&path); +			return NULL; +		}  		ppath = ppath->next;  	}  	return nr_tracepoints > 0 ? path.next : NULL;  } -static void -put_tracepoints_path(struct tracepoint_path *tps) -{ -	while (tps) { -		struct tracepoint_path *t = tps; - -		tps = tps->next; -		free(t->name); -		free(t->system); -		free(t); -	} -} -  bool have_tracepoints(struct list_head *pattrs)  {  	struct perf_evsel *pos; @@ -428,9 +496,10 @@ bool have_tracepoints(struct list_head *pattrs)  	return false;  } -static void tracing_data_header(void) +static int tracing_data_header(void)  {  	char buf[20]; +	ssize_t size;  	/* just guessing this is someone's birthday.. ;) */  	buf[0] = 23; @@ -438,9 +507,12 @@ static void tracing_data_header(void)  	buf[2] = 68;  	memcpy(buf + 3, "tracing", 7); -	write_or_die(buf, 10); +	if (write(output_fd, buf, 10) != 10) +		return -1; -	write_or_die(VERSION, strlen(VERSION) + 1); +	size = strlen(VERSION) + 1; +	if (write(output_fd, VERSION, size) != size) +		return -1;  	/* save endian */  	if (bigendian()) @@ -450,15 +522,19 @@ static void tracing_data_header(void)  	read_trace_init(buf[0], buf[0]); -	write_or_die(buf, 1); +	if (write(output_fd, buf, 1) != 1) +		return -1;  	/* save size of long */  	buf[0] = sizeof(long); -	write_or_die(buf, 1); +	if (write(output_fd, buf, 1) != 1) +		return -1;  	/* save page_size */ -	page_size = sysconf(_SC_PAGESIZE); -	write_or_die(&page_size, 4); +	if (write(output_fd, &page_size, 4) != 4) +		return -1; + +	return 0;  }  struct tracing_data *tracing_data_get(struct list_head *pattrs, @@ -466,6 +542,7 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,  {  	struct tracepoint_path *tps;  	struct tracing_data *tdata; +	int err;  	output_fd = fd; @@ -473,7 +550,10 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,  	if (!tps)  		return NULL; -	tdata = malloc_or_die(sizeof(*tdata)); +	tdata = malloc(sizeof(*tdata)); +	if (!tdata) +		return NULL; +  	tdata->temp = temp;  	tdata->size = 0; @@ -482,12 +562,16 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,  		snprintf(tdata->temp_file, sizeof(tdata->temp_file),  			 "/tmp/perf-XXXXXX"); -		if (!mkstemp(tdata->temp_file)) -			die("Can't make temp file"); +		if (!mkstemp(tdata->temp_file)) { +			pr_debug("Can't make temp file"); +			return NULL; +		}  		temp_fd = open(tdata->temp_file, O_RDWR); -		if (temp_fd < 0) -			die("Can't read '%s'", tdata->temp_file); +		if (temp_fd < 0) { +			pr_debug("Can't read '%s'", tdata->temp_file); +			return NULL; +		}  		/*  		 * Set the temp file the default output, so all the @@ -496,13 +580,24 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,  		output_fd = temp_fd;  	} -	tracing_data_header(); -	read_header_files(); -	read_ftrace_files(tps); -	read_event_files(tps); -	read_proc_kallsyms(); -	read_ftrace_printk(); +	err = tracing_data_header(); +	if (err) +		goto out; +	err = read_header_files(); +	if (err) +		goto out; +	err = read_ftrace_files(tps); +	if (err) +		goto out; +	err = read_event_files(tps); +	if (err) +		goto out; +	err = read_proc_kallsyms(); +	if (err) +		goto out; +	err = read_ftrace_printk(); +out:  	/*  	 * All tracing data are stored by now, we can restore  	 * the default output file in case we used temp file. @@ -513,22 +608,31 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,  		output_fd = fd;  	} +	if (err) { +		free(tdata); +		tdata = NULL; +	} +  	put_tracepoints_path(tps);  	return tdata;  } -void tracing_data_put(struct tracing_data *tdata) +int tracing_data_put(struct tracing_data *tdata)  { +	int err = 0; +  	if (tdata->temp) { -		record_file(tdata->temp_file, 0); +		err = record_file(tdata->temp_file, 0);  		unlink(tdata->temp_file);  	}  	free(tdata); +	return err;  }  int read_tracing_data(int fd, struct list_head *pattrs)  { +	int err;  	struct tracing_data *tdata;  	/* @@ -539,6 +643,6 @@ int read_tracing_data(int fd, struct list_head *pattrs)  	if (!tdata)  		return -ENOMEM; -	tracing_data_put(tdata); -	return 0; +	err = tracing_data_put(tdata); +	return err;  } |