diff options
Diffstat (limited to 'tools/perf/util/probe-event.c')
| -rw-r--r-- | tools/perf/util/probe-event.c | 108 | 
1 files changed, 107 insertions, 1 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 29465d44004..8f056884969 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -37,6 +37,8 @@  #include "string.h"  #include "strlist.h"  #include "debug.h" +#include "cache.h" +#include "color.h"  #include "parse-events.h"  /* For debugfs_path */  #include "probe-event.h" @@ -62,6 +64,42 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)  	return ret;  } +void parse_line_range_desc(const char *arg, struct line_range *lr) +{ +	const char *ptr; +	char *tmp; +	/* +	 * <Syntax> +	 * SRC:SLN[+NUM|-ELN] +	 * FUNC[:SLN[+NUM|-ELN]] +	 */ +	ptr = strchr(arg, ':'); +	if (ptr) { +		lr->start = (unsigned int)strtoul(ptr + 1, &tmp, 0); +		if (*tmp == '+') +			lr->end = lr->start + (unsigned int)strtoul(tmp + 1, +								    &tmp, 0); +		else if (*tmp == '-') +			lr->end = (unsigned int)strtoul(tmp + 1, &tmp, 0); +		else +			lr->end = 0; +		pr_debug("Line range is %u to %u\n", lr->start, lr->end); +		if (lr->end && lr->start > lr->end) +			semantic_error("Start line must be smaller" +				       " than end line."); +		if (*tmp != '\0') +			semantic_error("Tailing with invalid character '%d'.", +				       *tmp); +		tmp = strndup(arg, (ptr - arg)); +	} else +		tmp = strdup(arg); + +	if (strchr(tmp, '.')) +		lr->file = tmp; +	else +		lr->function = tmp; +} +  /* Check the name is good for event/group */  static bool check_event_name(const char *name)  { @@ -272,6 +310,7 @@ int synthesize_perf_probe_point(struct probe_point *pp)  	int ret;  	pp->probes[0] = buf = zalloc(MAX_CMDLEN); +	pp->found = 1;  	if (!buf)  		die("Failed to allocate memory by zalloc.");  	if (pp->offset) { @@ -294,6 +333,7 @@ int synthesize_perf_probe_point(struct probe_point *pp)  error:  		free(pp->probes[0]);  		pp->probes[0] = NULL; +		pp->found = 0;  	}  	return ret;  } @@ -368,7 +408,7 @@ static int open_kprobe_events(int flags, int mode)  	if (ret < 0) {  		if (errno == ENOENT)  			die("kprobe_events file does not exist -" -			    " please rebuild with CONFIG_KPROBE_TRACER."); +			    " please rebuild with CONFIG_KPROBE_EVENT.");  		else  			die("Could not open kprobe_events file: %s",  			    strerror(errno)); @@ -455,6 +495,9 @@ void show_perf_probe_events(void)  	struct strlist *rawlist;  	struct str_node *ent; +	setup_pager(); + +	memset(&pp, 0, sizeof(pp));  	fd = open_kprobe_events(O_RDONLY, 0);  	rawlist = get_trace_kprobe_event_rawlist(fd);  	close(fd); @@ -675,3 +718,66 @@ void del_trace_kprobe_events(struct strlist *dellist)  	close(fd);  } +#define LINEBUF_SIZE 256 + +static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) +{ +	char buf[LINEBUF_SIZE]; +	const char *color = PERF_COLOR_BLUE; + +	if (fgets(buf, LINEBUF_SIZE, fp) == NULL) +		goto error; +	if (!skip) { +		if (show_num) +			fprintf(stdout, "%7u  %s", l, buf); +		else +			color_fprintf(stdout, color, "         %s", buf); +	} + +	while (strlen(buf) == LINEBUF_SIZE - 1 && +	       buf[LINEBUF_SIZE - 2] != '\n') { +		if (fgets(buf, LINEBUF_SIZE, fp) == NULL) +			goto error; +		if (!skip) { +			if (show_num) +				fprintf(stdout, "%s", buf); +			else +				color_fprintf(stdout, color, "%s", buf); +		} +	} +	return; +error: +	if (feof(fp)) +		die("Source file is shorter than expected."); +	else +		die("File read error: %s", strerror(errno)); +} + +void show_line_range(struct line_range *lr) +{ +	unsigned int l = 1; +	struct line_node *ln; +	FILE *fp; + +	setup_pager(); + +	if (lr->function) +		fprintf(stdout, "<%s:%d>\n", lr->function, +			lr->start - lr->offset); +	else +		fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); + +	fp = fopen(lr->path, "r"); +	if (fp == NULL) +		die("Failed to open %s: %s", lr->path, strerror(errno)); +	/* Skip to starting line number */ +	while (l < lr->start) +		show_one_line(fp, l++, true, false); + +	list_for_each_entry(ln, &lr->line_list, list) { +		while (ln->line > l) +			show_one_line(fp, (l++) - lr->offset, false, false); +		show_one_line(fp, (l++) - lr->offset, false, true); +	} +	fclose(fp); +}  |