#define SCRIPT_NAMELEN 128 #define SCRIPT_MAX_NO 64 /* * Usually the full path for a script is: * /home/username/libexec/perf-core/scripts/python/xxx.py * /home/username/libexec/perf-core/scripts/perl/xxx.pl * So 256 should be long enough to contain the full path.
*/ #define SCRIPT_FULLPATH_LEN 256
if (!strstarts(var, "scripts.")) return -1; if (c->index >= SCRIPT_MAX_NO) return -1;
c->names[c->index] = strdup(var + 7); if (!c->names[c->index]) return -1; if (asprintf(&c->paths[c->index], "%s %s", value,
c->extra_format) < 0) return -1;
c->index++; return 0;
}
/* * 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 complex formats like event groups etc.
*/ staticint check_ev_match(int dir_fd, constchar *scriptname, struct perf_session *session)
{ char line[BUFSIZ];
FILE *fp;
while (fgets(line, sizeof(line), fp)) { char *p = skip_spaces(line);
if (*p == '#') continue;
while (strlen(p)) { int match, len; struct evsel *pos; char evname[128];
p = strstr(p, "-e"); if (!p) break;
p += 2;
p = skip_spaces(p);
len = strcspn(p, " \t"); if (!len) break;
snprintf(evname, len + 1, "%s", p);
match = 0;
evlist__for_each_entry(session->evlist, pos) { if (evsel__name_is(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 * will list all statically runnable scripts, select one, execute it and * show the output in a perf browser.
*/ staticint find_scripts(char **scripts_array, char **scripts_path_array, int num, int pathlen)
{ struct dirent *script_dirent, *lang_dirent; int scripts_dir_fd, lang_dir_fd;
DIR *scripts_dir, *lang_dir; struct perf_session *session; struct perf_data data = {
.path = input_name,
.mode = PERF_DATA_MODE_READ,
}; char *temp; int i = 0; constchar *exec_path = get_argv_exec_path();
session = perf_session__new(&data, NULL); if (IS_ERR(session)) return PTR_ERR(session);
{ char scripts_path[PATH_MAX];
snprintf(scripts_path, sizeof(scripts_path), "%s/scripts", exec_path);
scripts_dir_fd = open(scripts_path, O_DIRECTORY);
pr_err("Failed to open directory '%s'", scripts_path); if (scripts_dir_fd == -1) {
perf_session__delete(session); return -1;
}
}
scripts_dir = fdopendir(scripts_dir_fd); if (!scripts_dir) {
close(scripts_dir_fd);
perf_session__delete(session); return -1;
}
while ((lang_dirent = readdir(scripts_dir)) != NULL) { if (lang_dirent->d_type != DT_DIR &&
(lang_dirent->d_type == DT_UNKNOWN &&
!is_directory_at(scripts_dir_fd, lang_dirent->d_name))) continue; if (!strcmp(lang_dirent->d_name, ".") || !strcmp(lang_dirent->d_name, "..")) continue;
#ifndef HAVE_LIBPERL_SUPPORT if (strstr(lang_dirent->d_name, "perl")) continue; #endif #ifndef HAVE_LIBPYTHON_SUPPORT if (strstr(lang_dirent->d_name, "python")) continue; #endif
lang_dir_fd = openat(scripts_dir_fd, lang_dirent->d_name, O_DIRECTORY); if (lang_dir_fd == -1) continue;
lang_dir = fdopendir(lang_dir_fd); if (!lang_dir) {
close(lang_dir_fd); continue;
} while ((script_dirent = readdir(lang_dir)) != NULL) { if (script_dirent->d_type == DT_DIR) continue; if (script_dirent->d_type == DT_UNKNOWN &&
is_directory_at(lang_dir_fd, script_dirent->d_name)) continue; /* Skip those real time scripts: xxxtop.p[yl] */ if (strstr(script_dirent->d_name, "top.")) continue; if (i >= num) break;
scnprintf(scripts_path_array[i], pathlen, "%s/scripts/%s/%s",
exec_path,
lang_dirent->d_name,
script_dirent->d_name);
temp = strchr(script_dirent->d_name, '.');
snprintf(scripts_array[i],
(temp - script_dirent->d_name) + 1, "%s", script_dirent->d_name);
if (check_ev_match(lang_dir_fd, scripts_array[i], session)) continue;
/* * When success, will copy the full path of the selected script * into the buffer pointed by script_name, and return 0. * Return -1 on failure.
*/ staticint list_scripts(char *script_name, bool *custom, struct evsel *evsel)
{ char *buf, *paths[SCRIPT_MAX_NO], *names[SCRIPT_MAX_NO]; int i, num, choice; int ret = 0; int max_std, custom_perf; char pbuf[256]; constchar *perf = perf_exe(pbuf, sizeof pbuf); struct script_config scriptc = {
.names = (constchar **)names,
.paths = paths,
.perf = perf
};
script_name[0] = 0;
/* Preset the script name to SCRIPT_NAMELEN */
buf = malloc(SCRIPT_MAX_NO * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN)); if (!buf) return -1;
if (evsel)
attr_to_script(scriptc.extra_format, &evsel->core.attr);
add_script_option("Show individual samples", "", &scriptc);
add_script_option("Show individual samples with assembler", "-F +disasm",
&scriptc);
add_script_option("Show individual samples with source", "-F +srcline,+srccode",
&scriptc);
perf_config(scripts_config, &scriptc);
custom_perf = scriptc.index;
add_script_option("Show samples with custom perf script arguments", "", &scriptc);
i = scriptc.index;
max_std = i;
for (; i < SCRIPT_MAX_NO; i++) {
names[i] = buf + (i - max_std) * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN);
paths[i] = names[i] + SCRIPT_NAMELEN;
}
num = find_scripts(names + max_std, paths + max_std, SCRIPT_MAX_NO - max_std,
SCRIPT_FULLPATH_LEN); if (num < 0)
num = 0;
choice = ui__popup_menu(num + max_std, (char * const *)names, NULL); if (choice < 0) {
ret = -1; goto out;
} if (choice == custom_perf) { char script_args[50]; int key = ui_browser__input_window("perf script command", "Enter perf script command line (without perf script prefix)",
script_args, "", 0); if (key != K_ENTER) {
ret = -1; goto out;
}
sprintf(script_name, "%s script %s", perf, script_args);
} elseif (choice < num + max_std) {
strcpy(script_name, paths[choice]);
}
*custom = choice >= max_std;
out:
free(buf); for (i = 0; i < max_std; i++)
zfree(&paths[i]); return ret;
}
void run_script(char *cmd)
{
pr_debug("Running %s\n", cmd);
SLang_reset_tty(); if (system(cmd) < 0)
pr_warning("Cannot run %s\n", cmd); /* * SLang doesn't seem to reset the whole terminal, so be more * forceful to get back to the original state.
*/
printf("\033[c\033[H\033[J");
fflush(stdout);
SLang_init_tty(0, 0, 0);
SLtty_set_suspend_state(true);
SLsmg_refresh();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.