aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c107
1 files changed, 98 insertions, 9 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 61cfd8f70989..2f6232f1bfdc 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -49,7 +49,7 @@
#include <unistd.h>
#include <subcmd/pager.h>
-#include "sane_ctype.h"
+#include <linux/ctype.h>
static char const *script_name;
static char const *generate_script_lang;
@@ -102,6 +102,7 @@ enum perf_output_field {
PERF_OUTPUT_METRIC = 1U << 28,
PERF_OUTPUT_MISC = 1U << 29,
PERF_OUTPUT_SRCCODE = 1U << 30,
+ PERF_OUTPUT_IPC = 1U << 31,
};
struct output_option {
@@ -139,6 +140,7 @@ struct output_option {
{.str = "metric", .field = PERF_OUTPUT_METRIC},
{.str = "misc", .field = PERF_OUTPUT_MISC},
{.str = "srccode", .field = PERF_OUTPUT_SRCCODE},
+ {.str = "ipc", .field = PERF_OUTPUT_IPC},
};
enum {
@@ -1268,6 +1270,20 @@ static int perf_sample__fprintf_insn(struct perf_sample *sample,
return printed;
}
+static int perf_sample__fprintf_ipc(struct perf_sample *sample,
+ struct perf_event_attr *attr, FILE *fp)
+{
+ unsigned int ipc;
+
+ if (!PRINT_FIELD(IPC) || !sample->cyc_cnt || !sample->insn_cnt)
+ return 0;
+
+ ipc = (sample->insn_cnt * 100) / sample->cyc_cnt;
+
+ return fprintf(fp, " \t IPC: %u.%02u (%" PRIu64 "/%" PRIu64 ") ",
+ ipc / 100, ipc % 100, sample->insn_cnt, sample->cyc_cnt);
+}
+
static int perf_sample__fprintf_bts(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
@@ -1312,6 +1328,8 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
printed += perf_sample__fprintf_addr(sample, thread, attr, fp);
}
+ printed += perf_sample__fprintf_ipc(sample, attr, fp);
+
if (print_srcline_last)
printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
@@ -1606,6 +1624,7 @@ struct perf_script {
bool show_namespace_events;
bool show_lost_events;
bool show_round_events;
+ bool show_bpf_events;
bool allocated;
bool per_event_dump;
struct cpu_map *cpus;
@@ -1858,6 +1877,9 @@ static void process_event(struct perf_script *script,
if (PRINT_FIELD(PHYS_ADDR))
fprintf(fp, "%16" PRIx64, sample->phys_addr);
+
+ perf_sample__fprintf_ipc(sample, attr, fp);
+
fprintf(fp, "\n");
if (PRINT_FIELD(SRCCODE)) {
@@ -2318,6 +2340,41 @@ process_finished_round_event(struct perf_tool *tool __maybe_unused,
return 0;
}
+static int
+process_bpf_events(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine)
+{
+ struct thread *thread;
+ struct perf_script *script = container_of(tool, struct perf_script, tool);
+ struct perf_session *session = script->session;
+ struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+
+ if (machine__process_ksymbol(machine, event, sample) < 0)
+ return -1;
+
+ if (!evsel->attr.sample_id_all) {
+ perf_event__fprintf(event, stdout);
+ return 0;
+ }
+
+ thread = machine__findnew_thread(machine, sample->pid, sample->tid);
+ if (thread == NULL) {
+ pr_debug("problem processing MMAP event, skipping it.\n");
+ return -1;
+ }
+
+ if (!filter_cpu(sample)) {
+ perf_sample__fprintf_start(sample, thread, evsel,
+ event->header.type, stdout);
+ perf_event__fprintf(event, stdout);
+ }
+
+ thread__put(thread);
+ return 0;
+}
+
static void sig_handler(int sig __maybe_unused)
{
session_done = 1;
@@ -2420,6 +2477,10 @@ static int __cmd_script(struct perf_script *script)
script->tool.ordered_events = false;
script->tool.finished_round = process_finished_round_event;
}
+ if (script->show_bpf_events) {
+ script->tool.ksymbol = process_bpf_events;
+ script->tool.bpf_event = process_bpf_events;
+ }
if (perf_script__setup_per_event_dump(script)) {
pr_err("Couldn't create the per event dump files\n");
@@ -2819,7 +2880,7 @@ static int read_script_info(struct script_desc *desc, const char *filename)
return -1;
while (fgets(line, sizeof(line), fp)) {
- p = ltrim(line);
+ p = skip_spaces(line);
if (strlen(p) == 0)
continue;
if (*p != '#')
@@ -2828,19 +2889,19 @@ static int read_script_info(struct script_desc *desc, const char *filename)
if (strlen(p) && *p == '!')
continue;
- p = ltrim(p);
+ p = skip_spaces(p);
if (strlen(p) && p[strlen(p) - 1] == '\n')
p[strlen(p) - 1] = '\0';
if (!strncmp(p, "description:", strlen("description:"))) {
p += strlen("description:");
- desc->half_liner = strdup(ltrim(p));
+ desc->half_liner = strdup(skip_spaces(p));
continue;
}
if (!strncmp(p, "args:", strlen("args:"))) {
p += strlen("args:");
- desc->args = strdup(ltrim(p));
+ desc->args = strdup(skip_spaces(p));
continue;
}
}
@@ -2947,7 +3008,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
return -1;
while (fgets(line, sizeof(line), fp)) {
- p = ltrim(line);
+ p = skip_spaces(line);
if (*p == '#')
continue;
@@ -2957,7 +3018,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
break;
p += 2;
- p = ltrim(p);
+ p = skip_spaces(p);
len = strcspn(p, " \t");
if (!len)
break;
@@ -3297,6 +3358,7 @@ static int parse_call_trace(const struct option *opt __maybe_unused,
parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
itrace_parse_synth_opts(opt, "cewp", 0);
symbol_conf.nanosecs = true;
+ symbol_conf.pad_output_len_dso = 50;
return 0;
}
@@ -3392,7 +3454,7 @@ int cmd_script(int argc, const char **argv)
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,srcline,period,iregs,uregs,brstack,"
"brstacksym,flags,bpf-output,brstackinsn,brstackoff,"
- "callindent,insn,insnlen,synth,phys_addr,metric,misc",
+ "callindent,insn,insnlen,synth,phys_addr,metric,misc,ipc",
parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"),
@@ -3438,6 +3500,8 @@ int cmd_script(int argc, const char **argv)
"Show lost events (if recorded)"),
OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,
"Show round events (if recorded)"),
+ OPT_BOOLEAN('\0', "show-bpf-events", &script.show_bpf_events,
+ "Show bpf related events (if recorded)"),
OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
"Dump trace output to files named by the monitored events"),
OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
@@ -3458,6 +3522,15 @@ int cmd_script(int argc, const char **argv)
"Time span of interest (start,stop)"),
OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
"Show inline function"),
+ OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
+ "guest mount directory under which every guest os"
+ " instance has a subdir"),
+ OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
+ "file", "file saving guest os vmlinux"),
+ OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
+ "file", "file saving guest os /proc/kallsyms"),
+ OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
+ "file", "file saving guest os /proc/modules"),
OPT_END()
};
const char * const script_subcommands[] = { "record", "report", NULL };
@@ -3477,6 +3550,16 @@ int cmd_script(int argc, const char **argv)
argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
+ if (symbol_conf.guestmount ||
+ symbol_conf.default_guest_vmlinux_name ||
+ symbol_conf.default_guest_kallsyms ||
+ symbol_conf.default_guest_modules) {
+ /*
+ * Enable guest sample processing.
+ */
+ perf_guest = true;
+ }
+
data.path = input_name;
data.force = symbol_conf.force;
@@ -3765,6 +3848,10 @@ int cmd_script(int argc, const char **argv)
&script.range_num);
if (err < 0)
goto out_delete;
+
+ itrace_synth_opts__set_time_range(&itrace_synth_opts,
+ script.ptime_range,
+ script.range_num);
}
err = __cmd_script(&script);
@@ -3772,8 +3859,10 @@ int cmd_script(int argc, const char **argv)
flush_scripting();
out_delete:
- if (script.ptime_range)
+ if (script.ptime_range) {
+ itrace_synth_opts__clear_time_range(&itrace_synth_opts);
zfree(&script.ptime_range);
+ }
perf_evlist__free_stats(session->evlist);
perf_session__delete(session);