diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
| -rw-r--r-- | tools/perf/builtin-script.c | 87 | 
1 files changed, 81 insertions, 6 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index fb9625083a2..b363e7b292b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -520,8 +520,8 @@ static struct perf_tool perf_script = {  	.sample		 = process_sample_event,  	.mmap		 = perf_event__process_mmap,  	.comm		 = perf_event__process_comm, -	.exit		 = perf_event__process_task, -	.fork		 = perf_event__process_task, +	.exit		 = perf_event__process_exit, +	.fork		 = perf_event__process_fork,  	.attr		 = perf_event__process_attr,  	.event_type	 = perf_event__process_event_type,  	.tracing_data	 = perf_event__process_tracing_data, @@ -1030,6 +1030,68 @@ static int list_available_scripts(const struct option *opt __maybe_unused,  }  /* + * Some scripts specify the required events in their "xxx-record" file, + * this function will check if the events in perf.data match those + * mentioned in the "xxx-record". + * + * Fixme: All existing "xxx-record" are all in good formats "-e event ", + * which is covered well now. And new parsing code should be added to + * cover the future complexing formats like event groups etc. + */ +static int check_ev_match(char *dir_name, char *scriptname, +			struct perf_session *session) +{ +	char filename[MAXPATHLEN], evname[128]; +	char line[BUFSIZ], *p; +	struct perf_evsel *pos; +	int match, len; +	FILE *fp; + +	sprintf(filename, "%s/bin/%s-record", dir_name, scriptname); + +	fp = fopen(filename, "r"); +	if (!fp) +		return -1; + +	while (fgets(line, sizeof(line), fp)) { +		p = ltrim(line); +		if (*p == '#') +			continue; + +		while (strlen(p)) { +			p = strstr(p, "-e"); +			if (!p) +				break; + +			p += 2; +			p = ltrim(p); +			len = strcspn(p, " \t"); +			if (!len) +				break; + +			snprintf(evname, len + 1, "%s", p); + +			match = 0; +			list_for_each_entry(pos, +					&session->evlist->entries, node) { +				if (!strcmp(perf_evsel__name(pos), evname)) { +					match = 1; +					break; +				} +			} + +			if (!match) { +				fclose(fp); +				return -1; +			} +		} +	} + +	fclose(fp); +	return 0; +} + +/*   * Return -1 if none is found, otherwise the actual scripts number.   *   * Currently the only user of this function is the script browser, which @@ -1039,17 +1101,23 @@ static int list_available_scripts(const struct option *opt __maybe_unused,  int find_scripts(char **scripts_array, char **scripts_path_array)  {  	struct dirent *script_next, *lang_next, script_dirent, lang_dirent; -	char scripts_path[MAXPATHLEN]; +	char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];  	DIR *scripts_dir, *lang_dir; -	char lang_path[MAXPATHLEN]; +	struct perf_session *session;  	char *temp;  	int i = 0; +	session = perf_session__new(input_name, O_RDONLY, 0, false, NULL); +	if (!session) +		return -1; +  	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());  	scripts_dir = opendir(scripts_path); -	if (!scripts_dir) +	if (!scripts_dir) { +		perf_session__delete(session);  		return -1; +	}  	for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {  		snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, @@ -1077,10 +1145,18 @@ int find_scripts(char **scripts_array, char **scripts_path_array)  			snprintf(scripts_array[i],  				(temp - script_dirent.d_name) + 1,  				"%s", script_dirent.d_name); + +			if (check_ev_match(lang_path, +					scripts_array[i], session)) +				continue; +  			i++;  		} +		closedir(lang_dir);  	} +	closedir(scripts_dir); +	perf_session__delete(session);  	return i;  } @@ -1175,7 +1251,6 @@ static int have_cmd(int argc, const char **argv)  int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)  {  	bool show_full_info = false; -	const char *input_name = NULL;  	char *rec_script_path = NULL;  	char *rep_script_path = NULL;  	struct perf_session *session;  |