diff options
Diffstat (limited to 'tools/perf/util/trace-event-read.c')
| -rw-r--r-- | tools/perf/util/trace-event-read.c | 469 | 
1 files changed, 175 insertions, 294 deletions
| diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 3741572696a..af215c0d237 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -18,8 +18,6 @@   *   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   */ -#define _FILE_OFFSET_BITS 64 -  #include <dirent.h>  #include <stdio.h>  #include <stdlib.h> @@ -41,26 +39,14 @@  static int input_fd; -static int read_page; -  int file_bigendian;  int host_bigendian;  static int long_size; -static ssize_t calc_data_size; +static ssize_t trace_data_size;  static bool repipe; -static void *malloc_or_die(int size) -{ -	void *ret; - -	ret = malloc(size); -	if (!ret) -		die("malloc"); -	return ret; -} - -static int do_read(int fd, void *buf, int size) +static int __do_read(int fd, void *buf, int size)  {  	int rsize = size; @@ -73,8 +59,10 @@ static int do_read(int fd, void *buf, int size)  		if (repipe) {  			int retw = write(STDOUT_FILENO, buf, ret); -			if (retw <= 0 || retw != ret) -				die("repiping input file"); +			if (retw <= 0 || retw != ret) { +				pr_debug("repiping input file"); +				return -1; +			}  		}  		size -= ret; @@ -84,17 +72,18 @@ static int do_read(int fd, void *buf, int size)  	return rsize;  } -static int read_or_die(void *data, int size) +static int do_read(void *data, int size)  {  	int r; -	r = do_read(input_fd, data, size); -	if (r <= 0) -		die("reading input file (size expected=%d received=%d)", -		    size, r); +	r = __do_read(input_fd, data, size); +	if (r <= 0) { +		pr_debug("reading input file (size expected=%d received=%d)", +			 size, r); +		return -1; +	} -	if (calc_data_size) -		calc_data_size += r; +	trace_data_size += r;  	return r;  } @@ -107,7 +96,7 @@ static void skip(int size)  	while (size) {  		r = size > BUFSIZ ? BUFSIZ : size; -		read_or_die(buf, r); +		do_read(buf, r);  		size -= r;  	};  } @@ -116,7 +105,8 @@ static unsigned int read4(struct pevent *pevent)  {  	unsigned int data; -	read_or_die(&data, 4); +	if (do_read(&data, 4) < 0) +		return 0;  	return __data2host4(pevent, data);  } @@ -124,7 +114,8 @@ static unsigned long long read8(struct pevent *pevent)  {  	unsigned long long data; -	read_or_die(&data, 8); +	if (do_read(&data, 8) < 0) +		return 0;  	return __data2host8(pevent, data);  } @@ -138,17 +129,23 @@ static char *read_string(void)  	for (;;) {  		r = read(input_fd, &c, 1); -		if (r < 0) -			die("reading input file"); +		if (r < 0) { +			pr_debug("reading input file"); +			goto out; +		} -		if (!r) -			die("no data"); +		if (!r) { +			pr_debug("no data"); +			goto out; +		}  		if (repipe) {  			int retw = write(STDOUT_FILENO, &c, 1); -			if (retw <= 0 || retw != r) -				die("repiping input file string"); +			if (retw <= 0 || retw != r) { +				pr_debug("repiping input file string"); +				goto out; +			}  		}  		buf[size++] = c; @@ -157,60 +154,79 @@ static char *read_string(void)  			break;  	} -	if (calc_data_size) -		calc_data_size += size; - -	str = malloc_or_die(size); -	memcpy(str, buf, size); +	trace_data_size += size; +	str = malloc(size); +	if (str) +		memcpy(str, buf, size); +out:  	return str;  } -static void read_proc_kallsyms(struct pevent *pevent) +static int read_proc_kallsyms(struct pevent *pevent)  {  	unsigned int size;  	char *buf;  	size = read4(pevent);  	if (!size) -		return; +		return 0; + +	buf = malloc(size + 1); +	if (buf == NULL) +		return -1; -	buf = malloc_or_die(size + 1); -	read_or_die(buf, size); +	if (do_read(buf, size) < 0) { +		free(buf); +		return -1; +	}  	buf[size] = '\0';  	parse_proc_kallsyms(pevent, buf, size);  	free(buf); +	return 0;  } -static void read_ftrace_printk(struct pevent *pevent) +static int read_ftrace_printk(struct pevent *pevent)  {  	unsigned int size;  	char *buf; +	/* it can have 0 size */  	size = read4(pevent);  	if (!size) -		return; +		return 0; + +	buf = malloc(size); +	if (buf == NULL) +		return -1; -	buf = malloc_or_die(size); -	read_or_die(buf, size); +	if (do_read(buf, size) < 0) { +		free(buf); +		return -1; +	}  	parse_ftrace_printk(pevent, buf, size);  	free(buf); +	return 0;  } -static void read_header_files(struct pevent *pevent) +static int read_header_files(struct pevent *pevent)  {  	unsigned long long size;  	char *header_event;  	char buf[BUFSIZ]; +	int ret = 0; -	read_or_die(buf, 12); +	if (do_read(buf, 12) < 0) +		return -1; -	if (memcmp(buf, "header_page", 12) != 0) -		die("did not read header page"); +	if (memcmp(buf, "header_page", 12) != 0) { +		pr_debug("did not read header page"); +		return -1; +	}  	size = read8(pevent);  	skip(size); @@ -221,269 +237,107 @@ static void read_header_files(struct pevent *pevent)  	 */  	long_size = header_page_size_size; -	read_or_die(buf, 13); -	if (memcmp(buf, "header_event", 13) != 0) -		die("did not read header event"); +	if (do_read(buf, 13) < 0) +		return -1; + +	if (memcmp(buf, "header_event", 13) != 0) { +		pr_debug("did not read header event"); +		return -1; +	}  	size = read8(pevent); -	header_event = malloc_or_die(size); -	read_or_die(header_event, size); +	header_event = malloc(size); +	if (header_event == NULL) +		return -1; + +	if (do_read(header_event, size) < 0) +		ret = -1; +  	free(header_event); +	return ret;  } -static void read_ftrace_file(struct pevent *pevent, unsigned long long size) +static int read_ftrace_file(struct pevent *pevent, unsigned long long size)  {  	char *buf; -	buf = malloc_or_die(size); -	read_or_die(buf, size); +	buf = malloc(size); +	if (buf == NULL) +		return -1; + +	if (do_read(buf, size) < 0) { +		free(buf); +		return -1; +	} +  	parse_ftrace_file(pevent, buf, size);  	free(buf); +	return 0;  } -static void read_event_file(struct pevent *pevent, char *sys, +static int read_event_file(struct pevent *pevent, char *sys,  			    unsigned long long size)  {  	char *buf; -	buf = malloc_or_die(size); -	read_or_die(buf, size); +	buf = malloc(size); +	if (buf == NULL) +		return -1; + +	if (do_read(buf, size) < 0) { +		free(buf); +		return -1; +	} +  	parse_event_file(pevent, buf, size, sys);  	free(buf); +	return 0;  } -static void read_ftrace_files(struct pevent *pevent) +static int read_ftrace_files(struct pevent *pevent)  {  	unsigned long long size;  	int count;  	int i; +	int ret;  	count = read4(pevent);  	for (i = 0; i < count; i++) {  		size = read8(pevent); -		read_ftrace_file(pevent, size); +		ret = read_ftrace_file(pevent, size); +		if (ret) +			return ret;  	} +	return 0;  } -static void read_event_files(struct pevent *pevent) +static int read_event_files(struct pevent *pevent)  {  	unsigned long long size;  	char *sys;  	int systems;  	int count;  	int i,x; +	int ret;  	systems = read4(pevent);  	for (i = 0; i < systems; i++) {  		sys = read_string(); +		if (sys == NULL) +			return -1;  		count = read4(pevent); +  		for (x=0; x < count; x++) {  			size = read8(pevent); -			read_event_file(pevent, sys, size); -		} -	} -} - -struct cpu_data { -	unsigned long long	offset; -	unsigned long long	size; -	unsigned long long	timestamp; -	struct pevent_record	*next; -	char			*page; -	int			cpu; -	int			index; -	int			page_size; -}; - -static struct cpu_data *cpu_data; - -static void update_cpu_data_index(int cpu) -{ -	cpu_data[cpu].offset += page_size; -	cpu_data[cpu].size -= page_size; -	cpu_data[cpu].index = 0; -} - -static void get_next_page(int cpu) -{ -	off_t save_seek; -	off_t ret; - -	if (!cpu_data[cpu].page) -		return; - -	if (read_page) { -		if (cpu_data[cpu].size <= page_size) { -			free(cpu_data[cpu].page); -			cpu_data[cpu].page = NULL; -			return; -		} - -		update_cpu_data_index(cpu); - -		/* other parts of the code may expect the pointer to not move */ -		save_seek = lseek(input_fd, 0, SEEK_CUR); - -		ret = lseek(input_fd, cpu_data[cpu].offset, SEEK_SET); -		if (ret == (off_t)-1) -			die("failed to lseek"); -		ret = read(input_fd, cpu_data[cpu].page, page_size); -		if (ret < 0) -			die("failed to read page"); - -		/* reset the file pointer back */ -		lseek(input_fd, save_seek, SEEK_SET); - -		return; -	} - -	munmap(cpu_data[cpu].page, page_size); -	cpu_data[cpu].page = NULL; - -	if (cpu_data[cpu].size <= page_size) -		return; - -	update_cpu_data_index(cpu); - -	cpu_data[cpu].page = mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, -				  input_fd, cpu_data[cpu].offset); -	if (cpu_data[cpu].page == MAP_FAILED) -		die("failed to mmap cpu %d at offset 0x%llx", -		    cpu, cpu_data[cpu].offset); -} - -static unsigned int type_len4host(unsigned int type_len_ts) -{ -	if (file_bigendian) -		return (type_len_ts >> 27) & ((1 << 5) - 1); -	else -		return type_len_ts & ((1 << 5) - 1); -} - -static unsigned int ts4host(unsigned int type_len_ts) -{ -	if (file_bigendian) -		return type_len_ts & ((1 << 27) - 1); -	else -		return type_len_ts >> 5; -} - -static int calc_index(void *ptr, int cpu) -{ -	return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page; -} - -struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu) -{ -	struct pevent_record *data; -	void *page = cpu_data[cpu].page; -	int idx = cpu_data[cpu].index; -	void *ptr = page + idx; -	unsigned long long extend; -	unsigned int type_len_ts; -	unsigned int type_len; -	unsigned int delta; -	unsigned int length = 0; - -	if (cpu_data[cpu].next) -		return cpu_data[cpu].next; - -	if (!page) -		return NULL; - -	if (!idx) { -		/* FIXME: handle header page */ -		if (header_page_ts_size != 8) -			die("expected a long long type for timestamp"); -		cpu_data[cpu].timestamp = data2host8(pevent, ptr); -		ptr += 8; -		switch (header_page_size_size) { -		case 4: -			cpu_data[cpu].page_size = data2host4(pevent, ptr); -			ptr += 4; -			break; -		case 8: -			cpu_data[cpu].page_size = data2host8(pevent, ptr); -			ptr += 8; -			break; -		default: -			die("bad long size"); +			ret = read_event_file(pevent, sys, size); +			if (ret) +				return ret;  		} -		ptr = cpu_data[cpu].page + header_page_data_offset; -	} - -read_again: -	idx = calc_index(ptr, cpu); - -	if (idx >= cpu_data[cpu].page_size) { -		get_next_page(cpu); -		return trace_peek_data(pevent, cpu);  	} - -	type_len_ts = data2host4(pevent, ptr); -	ptr += 4; - -	type_len = type_len4host(type_len_ts); -	delta = ts4host(type_len_ts); - -	switch (type_len) { -	case RINGBUF_TYPE_PADDING: -		if (!delta) -			die("error, hit unexpected end of page"); -		length = data2host4(pevent, ptr); -		ptr += 4; -		length *= 4; -		ptr += length; -		goto read_again; - -	case RINGBUF_TYPE_TIME_EXTEND: -		extend = data2host4(pevent, ptr); -		ptr += 4; -		extend <<= TS_SHIFT; -		extend += delta; -		cpu_data[cpu].timestamp += extend; -		goto read_again; - -	case RINGBUF_TYPE_TIME_STAMP: -		ptr += 12; -		break; -	case 0: -		length = data2host4(pevent, ptr); -		ptr += 4; -		die("here! length=%d", length); -		break; -	default: -		length = type_len * 4; -		break; -	} - -	cpu_data[cpu].timestamp += delta; - -	data = malloc_or_die(sizeof(*data)); -	memset(data, 0, sizeof(*data)); - -	data->ts = cpu_data[cpu].timestamp; -	data->size = length; -	data->data = ptr; -	ptr += length; - -	cpu_data[cpu].index = calc_index(ptr, cpu); -	cpu_data[cpu].next = data; - -	return data; -} - -struct pevent_record *trace_read_data(struct pevent *pevent, int cpu) -{ -	struct pevent_record *data; - -	data = trace_peek_data(pevent, cpu); -	cpu_data[cpu].next = NULL; - -	return data; +	return 0;  }  ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) @@ -494,58 +348,85 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)  	int show_version = 0;  	int show_funcs = 0;  	int show_printk = 0; -	ssize_t size; +	ssize_t size = -1; +	struct pevent *pevent; +	int err; -	calc_data_size = 1; -	repipe = __repipe; +	*ppevent = NULL; +	repipe = __repipe;  	input_fd = fd; -	read_or_die(buf, 3); -	if (memcmp(buf, test, 3) != 0) -		die("no trace data in the file"); +	if (do_read(buf, 3) < 0) +		return -1; +	if (memcmp(buf, test, 3) != 0) { +		pr_debug("no trace data in the file"); +		return -1; +	} -	read_or_die(buf, 7); -	if (memcmp(buf, "tracing", 7) != 0) -		die("not a trace file (missing 'tracing' tag)"); +	if (do_read(buf, 7) < 0) +		return -1; +	if (memcmp(buf, "tracing", 7) != 0) { +		pr_debug("not a trace file (missing 'tracing' tag)"); +		return -1; +	}  	version = read_string(); +	if (version == NULL) +		return -1;  	if (show_version)  		printf("version = %s\n", version);  	free(version); -	read_or_die(buf, 1); +	if (do_read(buf, 1) < 0) +		return -1;  	file_bigendian = buf[0];  	host_bigendian = bigendian(); -	*ppevent = read_trace_init(file_bigendian, host_bigendian); -	if (*ppevent == NULL) -		die("read_trace_init failed"); +	pevent = read_trace_init(file_bigendian, host_bigendian); +	if (pevent == NULL) { +		pr_debug("read_trace_init failed"); +		goto out; +	} -	read_or_die(buf, 1); +	if (do_read(buf, 1) < 0) +		goto out;  	long_size = buf[0]; -	page_size = read4(*ppevent); +	page_size = read4(pevent); +	if (!page_size) +		goto out; -	read_header_files(*ppevent); +	err = read_header_files(pevent); +	if (err) +		goto out; +	err = read_ftrace_files(pevent); +	if (err) +		goto out; +	err = read_event_files(pevent); +	if (err) +		goto out; +	err = read_proc_kallsyms(pevent); +	if (err) +		goto out; +	err = read_ftrace_printk(pevent); +	if (err) +		goto out; -	read_ftrace_files(*ppevent); -	read_event_files(*ppevent); -	read_proc_kallsyms(*ppevent); -	read_ftrace_printk(*ppevent); - -	size = calc_data_size - 1; -	calc_data_size = 0; +	size = trace_data_size;  	repipe = false;  	if (show_funcs) { -		pevent_print_funcs(*ppevent); -		return size; -	} -	if (show_printk) { -		pevent_print_printk(*ppevent); -		return size; +		pevent_print_funcs(pevent); +	} else if (show_printk) { +		pevent_print_printk(pevent);  	} +	*ppevent = pevent; +	pevent = NULL; + +out: +	if (pevent) +		pevent_free(pevent);  	return size;  } |