diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
| -rw-r--r-- | tools/perf/builtin-script.c | 130 | 
1 files changed, 74 insertions, 56 deletions
| diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 2f62a295226..fd1909afcfd 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -7,6 +7,7 @@  #include "util/header.h"  #include "util/parse-options.h"  #include "util/session.h" +#include "util/tool.h"  #include "util/symbol.h"  #include "util/thread.h"  #include "util/trace-event.h" @@ -23,6 +24,7 @@ static u64			nr_unordered;  extern const struct option	record_options[];  static bool			no_callchain;  static bool			show_full_info; +static bool			system_wide;  static const char		*cpu_list;  static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); @@ -315,7 +317,7 @@ static bool sample_addr_correlates_sym(struct perf_event_attr *attr)  static void print_sample_addr(union perf_event *event,  			  struct perf_sample *sample, -			  struct perf_session *session, +			  struct machine *machine,  			  struct thread *thread,  			  struct perf_event_attr *attr)  { @@ -328,11 +330,11 @@ static void print_sample_addr(union perf_event *event,  	if (!sample_addr_correlates_sym(attr))  		return; -	thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, -			      event->ip.pid, sample->addr, &al); +	thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, +			      sample->addr, &al);  	if (!al.map) -		thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE, -				      event->ip.pid, sample->addr, &al); +		thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, +				      sample->addr, &al);  	al.cpu = sample->cpu;  	al.sym = NULL; @@ -362,7 +364,7 @@ static void print_sample_addr(union perf_event *event,  static void process_event(union perf_event *event __unused,  			  struct perf_sample *sample,  			  struct perf_evsel *evsel, -			  struct perf_session *session, +			  struct machine *machine,  			  struct thread *thread)  {  	struct perf_event_attr *attr = &evsel->attr; @@ -377,15 +379,15 @@ static void process_event(union perf_event *event __unused,  				  sample->raw_size);  	if (PRINT_FIELD(ADDR)) -		print_sample_addr(event, sample, session, thread, attr); +		print_sample_addr(event, sample, machine, thread, attr);  	if (PRINT_FIELD(IP)) {  		if (!symbol_conf.use_callchain)  			printf(" ");  		else  			printf("\n"); -		perf_session__print_ip(event, sample, session, -					      PRINT_FIELD(SYM), PRINT_FIELD(DSO)); +		perf_event__print_ip(event, sample, machine, evsel, +				     PRINT_FIELD(SYM), PRINT_FIELD(DSO));  	}  	printf("\n"); @@ -432,14 +434,16 @@ static int cleanup_scripting(void)  	return scripting_ops->stop_script();  } -static char const		*input_name = "perf.data"; +static const char *input_name; -static int process_sample_event(union perf_event *event, +static int process_sample_event(struct perf_tool *tool __used, +				union perf_event *event,  				struct perf_sample *sample,  				struct perf_evsel *evsel, -				struct perf_session *session) +				struct machine *machine)  { -	struct thread *thread = perf_session__findnew(session, event->ip.pid); +	struct addr_location al; +	struct thread *thread = machine__findnew_thread(machine, event->ip.tid);  	if (thread == NULL) {  		pr_debug("problem processing %d event, skipping it.\n", @@ -458,16 +462,25 @@ static int process_sample_event(union perf_event *event,  		return 0;  	} +	if (perf_event__preprocess_sample(event, machine, &al, sample, 0) < 0) { +		pr_err("problem processing %d event, skipping it.\n", +		       event->header.type); +		return -1; +	} + +	if (al.filtered) +		return 0; +  	if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))  		return 0; -	scripting_ops->process_event(event, sample, evsel, session, thread); +	scripting_ops->process_event(event, sample, evsel, machine, thread); -	session->hists.stats.total_period += sample->period; +	evsel->hists.stats.total_period += sample->period;  	return 0;  } -static struct perf_event_ops event_ops = { +static struct perf_tool perf_script = {  	.sample		 = process_sample_event,  	.mmap		 = perf_event__process_mmap,  	.comm		 = perf_event__process_comm, @@ -494,7 +507,7 @@ static int __cmd_script(struct perf_session *session)  	signal(SIGINT, sig_handler); -	ret = perf_session__process_events(session, &event_ops); +	ret = perf_session__process_events(session, &perf_script);  	if (debug_mode)  		pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); @@ -523,12 +536,6 @@ static struct script_spec *script_spec__new(const char *spec,  	return s;  } -static void script_spec__delete(struct script_spec *s) -{ -	free(s->spec); -	free(s); -} -  static void script_spec__add(struct script_spec *s)  {  	list_add_tail(&s->node, &script_specs); @@ -554,16 +561,11 @@ static struct script_spec *script_spec__findnew(const char *spec,  	s = script_spec__new(spec, ops);  	if (!s) -		goto out_delete_spec; +		return NULL;  	script_spec__add(s);  	return s; - -out_delete_spec: -	script_spec__delete(s); - -	return NULL;  }  int script_spec_register(const char *spec, struct scripting_ops *ops) @@ -681,7 +683,8 @@ static int parse_output_fields(const struct option *opt __used,  			type = PERF_TYPE_RAW;  		else {  			fprintf(stderr, "Invalid event type in field string.\n"); -			return -EINVAL; +			rc = -EINVAL; +			goto out;  		}  		if (output[type].user_set) @@ -923,6 +926,24 @@ static int read_script_info(struct script_desc *desc, const char *filename)  	return 0;  } +static char *get_script_root(struct dirent *script_dirent, const char *suffix) +{ +	char *script_root, *str; + +	script_root = strdup(script_dirent->d_name); +	if (!script_root) +		return NULL; + +	str = (char *)ends_with(script_root, suffix); +	if (!str) { +		free(script_root); +		return NULL; +	} + +	*str = '\0'; +	return script_root; +} +  static int list_available_scripts(const struct option *opt __used,  				  const char *s __used, int unset __used)  { @@ -934,7 +955,6 @@ static int list_available_scripts(const struct option *opt __used,  	struct script_desc *desc;  	char first_half[BUFSIZ];  	char *script_root; -	char *str;  	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); @@ -950,16 +970,14 @@ static int list_available_scripts(const struct option *opt __used,  			continue;  		for_each_script(lang_path, lang_dir, script_dirent, script_next) { -			script_root = strdup(script_dirent.d_name); -			str = (char *)ends_with(script_root, REPORT_SUFFIX); -			if (str) { -				*str = '\0'; +			script_root = get_script_root(&script_dirent, REPORT_SUFFIX); +			if (script_root) {  				desc = script_desc__findnew(script_root);  				snprintf(script_path, MAXPATHLEN, "%s/%s",  					 lang_path, script_dirent.d_name);  				read_script_info(desc, script_path); +				free(script_root);  			} -			free(script_root);  		}  	} @@ -981,8 +999,7 @@ static char *get_script_path(const char *script_root, const char *suffix)  	char script_path[MAXPATHLEN];  	DIR *scripts_dir, *lang_dir;  	char lang_path[MAXPATHLEN]; -	char *str, *__script_root; -	char *path = NULL; +	char *__script_root;  	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); @@ -998,23 +1015,18 @@ static char *get_script_path(const char *script_root, const char *suffix)  			continue;  		for_each_script(lang_path, lang_dir, script_dirent, script_next) { -			__script_root = strdup(script_dirent.d_name); -			str = (char *)ends_with(__script_root, suffix); -			if (str) { -				*str = '\0'; -				if (strcmp(__script_root, script_root)) -					continue; +			__script_root = get_script_root(&script_dirent, suffix); +			if (__script_root && !strcmp(script_root, __script_root)) { +				free(__script_root);  				snprintf(script_path, MAXPATHLEN, "%s/%s",  					 lang_path, script_dirent.d_name); -				path = strdup(script_path); -				free(__script_root); -				break; +				return strdup(script_path);  			}  			free(__script_root);  		}  	} -	return path; +	return NULL;  }  static bool is_top_script(const char *script_path) @@ -1083,7 +1095,11 @@ static const struct option options[] = {  	OPT_CALLBACK('f', "fields", NULL, "str",  		     "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",  		     parse_output_fields), -	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), +	OPT_BOOLEAN('a', "all-cpus", &system_wide, +		     "system-wide collection from all CPUs"), +	OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), +	OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", +		   "only display events for these comms"),  	OPT_BOOLEAN('I', "show-info", &show_full_info,  		    "display extended information from perf.data file"),  	OPT_END() @@ -1110,7 +1126,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)  	struct perf_session *session;  	char *script_path = NULL;  	const char **__argv; -	bool system_wide;  	int i, j, err;  	setup_scripting(); @@ -1178,15 +1193,17 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)  		}  		if (!pid) { -			system_wide = true;  			j = 0;  			dup2(live_pipe[1], 1);  			close(live_pipe[0]); -			if (!is_top_script(argv[0])) +			if (is_top_script(argv[0])) { +				system_wide = true; +			} else if (!system_wide) {  				system_wide = !have_cmd(argc - rep_args,  							&argv[rep_args]); +			}  			__argv = malloc((argc + 6) * sizeof(const char *));  			if (!__argv) @@ -1234,10 +1251,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)  		script_path = rep_script_path;  	if (script_path) { -		system_wide = false;  		j = 0; -		if (rec_script_path) +		if (!rec_script_path) +			system_wide = false; +		else if (!system_wide)  			system_wide = !have_cmd(argc - 1, &argv[1]);  		__argv = malloc((argc + 2) * sizeof(const char *)); @@ -1261,7 +1279,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)  	if (!script_name)  		setup_pager(); -	session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops); +	session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_script);  	if (session == NULL)  		return -ENOMEM; @@ -1287,7 +1305,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)  			return -1;  		} -		input = open(input_name, O_RDONLY); +		input = open(session->filename, O_RDONLY);	/* input_name */  		if (input < 0) {  			perror("failed to open file");  			exit(-1); | 
