Commit cc8fae1d authored by Adrian Hunter's avatar Adrian Hunter Committed by Arnaldo Carvalho de Melo

perf script: Add an option to print the source line number

Add field 'srcline' that displays the source file name and line number
associated with the sample ip.  The information displayed is the same as
from addr2line.

 $ perf script -f comm,tid,pid,time,ip,sym,dso,symoff,srcline
            grep 10701/10701 2497321.421013:  ffffffff81043ffa native_write_msr_safe+0xa ([kernel.kallsyms])
  /usr/src/debug/kernel-3.9.fc17/linux-3.9.10-100.fc17.x86_64/arch/x86/include/asm/msr.h:95
            grep 10701/10701 2497321.421984:  ffffffff8165b6b3 _raw_spin_lock+0x13 ([kernel.kallsyms])
  /usr/src/debug/kernel-3.9.fc17/linux-3.9.10-100.fc17.x86_64/arch/x86/include/asm/spinlock.h:54
            grep 10701/10701 2497321.421990:  ffffffff810b64b3 tick_sched_timer+0x53 ([kernel.kallsyms])
  /usr/src/debug/kernel-3.9.fc17/linux-3.9.10-100.fc17.x86_64/kernel/time/tick-sched.c:840
            grep 10701/10701 2497321.421992:  ffffffff8106f63f run_timer_softirq+0x2f ([kernel.kallsyms])
  /usr/src/debug/kernel-3.9.fc17/linux-3.9.10-100.fc17.x86_64/kernel/timer.c:1372
Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1386315778-11633-3-git-send-email-adrian.hunter@intel.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent a4eb24a4
...@@ -115,7 +115,7 @@ OPTIONS ...@@ -115,7 +115,7 @@ OPTIONS
-f:: -f::
--fields:: --fields::
Comma separated list of fields to print. Options are: Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff. comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline.
Field list can be prepended with the type, trace, sw or hw, Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies. 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 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
......
...@@ -43,6 +43,7 @@ enum perf_output_field { ...@@ -43,6 +43,7 @@ enum perf_output_field {
PERF_OUTPUT_DSO = 1U << 9, PERF_OUTPUT_DSO = 1U << 9,
PERF_OUTPUT_ADDR = 1U << 10, PERF_OUTPUT_ADDR = 1U << 10,
PERF_OUTPUT_SYMOFFSET = 1U << 11, PERF_OUTPUT_SYMOFFSET = 1U << 11,
PERF_OUTPUT_SRCLINE = 1U << 12,
}; };
struct output_option { struct output_option {
...@@ -61,6 +62,7 @@ struct output_option { ...@@ -61,6 +62,7 @@ struct output_option {
{.str = "dso", .field = PERF_OUTPUT_DSO}, {.str = "dso", .field = PERF_OUTPUT_DSO},
{.str = "addr", .field = PERF_OUTPUT_ADDR}, {.str = "addr", .field = PERF_OUTPUT_ADDR},
{.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
{.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
}; };
/* default set to maintain compatibility with current format */ /* default set to maintain compatibility with current format */
...@@ -210,6 +212,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, ...@@ -210,6 +212,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
"to DSO.\n"); "to DSO.\n");
return -EINVAL; return -EINVAL;
} }
if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
pr_err("Display of source line number requested but sample IP is not\n"
"selected. Hence, no address to lookup the source line number.\n");
return -EINVAL;
}
if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
...@@ -245,6 +252,9 @@ static void set_print_ip_opts(struct perf_event_attr *attr) ...@@ -245,6 +252,9 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
if (PRINT_FIELD(SYMOFFSET)) if (PRINT_FIELD(SYMOFFSET))
output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
if (PRINT_FIELD(SRCLINE))
output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE;
} }
/* /*
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "strlist.h" #include "strlist.h"
#include "vdso.h" #include "vdso.h"
#include "build-id.h" #include "build-id.h"
#include "util.h"
#include <linux/string.h> #include <linux/string.h>
const char *map_type__name[MAP__NR_TYPES] = { const char *map_type__name[MAP__NR_TYPES] = {
...@@ -252,6 +253,22 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp) ...@@ -252,6 +253,22 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
return fprintf(fp, "%s", dsoname); return fprintf(fp, "%s", dsoname);
} }
int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
FILE *fp)
{
char *srcline;
int ret = 0;
if (map && map->dso) {
srcline = get_srcline(map->dso,
map__rip_2objdump(map, addr));
if (srcline != SRCLINE_UNKNOWN)
ret = fprintf(fp, "%s%s", prefix, srcline);
free_srcline(srcline);
}
return ret;
}
/** /**
* map__rip_2objdump - convert symbol start address to objdump address. * map__rip_2objdump - convert symbol start address to objdump address.
* @map: memory map * @map: memory map
......
...@@ -103,6 +103,8 @@ struct map *map__clone(struct map *map); ...@@ -103,6 +103,8 @@ struct map *map__clone(struct map *map);
int map__overlap(struct map *l, struct map *r); int map__overlap(struct map *l, struct map *r);
size_t map__fprintf(struct map *map, FILE *fp); size_t map__fprintf(struct map *map, FILE *fp);
size_t map__fprintf_dsoname(struct map *map, FILE *fp); size_t map__fprintf_dsoname(struct map *map, FILE *fp);
int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
FILE *fp);
int map__load(struct map *map, symbol_filter_t filter); int map__load(struct map *map, symbol_filter_t filter);
struct symbol *map__find_symbol(struct map *map, struct symbol *map__find_symbol(struct map *map,
......
...@@ -1497,6 +1497,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, ...@@ -1497,6 +1497,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
int print_dso = print_opts & PRINT_IP_OPT_DSO; int print_dso = print_opts & PRINT_IP_OPT_DSO;
int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
char s = print_oneline ? ' ' : '\t'; char s = print_oneline ? ' ' : '\t';
if (symbol_conf.use_callchain && sample->callchain) { if (symbol_conf.use_callchain && sample->callchain) {
...@@ -1546,6 +1547,10 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, ...@@ -1546,6 +1547,10 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
printf(")"); printf(")");
} }
if (print_srcline)
map__fprintf_srcline(node->map, addr, "\n ",
stdout);
if (!print_oneline) if (!print_oneline)
printf("\n"); printf("\n");
...@@ -1575,6 +1580,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, ...@@ -1575,6 +1580,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
map__fprintf_dsoname(al->map, stdout); map__fprintf_dsoname(al->map, stdout);
printf(")"); printf(")");
} }
if (print_srcline)
map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
} }
} }
......
...@@ -45,6 +45,7 @@ struct perf_session { ...@@ -45,6 +45,7 @@ struct perf_session {
#define PRINT_IP_OPT_DSO (1<<2) #define PRINT_IP_OPT_DSO (1<<2)
#define PRINT_IP_OPT_SYMOFFSET (1<<3) #define PRINT_IP_OPT_SYMOFFSET (1<<3)
#define PRINT_IP_OPT_ONELINE (1<<4) #define PRINT_IP_OPT_ONELINE (1<<4)
#define PRINT_IP_OPT_SRCLINE (1<<5)
struct perf_tool; struct perf_tool;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment