Skip to content

Commit

Permalink
perf script: Add printing of sample address
Browse files Browse the repository at this point in the history
Resolve to a function or variable if possible and if the sym option is
enabled.

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1306782503-22002-1-git-send-email-dsahern@gmail.com
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
David Ahern authored and Arnaldo Carvalho de Melo committed Jun 2, 2011
1 parent 610723f commit 7cec092
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 11 deletions.
4 changes: 2 additions & 2 deletions tools/perf/Documentation/perf-script.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ OPTIONS
-f::
--fields::
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso. Field
list can be prepended with the type, trace, sw or hw,
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr.
Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace

Expand Down
84 changes: 77 additions & 7 deletions tools/perf/builtin-script.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum perf_output_field {
PERF_OUTPUT_IP = 1U << 7,
PERF_OUTPUT_SYM = 1U << 8,
PERF_OUTPUT_DSO = 1U << 9,
PERF_OUTPUT_ADDR = 1U << 10,
};

struct output_option {
Expand All @@ -49,6 +50,7 @@ struct output_option {
{.str = "ip", .field = PERF_OUTPUT_IP},
{.str = "sym", .field = PERF_OUTPUT_SYM},
{.str = "dso", .field = PERF_OUTPUT_DSO},
{.str = "addr", .field = PERF_OUTPUT_ADDR},
};

/* default set to maintain compatibility with current format */
Expand Down Expand Up @@ -173,14 +175,22 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
!(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
symbol_conf.use_callchain = false;
}
if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP)) {
pr_err("Display of symbols requested but IP is not selected.\n"
"No addresses to convert to symbols.\n");

if (PRINT_FIELD(ADDR) &&
perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR",
PERF_OUTPUT_ADDR))
return -EINVAL;

if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
pr_err("Display of symbols requested but neither sample IP nor "
"sample address\nis selected. Hence, no addresses to convert "
"to symbols.\n");
return -EINVAL;
}
if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP)) {
pr_err("Display of DSO requested but IP is not selected.\n"
"No addresses to convert to dso.\n");
if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
pr_err("Display of DSO requested but neither sample IP nor "
"sample address\nis selected. Hence, no addresses to convert "
"to DSO.\n");
return -EINVAL;
}

Expand Down Expand Up @@ -288,6 +298,63 @@ static void print_sample_start(struct perf_sample *sample,
}
}

static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
{
if ((attr->type == PERF_TYPE_SOFTWARE) &&
((attr->config == PERF_COUNT_SW_PAGE_FAULTS) ||
(attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) ||
(attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
return true;

return false;
}

static void print_sample_addr(union perf_event *event,
struct perf_sample *sample,
struct perf_session *session,
struct thread *thread,
struct perf_event_attr *attr)
{
struct addr_location al;
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
const char *symname, *dsoname;

printf("%16" PRIx64, sample->addr);

if (!sample_addr_correlates_sym(attr))
return;

thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
event->ip.pid, sample->addr, &al);
if (!al.map)
thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE,
event->ip.pid, sample->addr, &al);

al.cpu = sample->cpu;
al.sym = NULL;

if (al.map)
al.sym = map__find_symbol(al.map, al.addr, NULL);

if (PRINT_FIELD(SYM)) {
if (al.sym && al.sym->name)
symname = al.sym->name;
else
symname = "";

printf(" %16s", symname);
}

if (PRINT_FIELD(DSO)) {
if (al.map && al.map->dso && al.map->dso->name)
dsoname = al.map->dso->name;
else
dsoname = "";

printf(" (%s)", dsoname);
}
}

static void process_event(union perf_event *event __unused,
struct perf_sample *sample,
struct perf_evsel *evsel,
Expand All @@ -305,6 +372,9 @@ static void process_event(union perf_event *event __unused,
print_trace_event(sample->cpu, sample->raw_data,
sample->raw_size);

if (PRINT_FIELD(ADDR))
print_sample_addr(event, sample, session, thread, attr);

if (PRINT_FIELD(IP)) {
if (!symbol_conf.use_callchain)
printf(" ");
Expand Down Expand Up @@ -1003,7 +1073,7 @@ static const struct option options[] = {
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",
"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_END()
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
array++;
}

data->addr = 0;
if (type & PERF_SAMPLE_ADDR) {
data->addr = *array;
array++;
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/util/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,9 +708,9 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
if (!dump_trace)
return;

printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 "\n",
printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
event->header.misc, sample->pid, sample->tid, sample->ip,
sample->period);
sample->period, sample->addr);

if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
callchain__printf(sample);
Expand Down

0 comments on commit 7cec092

Please sign in to comment.