Skip to content
Snippets Groups Projects
builtin-script.c 28.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
    		    "When printing symbols do not display call chain"),
    	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
    		    "Look for files with symbols relative to this directory"),
    
    	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",
    
    static bool have_cmd(int argc, const char **argv)
    {
    	char **__argv = malloc(sizeof(const char *) * argc);
    
    	if (!__argv)
    		die("malloc");
    	memcpy(__argv, argv, sizeof(const char *) * argc);
    	argc = parse_options(argc, (const char **)__argv, record_options,
    			     NULL, PARSE_OPT_STOP_AT_NON_OPTION);
    	free(__argv);
    
    	return argc != 0;
    }
    
    
    int cmd_script(int argc, const char **argv, const char *prefix __used)
    
    	char *rec_script_path = NULL;
    	char *rep_script_path = NULL;
    
    	char *script_path = NULL;
    
    	bool system_wide;
    	int i, j, err;
    
    	argc = parse_options(argc, argv, options, script_usage,
    
    			     PARSE_OPT_STOP_AT_NON_OPTION);
    
    	if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
    		rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
    		if (!rec_script_path)
    			return cmd_record(argc, argv, NULL);
    
    	if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
    		rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
    		if (!rep_script_path) {
    
    				"Please specify a valid report script"
    
    				"(see 'perf script -l' for listing)\n");
    
    	/* make sure PERF_EXEC_PATH is set for scripts */
    	perf_set_argv_exec_path(perf_exec_path());
    
    
    	if (argc && !script_name && !rec_script_path && !rep_script_path) {
    
    		rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
    		rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
    
    		if (!rec_script_path && !rep_script_path) {
    			fprintf(stderr, " Couldn't find script %s\n\n See perf"
    
    				" script -l for available scripts.\n", argv[0]);
    			usage_with_options(script_usage, options);
    
    		if (is_top_script(argv[0])) {
    			rep_args = argc - 1;
    		} else {
    			int rec_args;
    
    			rep_args = has_required_arg(rep_script_path);
    			rec_args = (argc - 1) - rep_args;
    			if (rec_args < 0) {
    				fprintf(stderr, " %s script requires options."
    
    					"\n\n See perf script -l for available "
    
    					"scripts and options.\n", argv[0]);
    
    				usage_with_options(script_usage, options);
    
    		}
    
    		if (pipe(live_pipe) < 0) {
    			perror("failed to create pipe");
    			exit(-1);
    		}
    
    		pid = fork();
    		if (pid < 0) {
    			perror("failed to fork");
    			exit(-1);
    		}
    
    		if (!pid) {
    
    			system_wide = true;
    			j = 0;
    
    
    			if (!is_top_script(argv[0]))
    				system_wide = !have_cmd(argc - rep_args,
    							&argv[rep_args]);
    
    			__argv = malloc((argc + 6) * sizeof(const char *));
    
    			__argv[j++] = "/bin/sh";
    			__argv[j++] = rec_script_path;
    			if (system_wide)
    				__argv[j++] = "-a";
    			__argv[j++] = "-q";
    			__argv[j++] = "-o";
    			__argv[j++] = "-";
    			for (i = rep_args + 1; i < argc; i++)
    				__argv[j++] = argv[i];
    			__argv[j++] = NULL;
    
    		__argv = malloc((argc + 4) * sizeof(const char *));
    
    		j = 0;
    		__argv[j++] = "/bin/sh";
    		__argv[j++] = rep_script_path;
    		for (i = 1; i < rep_args + 1; i++)
    			__argv[j++] = argv[i];
    		__argv[j++] = "-i";
    		__argv[j++] = "-";
    		__argv[j++] = NULL;
    
    	if (rec_script_path)
    		script_path = rec_script_path;
    	if (rep_script_path)
    		script_path = rep_script_path;
    
    	if (script_path) {
    		system_wide = false;
    		j = 0;
    
    		if (rec_script_path)
    			system_wide = !have_cmd(argc - 1, &argv[1]);
    
    		__argv = malloc((argc + 2) * sizeof(const char *));
    
    		__argv[j++] = "/bin/sh";
    		__argv[j++] = script_path;
    		if (system_wide)
    			__argv[j++] = "-a";
    
    		for (i = 2; i < argc; i++)
    
    			__argv[j++] = argv[i];
    		__argv[j++] = NULL;
    
    
    		execvp("/bin/sh", (char **)__argv);
    
    	if (symbol__init() < 0)
    		return -1;
    
    	if (!script_name)
    		setup_pager();
    
    	session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops);
    
    	if (!no_callchain)
    
    		symbol_conf.use_callchain = true;
    	else
    		symbol_conf.use_callchain = false;
    
    
    	if (generate_script_lang) {
    		struct stat perf_stat;
    
    		if (output_set_by_user()) {
    
    			fprintf(stderr,
    				"custom fields not supported for generated scripts");
    			return -1;
    		}
    
    		input = open(input_name, O_RDONLY);
    
    		if (input < 0) {
    			perror("failed to open file");
    			exit(-1);
    		}
    
    		err = fstat(input, &perf_stat);
    		if (err < 0) {
    			perror("failed to stat file");
    			exit(-1);
    		}
    
    		if (!perf_stat.st_size) {
    			fprintf(stderr, "zero-sized file, nothing to do!\n");
    			exit(0);
    		}
    
    		scripting_ops = script_spec__lookup(generate_script_lang);
    		if (!scripting_ops) {
    			fprintf(stderr, "invalid language specifier");
    			return -1;
    		}
    
    
    		err = scripting_ops->generate_script("perf-script");
    
    		goto out;
    	}
    
    	if (script_name) {
    
    		err = scripting_ops->start_script(script_name, argc, argv);
    
    		if (err)
    			goto out;
    
    		pr_debug("perf script started with script %s\n\n", script_name);
    
    
    	err = perf_session__check_output_opt(session);
    	if (err < 0)
    		goto out;
    
    
    	err = __cmd_script(session);
    
    	cleanup_scripting();
    out:
    	return err;