diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 6debb9c..55f9967 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -32,6 +32,7 @@ enum perf_output_field { PERF_OUTPUT_EVNAME = 1U << 5, PERF_OUTPUT_TRACE = 1U << 6, PERF_OUTPUT_SYM = 1U << 7, + PERF_OUTPUT_ADDR = 1U << 8, }; struct output_option { @@ -46,6 +47,7 @@ struct output_option { {.str = "event", .field = PERF_OUTPUT_EVNAME}, {.str = "trace", .field = PERF_OUTPUT_TRACE}, {.str = "sym", .field = PERF_OUTPUT_SYM}, + {.str = "addr", .field = PERF_OUTPUT_ADDR}, }; /* default set to maintain compatibility with current format */ @@ -71,7 +73,8 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, + PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM | + PERF_OUTPUT_ADDR, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -173,6 +176,11 @@ static int perf_evsel__check_attr(struct perf_session *session, PERF_OUTPUT_CPU)) return -EINVAL; + if (PRINT_FIELD(ADDR) && + perf_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR", + PERF_OUTPUT_ADDR)) + return -EINVAL; + return 0; } @@ -260,7 +268,7 @@ static void print_sample_start(struct perf_sample *sample, } } -static void process_event(union perf_event *event __unused, +static void process_event(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct perf_session *session, @@ -273,6 +281,31 @@ static void process_event(union perf_event *event __unused, print_sample_start(sample, thread, attr); + if (PRINT_FIELD(ADDR)) { + struct addr_location al; + u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + const char *symname, *dsoname; + + thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, + event->ip.pid, sample->addr, &al); + if (al.map) + al.sym = map__find_symbol(al.map, al.addr, NULL); + else + al.sym = NULL; + + if (al.sym && al.sym->name) + symname = al.sym->name; + else + symname = ""; + + if (al.map && al.map->dso && al.map->dso->name) + dsoname = al.map->dso->name; + else + dsoname = ""; + + printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname); + } + if (PRINT_FIELD(TRACE)) print_trace_event(sample->cpu, sample->raw_data, sample->raw_size); @@ -972,7 +1005,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. Fields: comm,tid,pid,time,cpu,event,trace,sym", + "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace. Fields: comm,tid,pid,time,cpu,event,trace,sym,addr", parse_output_fields), OPT_END()