diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
| -rw-r--r-- | tools/perf/builtin-script.c | 216 | 
1 files changed, 116 insertions, 100 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index c57be48d65bb..200b3e7ea8da 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -133,6 +133,7 @@ enum perf_output_field {  	PERF_OUTPUT_VCPU            = 1ULL << 38,  	PERF_OUTPUT_CGROUP          = 1ULL << 39,  	PERF_OUTPUT_RETIRE_LAT      = 1ULL << 40, +	PERF_OUTPUT_DSOFF           = 1ULL << 41,  };  struct perf_script { @@ -174,6 +175,7 @@ struct output_option {  	{.str = "ip",    .field = PERF_OUTPUT_IP},  	{.str = "sym",   .field = PERF_OUTPUT_SYM},  	{.str = "dso",   .field = PERF_OUTPUT_DSO}, +	{.str = "dsoff", .field = PERF_OUTPUT_DSOFF},  	{.str = "addr",  .field = PERF_OUTPUT_ADDR},  	{.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},  	{.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, @@ -574,6 +576,9 @@ static void set_print_ip_opts(struct perf_event_attr *attr)  	if (PRINT_FIELD(DSO))  		output[type].print_ip_opts |= EVSEL__PRINT_DSO; +	if (PRINT_FIELD(DSOFF)) +		output[type].print_ip_opts |= EVSEL__PRINT_DSOFF; +  	if (PRINT_FIELD(SYMOFFSET))  		output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET; @@ -627,6 +632,10 @@ static int perf_session__check_output_opt(struct perf_session *session)  		if (evsel == NULL)  			continue; +		/* 'dsoff' implys 'dso' field */ +		if (output[j].fields & PERF_OUTPUT_DSOFF) +			output[j].fields |= PERF_OUTPUT_DSO; +  		set_print_ip_opts(&evsel->core.attr);  		tod |= output[j].fields & PERF_OUTPUT_TOD;  	} @@ -792,11 +801,11 @@ static int perf_sample__fprintf_start(struct perf_script *script,  	}  	if (PRINT_FIELD(PID) && PRINT_FIELD(TID)) -		printed += fprintf(fp, "%5d/%-5d ", sample->pid, sample->tid); +		printed += fprintf(fp, "%7d/%-7d ", sample->pid, sample->tid);  	else if (PRINT_FIELD(PID)) -		printed += fprintf(fp, "%5d ", sample->pid); +		printed += fprintf(fp, "%7d ", sample->pid);  	else if (PRINT_FIELD(TID)) -		printed += fprintf(fp, "%5d ", sample->tid); +		printed += fprintf(fp, "%7d ", sample->tid);  	if (PRINT_FIELD(CPU)) {  		if (latency_format) @@ -910,7 +919,6 @@ static int perf_sample__fprintf_brstack(struct perf_sample *sample,  {  	struct branch_stack *br = sample->branch_stack;  	struct branch_entry *entries = perf_sample__branch_entries(sample); -	struct addr_location alf, alt;  	u64 i, from, to;  	int printed = 0; @@ -921,26 +929,22 @@ static int perf_sample__fprintf_brstack(struct perf_sample *sample,  		from = entries[i].from;  		to   = entries[i].to; +		printed += fprintf(fp, " 0x%"PRIx64, from);  		if (PRINT_FIELD(DSO)) { -			memset(&alf, 0, sizeof(alf)); -			memset(&alt, 0, sizeof(alt)); +			struct addr_location alf, alt; + +			addr_location__init(&alf); +			addr_location__init(&alt);  			thread__find_map_fb(thread, sample->cpumode, from, &alf);  			thread__find_map_fb(thread, sample->cpumode, to, &alt); -		} - -		printed += fprintf(fp, " 0x%"PRIx64, from); -		if (PRINT_FIELD(DSO)) { -			printed += fprintf(fp, "("); -			printed += map__fprintf_dsoname(alf.map, fp); -			printed += fprintf(fp, ")"); -		} -		printed += fprintf(fp, "/0x%"PRIx64, to); -		if (PRINT_FIELD(DSO)) { -			printed += fprintf(fp, "("); -			printed += map__fprintf_dsoname(alt.map, fp); -			printed += fprintf(fp, ")"); -		} +			printed += map__fprintf_dsoname_dsoff(alf.map, PRINT_FIELD(DSOFF), alf.addr, fp); +			printed += fprintf(fp, "/0x%"PRIx64, to); +			printed += map__fprintf_dsoname_dsoff(alt.map, PRINT_FIELD(DSOFF), alt.addr, fp); +			addr_location__exit(&alt); +			addr_location__exit(&alf); +		} else +			printed += fprintf(fp, "/0x%"PRIx64, to);  		printed += print_bstack_flags(fp, entries + i);  	} @@ -954,7 +958,6 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,  {  	struct branch_stack *br = sample->branch_stack;  	struct branch_entry *entries = perf_sample__branch_entries(sample); -	struct addr_location alf, alt;  	u64 i, from, to;  	int printed = 0; @@ -962,9 +965,10 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,  		return 0;  	for (i = 0; i < br->nr; i++) { +		struct addr_location alf, alt; -		memset(&alf, 0, sizeof(alf)); -		memset(&alt, 0, sizeof(alt)); +		addr_location__init(&alf); +		addr_location__init(&alt);  		from = entries[i].from;  		to   = entries[i].to; @@ -972,19 +976,15 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,  		thread__find_symbol_fb(thread, sample->cpumode, to, &alt);  		printed += symbol__fprintf_symname_offs(alf.sym, &alf, fp); -		if (PRINT_FIELD(DSO)) { -			printed += fprintf(fp, "("); -			printed += map__fprintf_dsoname(alf.map, fp); -			printed += fprintf(fp, ")"); -		} +		if (PRINT_FIELD(DSO)) +			printed += map__fprintf_dsoname_dsoff(alf.map, PRINT_FIELD(DSOFF), alf.addr, fp);  		printed += fprintf(fp, "%c", '/');  		printed += symbol__fprintf_symname_offs(alt.sym, &alt, fp); -		if (PRINT_FIELD(DSO)) { -			printed += fprintf(fp, "("); -			printed += map__fprintf_dsoname(alt.map, fp); -			printed += fprintf(fp, ")"); -		} +		if (PRINT_FIELD(DSO)) +			printed += map__fprintf_dsoname_dsoff(alt.map, PRINT_FIELD(DSOFF), alt.addr, fp);  		printed += print_bstack_flags(fp, entries + i); +		addr_location__exit(&alt); +		addr_location__exit(&alf);  	}  	return printed; @@ -996,7 +996,6 @@ static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,  {  	struct branch_stack *br = sample->branch_stack;  	struct branch_entry *entries = perf_sample__branch_entries(sample); -	struct addr_location alf, alt;  	u64 i, from, to;  	int printed = 0; @@ -1004,9 +1003,10 @@ static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,  		return 0;  	for (i = 0; i < br->nr; i++) { +		struct addr_location alf, alt; -		memset(&alf, 0, sizeof(alf)); -		memset(&alt, 0, sizeof(alt)); +		addr_location__init(&alf); +		addr_location__init(&alt);  		from = entries[i].from;  		to   = entries[i].to; @@ -1019,18 +1019,14 @@ static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,  			to = map__dso_map_ip(alt.map, to);  		printed += fprintf(fp, " 0x%"PRIx64, from); -		if (PRINT_FIELD(DSO)) { -			printed += fprintf(fp, "("); -			printed += map__fprintf_dsoname(alf.map, fp); -			printed += fprintf(fp, ")"); -		} +		if (PRINT_FIELD(DSO)) +			printed += map__fprintf_dsoname_dsoff(alf.map, PRINT_FIELD(DSOFF), alf.addr, fp);  		printed += fprintf(fp, "/0x%"PRIx64, to); -		if (PRINT_FIELD(DSO)) { -			printed += fprintf(fp, "("); -			printed += map__fprintf_dsoname(alt.map, fp); -			printed += fprintf(fp, ")"); -		} +		if (PRINT_FIELD(DSO)) +			printed += map__fprintf_dsoname_dsoff(alt.map, PRINT_FIELD(DSOFF), alt.addr, fp);  		printed += print_bstack_flags(fp, entries + i); +		addr_location__exit(&alt); +		addr_location__exit(&alf);  	}  	return printed; @@ -1045,6 +1041,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,  	struct addr_location al;  	bool kernel;  	struct dso *dso; +	int ret = 0;  	if (!start || !end)  		return 0; @@ -1066,7 +1063,6 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,  		return -ENXIO;  	} -	memset(&al, 0, sizeof(al));  	if (end - start > MAXBB - MAXINSN) {  		if (last)  			pr_debug("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end); @@ -1075,13 +1071,14 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,  		return 0;  	} +	addr_location__init(&al);  	if (!thread__find_map(thread, *cpumode, start, &al) || (dso = map__dso(al.map)) == NULL) {  		pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); -		return 0; +		goto out;  	}  	if (dso->data.status == DSO_DATA_STATUS_ERROR) {  		pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); -		return 0; +		goto out;  	}  	/* Load maps to ensure dso->is_64_bit has been updated */ @@ -1095,7 +1092,10 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,  	if (len <= 0)  		pr_debug("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",  			start, end); -	return len; +	ret = len; +out: +	addr_location__exit(&al); +	return ret;  }  static int map__fprintf_srccode(struct map *map, u64 addr, FILE *fp, struct srccode_state *state) @@ -1146,14 +1146,16 @@ static int print_srccode(struct thread *thread, u8 cpumode, uint64_t addr)  	struct addr_location al;  	int ret = 0; -	memset(&al, 0, sizeof(al)); +	addr_location__init(&al);  	thread__find_map(thread, cpumode, addr, &al);  	if (!al.map) -		return 0; +		goto out;  	ret = map__fprintf_srccode(al.map, al.addr, stdout, -		    &thread->srccode_state); +				   thread__srccode_state(thread));  	if (ret)  		ret += printf("\n"); +out: +	addr_location__exit(&al);  	return ret;  } @@ -1188,14 +1190,13 @@ static int ip__fprintf_sym(uint64_t addr, struct thread *thread,  			   struct perf_event_attr *attr, FILE *fp)  {  	struct addr_location al; -	int off, printed = 0; - -	memset(&al, 0, sizeof(al)); +	int off, printed = 0, ret = 0; +	addr_location__init(&al);  	thread__find_map(thread, cpumode, addr, &al);  	if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end) -		return 0; +		goto out;  	al.cpu = cpu;  	al.sym = NULL; @@ -1203,7 +1204,7 @@ static int ip__fprintf_sym(uint64_t addr, struct thread *thread,  		al.sym = map__find_symbol(al.map, al.addr);  	if (!al.sym) -		return 0; +		goto out;  	if (al.addr < al.sym->end)  		off = al.addr - al.sym->start; @@ -1218,7 +1219,10 @@ static int ip__fprintf_sym(uint64_t addr, struct thread *thread,  	printed += fprintf(fp, "\n");  	*lastsym = al.sym; -	return printed; +	ret = printed; +out: +	addr_location__exit(&al); +	return ret;  }  static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, @@ -1380,6 +1384,7 @@ static int perf_sample__fprintf_addr(struct perf_sample *sample,  	struct addr_location al;  	int printed = fprintf(fp, "%16" PRIx64, sample->addr); +	addr_location__init(&al);  	if (!sample_addr_correlates_sym(attr))  		goto out; @@ -1393,12 +1398,10 @@ static int perf_sample__fprintf_addr(struct perf_sample *sample,  			printed += symbol__fprintf_symname(al.sym, fp);  	} -	if (PRINT_FIELD(DSO)) { -		printed += fprintf(fp, " ("); -		printed += map__fprintf_dsoname(al.map, fp); -		printed += fprintf(fp, ")"); -	} +	if (PRINT_FIELD(DSO)) +		printed += map__fprintf_dsoname_dsoff(al.map, PRINT_FIELD(DSOFF), al.addr, fp);  out: +	addr_location__exit(&al);  	return printed;  } @@ -1451,7 +1454,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,  	 * The 'return' has already been popped off the stack so the depth has  	 * to be adjusted to match the 'call'.  	 */ -	if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN) +	if (thread__ts(thread) && sample->flags & PERF_IP_FLAG_RETURN)  		depth += 1;  	name = resolve_branch_sym(sample, evsel, thread, al, addr_al, &ip); @@ -1554,11 +1557,13 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,  		unsigned int print_opts = output[type].print_ip_opts;  		struct callchain_cursor *cursor = NULL; -		if (symbol_conf.use_callchain && sample->callchain && -		    thread__resolve_callchain(al->thread, &callchain_cursor, evsel, -					      sample, NULL, NULL, scripting_max_stack) == 0) -			cursor = &callchain_cursor; - +		if (symbol_conf.use_callchain && sample->callchain) { +			cursor = get_tls_callchain_cursor(); +			if (thread__resolve_callchain(al->thread, cursor, evsel, +						      sample, NULL, NULL, +						      scripting_max_stack)) +				cursor = NULL; +		}  		if (cursor == NULL) {  			printed += fprintf(fp, " ");  			if (print_opts & EVSEL__PRINT_SRCLINE) { @@ -1589,7 +1594,7 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,  	printed += fprintf(fp, "\n");  	if (PRINT_FIELD(SRCCODE)) {  		int ret = map__fprintf_srccode(al->map, al->addr, stdout, -					 &thread->srccode_state); +					       thread__srccode_state(thread));  		if (ret) {  			printed += ret;  			printed += printf("\n"); @@ -2098,9 +2103,9 @@ static bool show_event(struct perf_sample *sample,  	if (!symbol_conf.graph_function)  		return true; -	if (thread->filter) { -		if (depth <= thread->filter_entry_depth) { -			thread->filter = false; +	if (thread__filter(thread)) { +		if (depth <= thread__filter_entry_depth(thread)) { +			thread__set_filter(thread, false);  			return false;  		}  		return true; @@ -2117,8 +2122,8 @@ static bool show_event(struct perf_sample *sample,  		while (*s) {  			unsigned len = strcspn(s, ",");  			if (nlen == len && !strncmp(name, s, len)) { -				thread->filter = true; -				thread->filter_entry_depth = depth; +				thread__set_filter(thread, true); +				thread__set_filter_entry_depth(thread, depth);  				return true;  			}  			s += len; @@ -2198,13 +2203,15 @@ static void process_event(struct perf_script *script,  		struct callchain_cursor *cursor = NULL;  		if (script->stitch_lbr) -			al->thread->lbr_stitch_enable = true; - -		if (symbol_conf.use_callchain && sample->callchain && -		    thread__resolve_callchain(al->thread, &callchain_cursor, evsel, -					      sample, NULL, NULL, scripting_max_stack) == 0) -			cursor = &callchain_cursor; +			thread__set_lbr_stitch_enable(al->thread, true); +		if (symbol_conf.use_callchain && sample->callchain) { +			cursor = get_tls_callchain_cursor(); +			if (thread__resolve_callchain(al->thread, cursor, evsel, +						      sample, NULL, NULL, +						      scripting_max_stack)) +				cursor = NULL; +		}  		fputc(cursor ? '\n' : ' ', fp);  		sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor,  				    symbol_conf.bt_stop_list, fp); @@ -2253,7 +2260,7 @@ static void process_event(struct perf_script *script,  	if (PRINT_FIELD(SRCCODE)) {  		if (map__fprintf_srccode(al->map, al->addr, stdout, -					 &thread->srccode_state)) +					 thread__srccode_state(thread)))  			printf("\n");  	} @@ -2350,8 +2357,8 @@ static int process_sample_event(struct perf_tool *tool,  	int ret = 0;  	/* Set thread to NULL to indicate addr_al and al are not initialized */ -	addr_al.thread = NULL; -	al.thread = NULL; +	addr_location__init(&al); +	addr_location__init(&addr_al);  	ret = dlfilter__filter_event_early(dlfilter, event, sample, evsel, machine, &al, &addr_al);  	if (ret) { @@ -2417,11 +2424,14 @@ static int process_sample_event(struct perf_tool *tool,  	}  out_put: -	if (al.thread) -		addr_location__put(&al); +	addr_location__exit(&addr_al); +	addr_location__exit(&al);  	return ret;  } +// Used when scr->per_event_dump is not set +static struct evsel_script es_stdout; +  static int process_attr(struct perf_tool *tool, union perf_event *event,  			struct evlist **pevlist)  { @@ -2430,7 +2440,6 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,  	struct evsel *evsel, *pos;  	u64 sample_type;  	int err; -	static struct evsel_script *es;  	err = perf_event__process_attr(tool, event, pevlist);  	if (err) @@ -2440,14 +2449,13 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,  	evsel = evlist__last(*pevlist);  	if (!evsel->priv) { -		if (scr->per_event_dump) { +		if (scr->per_event_dump) {   			evsel->priv = evsel_script__new(evsel, scr->session->data); -		} else { -			es = zalloc(sizeof(*es)); -			if (!es) +			if (!evsel->priv)  				return -ENOMEM; -			es->fp = stdout; -			evsel->priv = es; +		} else { // Replicate what is done in perf_script__setup_per_event_dump() +			es_stdout.fp = stdout; +			evsel->priv = &es_stdout;  		}  	} @@ -2753,7 +2761,6 @@ out_err_fclose:  static int perf_script__setup_per_event_dump(struct perf_script *script)  {  	struct evsel *evsel; -	static struct evsel_script es_stdout;  	if (script->per_event_dump)  		return perf_script__fopen_per_event_dump(script); @@ -3311,14 +3318,21 @@ static int list_available_scripts(const struct option *opt __maybe_unused,  				  int unset __maybe_unused)  {  	struct dirent *script_dirent, *lang_dirent; -	char scripts_path[MAXPATHLEN]; +	char *buf, *scripts_path, *script_path, *lang_path, *first_half;  	DIR *scripts_dir, *lang_dir; -	char script_path[MAXPATHLEN]; -	char lang_path[MAXPATHLEN];  	struct script_desc *desc; -	char first_half[BUFSIZ];  	char *script_root; +	buf = malloc(3 * MAXPATHLEN + BUFSIZ); +	if (!buf) { +		pr_err("malloc failed\n"); +		exit(-1); +	} +	scripts_path = buf; +	script_path = buf + MAXPATHLEN; +	lang_path = buf + 2 * MAXPATHLEN; +	first_half = buf + 3 * MAXPATHLEN; +  	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());  	scripts_dir = opendir(scripts_path); @@ -3327,6 +3341,7 @@ static int list_available_scripts(const struct option *opt __maybe_unused,  			"open(%s) failed.\n"  			"Check \"PERF_EXEC_PATH\" env to set scripts dir.\n",  			scripts_path); +		free(buf);  		exit(-1);  	} @@ -3357,6 +3372,7 @@ static int list_available_scripts(const struct option *opt __maybe_unused,  			desc->half_liner ? desc->half_liner : "");  	} +	free(buf);  	exit(0);  } @@ -3883,7 +3899,7 @@ int cmd_script(int argc, const char **argv)  		     "comma separated output fields prepend with 'type:'. "  		     "+field to add and -field to remove."  		     "Valid types: hw,sw,trace,raw,synth. " -		     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," +		     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,dsoff"  		     "addr,symoff,srcline,period,iregs,uregs,brstack,"  		     "brstacksym,flags,data_src,weight,bpf-output,brstackinsn,"  		     "brstackinsnlen,brstackoff,callindent,insn,insnlen,synth,"  | 
