Skip to contentSkip to conversation

perf script: add BTS analysis features

PATCH Superseded Akihiro Nagai 3 participants 13 messages Aug 11, 2011 – Aug 22, 2011

Subsystems (2)

v3 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v3 cover perf script: add BTS analysis features

Hi Frederic, David,

This patch series adds the functions to analyze BTS logs to perf-script and, makes perf-script more informative version 3.
The patches add the following functions.
- Unify the expression to "[unknown]"
- Fix BTS record header to resolve DSOs and symbols of user-space
- Resolve DSOs and symbols for BTS's branch_from addresses
- Show the offset of symbols with the 'offs' field specifier.
- Resolve the real path of [kernel.kallsym] using '--show-kernel-path' option.

Usage:
First, get the BTS log with the following command.

# perf record -e branches:u -c 1 -d <command>

Second, analyze that trace data.

# perf script -f ip,addr,sym,offs,dso [--show-kernel-path]
This command's output format is:
<branch_to addr> <branch_to function+offset> <branch_to DSO> <branch_from addr> <branch_from function+offset> <branch_from DSO>

Output sample:

# perf record -e branches:u -c 1 -d ls
[snip]
# perf script -f ip,addr,sym,dso,offs --show-kernel-path
34308016b0 _start+0x0     (/lib64/ld-2.14.so) ffffffff81465a6d irq_return+0x0 (/lib/modules/3.0.0+/build/vmlinux)
34308016b0 _start+0x0     (/lib64/ld-2.14.so) ffffffff81465a6d irq_return+0x0 (/lib/modules/3.0.0+/build/vmlinux)
3430804b80 _dl_start+0x0  (/lib64/ld-2.14.so)       34308016b3 _start+0x3     (/lib64/ld-2.14.so)
3430804b80 _dl_start+0x0  (/lib64/ld-2.14.so) ffffffff81465a6d irq_return+0x0 (/lib/modules/3.0.0+/build/vmlinux)

3430804ba6 _dl_start+0x26 (/lib64/ld-2.14.so) ffffffff81465a6d irq_return+0x0 (/lib/modules/3.0.0+/build/vmlinux) 3430804bad _dl_start+0x2d (/lib64/ld-2.14.so) ffffffff81465a6d irq_return+0x0 (/lib/modules/3.0.0+/build/vmlinux)
3430804c1d _dl_start+0x9d (/lib64/ld-2.14.so) 3430804bfb _dl_start+0x7b (/lib64/ld-2.14.so)
3430804c00 _dl_start+0x80 (/lib64/ld-2.14.so) 3430804c21 _dl_start+0xa1 (/lib64/ld-2.14.so)
[snip]
401fd0 main+0x0 (/root/bin/ls) 3430c21399 __libc_start_main+0xe9 (/lib64/libc-2.14.so)

409ad0 set_program_name+0x0 (/root/bin/ls)           401ff3 main+0x23              (/root/bin/ls)
409ad0 set_program_name+0x0 (/root/bin/ls) ffffffff81465a6d irq_return+0x0         (/lib/modules/3.0.0+/build/vmlinux)
401ca8 strrchr@plt+0x0      (/root/bin/ls)           409ade set_program_name+0xe   (/root/bin/ls)
401cae strrchr@plt+0x6      (/root/bin/ls)           401ca8 strrchr@plt+0x0        (/root/bin/ls)
401a38 _init+0x18           (/root/bin/ls)           401cb3 strrchr@plt+0xb        (/root/bin/ls)

3430813850 _dl_runtime_resolve+0x0 (/lib64/ld-2.14.so) 401a3e _init+0x1e (/root/bin/ls)
[snip]

It shows the tracee application's execution path.

TODO:
- add source code path field, line number field ...etc.
- add record/report script to use easily and, show human-friendly output.
- filtering kernel functions using scripts

Changes in v3:
- remove the bug fix patch already fixed.
- unify the "[unknown]" expressions in perf-script.
- fix perf_event_header of BTS events.
- fix patch's descriptions

Changes in v2:
- add a bug fix patch that prints correct IP address
- output the magic word "(unknown)" as symbol name when perf-script can't resolve symbols.
- output "[unknown]" as DSO name when perf-script can't resolve DSO path.
- change the way to output offset of symbols from '--show-symbol-offset' to 'offs' field.
- clean up codes.

Thanks,

---

Akihiro Nagai (5):
perf script: add option resolving vmlinux path
perf script: add the offset field specifier
perf script: enhance IP and ADDR correlate detection for BTS
perf: change perf_event_header.misc to PERF_RECORD_MISC_USER for BTS
perf-script: unify the expressions indicate "unknown"

 arch/x86/kernel/cpu/perf_event_intel_ds.c |    8 +++++
 tools/perf/Documentation/perf-script.txt  |    5 +++
 tools/perf/builtin-script.c               |   44 +++++++++++++++++++----------
 tools/perf/util/map.c                     |   15 ++++++++++
 tools/perf/util/map.h                     |    1 +
 tools/perf/util/session.c                 |   38 +++++++++----------------
 tools/perf/util/session.h                 |    3 +-
 tools/perf/util/symbol.c                  |   20 +++++++++++++
 tools/perf/util/symbol.h                  |    4 +++
 9 files changed, 96 insertions(+), 42 deletions(-)
Signature · 1 line
Akihiro Nagai ([email protected])
#1 lore raw

PATCH v3 1/5 perf-script: unify the expressions indicate "unknown"

perf-script uses various expressions to indicate "unknown". It is unfriendly for user scripts to parse it. So, this patch unifies the expressions to "[unknown]".

Changes in v3:
- unify all expressions to [unknown]

Changes in v2:
- add this patch

Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc David Ahern <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---

 tools/perf/builtin-script.c |   20 ++++++--------------
 tools/perf/util/map.c       |   12 ++++++++++++
 tools/perf/util/map.h       |    1 +
 tools/perf/util/session.c   |   35 ++++++++++-------------------------
 tools/perf/util/symbol.c    |   12 ++++++++++++
 tools/perf/util/symbol.h    |    1 +
 6 files changed, 42 insertions(+), 39 deletions(-)
tools/perf/builtin-script.c +6 -14
index 09024ec..b3312ff 100644
@@ -297,7 +297,7 @@ static void print_sample_start(struct perf_sample *sample,
 		} else
 			evname = __event_name(attr->type, attr->config);
 
-		printf("%s: ", evname ? evname : "(unknown)");
+		printf("%s: ", evname ? evname : "[unknown]");
 	}
 }
 
@@ -320,7 +320,6 @@ static void print_sample_addr(union perf_event *event,
 {
 	struct addr_location al;
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-	const char *symname, *dsoname;
 
 	printf("%16" PRIx64, sample->addr);
 
@@ -340,21 +339,14 @@ static void print_sample_addr(union perf_event *event,
 		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);
+		printf(" ");
+		symbol__print_symname(al.sym);
 	}
 
 	if (PRINT_FIELD(DSO)) {
-		if (al.map && al.map->dso && al.map->dso->name)
-			dsoname = al.map->dso->name;
-		else
-			dsoname = "";
-
-		printf(" (%s)", dsoname);
+		printf(" (");
+		map__print_dsoname(al.map);
+		printf(")");
 	}
 }
 
tools/perf/util/map.c +12 -0
index a16ecab..530a5ea 100644
@@ -200,6 +200,18 @@ size_t map__fprintf(struct map *self, FILE *fp)
 		       self->start, self->end, self->pgoff, self->dso->name);
 }
 
+void map__print_dsoname(struct map *self)
+{
+	const char *dsoname;
+
+	if (self && self->dso && self->dso->name)
+		dsoname = self->dso->name;
+	else
+		dsoname = "[unknown]";
+
+	printf("%s", dsoname);
+}
+
 /*
  * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
  * map->dso->adjust_symbols==1 for ET_EXEC-like cases.
tools/perf/util/map.h +1 -0
index b397c03..6f452b9 100644
@@ -112,6 +112,7 @@ void map__delete(struct map *self);
 struct map *map__clone(struct map *self);
 int map__overlap(struct map *l, struct map *r);
 size_t map__fprintf(struct map *self, FILE *fp);
+void map__print_dsoname(struct map *self);
 
 int map__load(struct map *self, symbol_filter_t filter);
 struct symbol *map__find_symbol(struct map *self,
tools/perf/util/session.c +10 -25
index 72458d9..730fcd2 100644
@@ -1220,7 +1220,6 @@ void perf_session__print_ip(union perf_event *event,
 			    int print_sym, int print_dso)
 {
 	struct addr_location al;
-	const char *symname, *dsoname;
 	struct callchain_cursor *cursor = &session->callchain_cursor;
 	struct callchain_cursor_node *node;
 
@@ -1248,20 +1247,13 @@ void perf_session__print_ip(union perf_event *event,
 
 			printf("\t%16" PRIx64, node->ip);
 			if (print_sym) {
-				if (node->sym && node->sym->name)
-					symname = node->sym->name;
-				else
-					symname = "";
-
-				printf(" %s", symname);
+				printf(" ");
+				symbol__print_symname(node->sym);
 			}
 			if (print_dso) {
-				if (node->map && node->map->dso && node->map->dso->name)
-					dsoname = node->map->dso->name;
-				else
-					dsoname = "";
-
-				printf(" (%s)", dsoname);
+				printf(" (");
+				map__print_dsoname(al.map);
+				printf(")");
 			}
 			printf("\n");
 
@@ -1271,21 +1263,14 @@ void perf_session__print_ip(union perf_event *event,
 	} else {
 		printf("%16" PRIx64, sample->ip);
 		if (print_sym) {
-			if (al.sym && al.sym->name)
-				symname = al.sym->name;
-			else
-				symname = "";
-
-			printf(" %s", symname);
+			printf(" ");
+			symbol__print_symname(al.sym);
 		}
 
 		if (print_dso) {
-			if (al.map && al.map->dso && al.map->dso->name)
-				dsoname = al.map->dso->name;
-			else
-				dsoname = "";
-
-			printf(" (%s)", dsoname);
+			printf(" (");
+			map__print_dsoname(al.map);
+			printf(")");
 		}
 	}
 }
tools/perf/util/symbol.c +12 -0
index eec1963..aa37485 100644
@@ -175,6 +175,18 @@ static size_t symbol__fprintf(struct symbol *sym, FILE *fp)
 		       sym->name);
 }
 
+void symbol__print_symname(const struct symbol *sym)
+{
+	const char *symname;
+
+	if (sym && sym->name)
+		symname = sym->name;
+	else
+		symname = "[unknown]";
+
+	printf("%s", symname);
+}
+
 void dso__set_long_name(struct dso *dso, char *name)
 {
 	if (name == NULL)
tools/perf/util/symbol.h +1 -0
index 325ee36..1ec17b4 100644
@@ -238,6 +238,7 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines);
 
 int symbol__init(void);
 void symbol__exit(void);
+void symbol__print_symname(const struct symbol *sym);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
 
 size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
Acked-by on v3 1/5
#2 lore raw

Re: [PATCH -tip v3 1/5] perf-script: unify the expressions indicate "unknown"

Quoted 205 lines · Akihiro Nagai

perf-script uses various expressions to indicate "unknown". It is unfriendly for user scripts to parse it. So, this patch unifies the expressions to "[unknown]".

Changes in v3:
- unify all expressions to [unknown]

Changes in v2:
- add this patch

Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc David Ahern <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---

 tools/perf/builtin-script.c |   20 ++++++--------------
 tools/perf/util/map.c       |   12 ++++++++++++
 tools/perf/util/map.h       |    1 +
 tools/perf/util/session.c   |   35 ++++++++++-------------------------
 tools/perf/util/symbol.c    |   12 ++++++++++++
 tools/perf/util/symbol.h    |    1 +
 6 files changed, 42 insertions(+), 39 deletions(-)
tools/perf/builtin-script.c +6 -14
index 09024ec..b3312ff 100644
@@ -297,7 +297,7 @@ static void print_sample_start(struct perf_sample *sample,
 		} else
 			evname = __event_name(attr->type, attr->config);
 
-		printf("%s: ", evname ? evname : "(unknown)");
+		printf("%s: ", evname ? evname : "[unknown]");
 	}
 }
 
@@ -320,7 +320,6 @@ static void print_sample_addr(union perf_event *event,
 {
 	struct addr_location al;
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-	const char *symname, *dsoname;
 
 	printf("%16" PRIx64, sample->addr);
 
@@ -340,21 +339,14 @@ static void print_sample_addr(union perf_event *event,
 		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);
+		printf(" ");
+		symbol__print_symname(al.sym);
 	}
 
 	if (PRINT_FIELD(DSO)) {
-		if (al.map && al.map->dso && al.map->dso->name)
-			dsoname = al.map->dso->name;
-		else
-			dsoname = "";
-
-		printf(" (%s)", dsoname);
+		printf(" (");
+		map__print_dsoname(al.map);
+		printf(")");
 	}
 }
 
tools/perf/util/map.c +12 -0
index a16ecab..530a5ea 100644
@@ -200,6 +200,18 @@ size_t map__fprintf(struct map *self, FILE *fp)
 		       self->start, self->end, self->pgoff, self->dso->name);
 }
 
+void map__print_dsoname(struct map *self)
+{
+	const char *dsoname;
+
+	if (self && self->dso && self->dso->name)
+		dsoname = self->dso->name;
+	else
+		dsoname = "[unknown]";
+
+	printf("%s", dsoname);
+}
+
 /*
  * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
  * map->dso->adjust_symbols==1 for ET_EXEC-like cases.
tools/perf/util/map.h +1 -0
index b397c03..6f452b9 100644
@@ -112,6 +112,7 @@ void map__delete(struct map *self);
 struct map *map__clone(struct map *self);
 int map__overlap(struct map *l, struct map *r);
 size_t map__fprintf(struct map *self, FILE *fp);
+void map__print_dsoname(struct map *self);
 
 int map__load(struct map *self, symbol_filter_t filter);
 struct symbol *map__find_symbol(struct map *self,
tools/perf/util/session.c +10 -25
index 72458d9..730fcd2 100644
@@ -1220,7 +1220,6 @@ void perf_session__print_ip(union perf_event *event,
 			    int print_sym, int print_dso)
 {
 	struct addr_location al;
-	const char *symname, *dsoname;
 	struct callchain_cursor *cursor = &session->callchain_cursor;
 	struct callchain_cursor_node *node;
 
@@ -1248,20 +1247,13 @@ void perf_session__print_ip(union perf_event *event,
 
 			printf("\t%16" PRIx64, node->ip);
 			if (print_sym) {
-				if (node->sym && node->sym->name)
-					symname = node->sym->name;
-				else
-					symname = "";
-
-				printf(" %s", symname);
+				printf(" ");
+				symbol__print_symname(node->sym);
 			}
 			if (print_dso) {
-				if (node->map && node->map->dso && node->map->dso->name)
-					dsoname = node->map->dso->name;
-				else
-					dsoname = "";
-
-				printf(" (%s)", dsoname);
+				printf(" (");
+				map__print_dsoname(al.map);
+				printf(")");
 			}
 			printf("\n");
 
@@ -1271,21 +1263,14 @@ void perf_session__print_ip(union perf_event *event,
 	} else {
 		printf("%16" PRIx64, sample->ip);
 		if (print_sym) {
-			if (al.sym && al.sym->name)
-				symname = al.sym->name;
-			else
-				symname = "";
-
-			printf(" %s", symname);
+			printf(" ");
+			symbol__print_symname(al.sym);
 		}
 
 		if (print_dso) {
-			if (al.map && al.map->dso && al.map->dso->name)
-				dsoname = al.map->dso->name;
-			else
-				dsoname = "";
-
-			printf(" (%s)", dsoname);
+			printf(" (");
+			map__print_dsoname(al.map);
+			printf(")");
 		}
 	}
 }
tools/perf/util/symbol.c +12 -0
index eec1963..aa37485 100644
@@ -175,6 +175,18 @@ static size_t symbol__fprintf(struct symbol *sym, FILE *fp)
 		       sym->name);
 }
 
+void symbol__print_symname(const struct symbol *sym)
+{
+	const char *symname;
+
+	if (sym && sym->name)
+		symname = sym->name;
+	else
+		symname = "[unknown]";
+
+	printf("%s", symname);
+}
+
 void dso__set_long_name(struct dso *dso, char *name)
 {
 	if (name == NULL)
tools/perf/util/symbol.h +0 -0
index 325ee36..1ec17b4 100644

tools/perf/util/symbol.h void machines__destroy_guest_kernel_maps(struct rb_root *machines); · line 244

Quoted 7 lines
tools/perf/util/symbol.h +1 -0
@@ -238,6 +238,7 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines);
 
 int symbol__init(void);
 void symbol__exit(void);
+void symbol__print_symname(const struct symbol *sym);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
 
 size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
#3 lore raw

PATCH v3 2/5 perf: change perf_event_header.misc to PERF_RECORD_MISC_USER for BTS

In reply to Akihiro Nagai

Change perf_event_headder.misc to PERF_RECORD_MISC_USER for BTS records, because BTS traces both kernel and user spaces nevertheless perf specifies to trace only kernel or user space.

Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc David Ahern <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---

 arch/x86/kernel/cpu/perf_event_intel_ds.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/perf_event_intel_ds.c +8 -0
index 1b1ef3a..323f3f0 100644
@@ -340,6 +340,14 @@ static int intel_pmu_drain_bts_buffer(void)
 	 */
 	perf_prepare_sample(&header, &data, event, &regs);
 
+	/*
+	 * Since BTS can not trace kernel and user space separately, set
+	 * PERF_RECORD_MISC_USER in header.misc to resolve both kernel and
+	 * user DSOs and symbols.
+	 */
+	header.misc &= ~PERF_RECORD_MISC_CPUMODE_MASK;
+	header.misc |= PERF_RECORD_MISC_USER;
+
 	if (perf_output_begin(&handle, event, header.size * (top - at)))
 		return 1;
 
maintainer
#4 lore raw

Re: [PATCH -tip v3 2/5] perf: change perf_event_header.misc to PERF_RECORD_MISC_USER for BTS

Quoted 3 lines · Akihiro Nagai

Change perf_event_headder.misc to PERF_RECORD_MISC_USER for BTS records, because BTS traces both kernel and user spaces nevertheless perf specifies to trace only kernel or user space.

Now I'm confused..

If BTS traces both kernel and user, the MISC bit should reflect the right state per-sample, on x86 that's easy enough to do by the address.

Quoted 10 lines

---

 arch/x86/kernel/cpu/perf_event_intel_ds.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/perf_event_intel_ds.c +0 -0
index 1b1ef3a..323f3f0 100644

arch/x86/kernel/cpu/perf_event_intel_ds.c static int intel_pmu_drain_bts_buffer(void) · line 344

Quoted 5 lines
arch/x86/kernel/cpu/perf_event_intel_ds.c +2 -0
@@ -340,6 +340,14 @@ static int intel_pmu_drain_bts_buffer(void)
 	 */
 	perf_prepare_sample(&header, &data, event, &regs);
 
+	/*
+	 * Since BTS can not trace kernel and user space separately, set

Uhm, IA32_DEBUGCTL_MSR.BTS_OFF_{OS,USR} seem to suggest it can?!

arch/x86/kernel/cpu/perf_event_intel_ds.c static int intel_pmu_drain_bts_buffer(void) · line 349

Quoted 5 lines
arch/x86/kernel/cpu/perf_event_intel_ds.c +5 -0
+	 * PERF_RECORD_MISC_USER in header.misc to resolve both kernel and
+	 * user DSOs and symbols.
+	 */
+	header.misc &= ~PERF_RECORD_MISC_CPUMODE_MASK;
+	header.misc |= PERF_RECORD_MISC_USER;

So what's wrong with something like:

	header.misc |= is_kernel_address(at->from) ?
			PERF_RECORD_MISC_KERNEL :
			PERF_RECORD_MISC_USER;
Quoted 4 lines
arch/x86/kernel/cpu/perf_event_intel_ds.c +0 -0
 	if (perf_output_begin(&handle, event, header.size * (top - at)))
 		return 1;
 
#5 lore raw

Re: [PATCH -tip v3 2/5] perf: change perf_event_header.misc to PERF_RECORD_MISC_USER for BTS

Quoted 9 lines · Peter Zijlstra
Quoted 3 lines · Akihiro Nagai

Change perf_event_headder.misc to PERF_RECORD_MISC_USER for BTS records, because BTS traces both kernel and user spaces nevertheless perf specifies to trace only kernel or user space.

Now I'm confused..

If BTS traces both kernel and user, the MISC bit should reflect the right state per-sample, on x86 that's easy enough to do by the address.

Yes.
However, PERF_RECORD_MISC_KERNEL can be specified only when
both from_addr and to_addr are kernel-space. Since current perf always enables IA32_DEBUGCTL_MSR.BTS_OFF_OS flag when it uses BTS, such BTS records are not output. So, it's enough to specify only PERF_RECORD_MISC_USER.

Quoted 15 lines
Quoted 15 lines

---

  arch/x86/kernel/cpu/perf_event_intel_ds.c |    8 ++++++++
  1 files changed, 8 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/perf_event_intel_ds.c +0 -0
index 1b1ef3a..323f3f0 100644
@@ -340,6 +340,14 @@ static int intel_pmu_drain_bts_buffer(void)
  	 */
  	perf_prepare_sample(&header,&data, event,&regs);
 
Quoted 4 lines

arch/x86/kernel/cpu/perf_event_intel_ds.c static int intel_pmu_drain_bts_buffer(void) · line 344

Quoted 2 lines
arch/x86/kernel/cpu/perf_event_intel_ds.c +2 -0
+	/*
+	 * Since BTS can not trace kernel and user space separately, set

Uhm, IA32_DEBUGCTL_MSR.BTS_OFF_{OS,USR} seem to suggest it can?!

Current perf always enables IA32_DEBUGCTL_MSR.BTS_OFF_OS when traces with BTS. However, BTS records branches which jump from kernel(irq_return) to user, because the msr is to stop tracing in Ring0. It's different with kernel-space in the strict sense.

Quoted 10 lines

arch/x86/kernel/cpu/perf_event_intel_ds.c static int intel_pmu_drain_bts_buffer(void) · line 349

Quoted 6 lines
arch/x86/kernel/cpu/perf_event_intel_ds.c +5 -0
+	 * PERF_RECORD_MISC_USER in header.misc to resolve both kernel and
+	 * user DSOs and symbols.
+	 */
+	header.misc&= ~PERF_RECORD_MISC_CPUMODE_MASK;
+	header.misc |= PERF_RECORD_MISC_USER;

So what's wrong with something like:

Quoted 4 lines
	header.misc |= is_kernel_address(at->from) ?
			PERF_RECORD_MISC_KERNEL :
			PERF_RECORD_MISC_USER;

It looks good.
However, current perf doesn't output "kernel to kernel" BTS records. So, it is unnecessary yet.

Thank you.

Quoted 6 lines
Quoted 4 lines
arch/x86/kernel/cpu/perf_event_intel_ds.c +0 -0
  	if (perf_output_begin(&handle, event, header.size * (top - at)))
  		return 1;
 
maintainer
#6 lore raw

Re: [PATCH -tip v3 2/5] perf: change perf_event_header.misc to PERF_RECORD_MISC_USER for BTS

Quoted 10 lines · Akihiro Nagai
Quoted 6 lines

So what's wrong with something like:

      header.misc |= is_kernel_address(at->from) ?
                      PERF_RECORD_MISC_KERNEL :
                      PERF_RECORD_MISC_USER;

It looks good.
However, current perf doesn't output "kernel to kernel" BTS records. So, it is unnecessary yet.

Ah, right, I thought we cured that at some point, ok all clear now.

#7 lore raw

PATCH v3 3/5 perf script: enhance IP and ADDR correlate detection for BTS

In reply to Akihiro Nagai

BTS records branch_from_addr and branch_to_addr in IP and ADDR field in perf_sample. This patch detects this correlation in perf-script.

# perf script -f ip,addr,dso,sym
3f03e016b0    _start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e016b0    _start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e04b80 _dl_start (/lib64/ld-2.14.so)       3f03e016b3     _start (/lib64/ld-2.14.so)
3f03e04b80 _dl_start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e04ba6 _dl_start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e04bad _dl_start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e04c1d _dl_start (/lib64/ld-2.14.so)       3f03e04bfb  _dl_start (/lib64/ld-2.14.so)
[snip]
Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc David Ahern <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---

 tools/perf/builtin-script.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
tools/perf/builtin-script.c +6 -0
index b3312ff..aeec5bc 100644
@@ -309,6 +309,12 @@ static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
 	     (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
 		return true;
 
+	/* BTS Events */
+	if ((attr->type == PERF_TYPE_HARDWARE) &&
+	    (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
+	    (attr->sample_period == 1))
+		return true;
+
 	return false;
 }
 
Acked-by on v3 3/5
#8 lore raw

Re: [PATCH -tip v3 3/5] perf script: enhance IP and ADDR correlate detection for BTS

Quoted 34 lines · Akihiro Nagai

BTS records branch_from_addr and branch_to_addr in IP and ADDR field in perf_sample. This patch detects this correlation in perf-script.

# perf script -f ip,addr,dso,sym
3f03e016b0    _start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e016b0    _start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e04b80 _dl_start (/lib64/ld-2.14.so)       3f03e016b3     _start (/lib64/ld-2.14.so)
3f03e04b80 _dl_start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e04ba6 _dl_start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e04bad _dl_start (/lib64/ld-2.14.so) ffffffff814675d2 irq_return ([kernel.kallsyms])
3f03e04c1d _dl_start (/lib64/ld-2.14.so)       3f03e04bfb  _dl_start (/lib64/ld-2.14.so)
[snip]
Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc David Ahern <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---

 tools/perf/builtin-script.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
tools/perf/builtin-script.c +0 -0
index b3312ff..aeec5bc 100644
@@ -309,6 +309,12 @@ static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
 	     (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
 		return true;

tools/perf/builtin-script.c static bool sample_addr_correlates_sym(struct perf_event_attr *attr) · line 320

Quoted 10 lines
tools/perf/builtin-script.c +6 -0
 
+	/* BTS Events */
+	if ((attr->type == PERF_TYPE_HARDWARE) &&
+	    (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
+	    (attr->sample_period == 1))
+		return true;
+
 	return false;
 }
 
#9 lore raw

PATCH v3 4/5 perf script: add the offset field specifier

In reply to Akihiro Nagai

Add the offset field specifier 'offs' to show the offset from the symbols in the output of perf-script. We can get the more detailed address information.

Output sample:

# perf script -f ip,addr,sym,offs
301ec016b0            _start+0x0 ffffffff81467612 irq_return+0x0
301ec016b0            _start+0x0 ffffffff81467612 irq_return+0x0
301ec04b70         _dl_start+0x0       301ec016b3 _start+0x3
301ec04b70         _dl_start+0x0 ffffffff81467612 irq_return+0x0
301ec04b96        _dl_start+0x26 ffffffff81467612 irq_return+0x0
301ec04b9d        _dl_start+0x2d ffffffff81467612 irq_return+0x0
301ec04c0d        _dl_start+0x9d       301ec04beb _dl_start+0x7b
301ec04bf0        _dl_start+0x80       301ec04c11 _dl_start+0xa1
[snip]

Changes in v2:
- change the way to output offset from '--show-symbol-offset' to 'offs' field.
- clean up codes.

Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc David Ahern <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---

 tools/perf/Documentation/perf-script.txt |    2 +-
 tools/perf/builtin-script.c              |   20 +++++++++++++++++---
 tools/perf/util/session.c                |    7 +++++--
 tools/perf/util/session.h                |    3 ++-
 tools/perf/util/symbol.c                 |   22 +++++++++++++++-------
 tools/perf/util/symbol.h                 |    2 ++
 6 files changed, 42 insertions(+), 14 deletions(-)
tools/perf/Documentation/perf-script.txt +1 -1
index db01786..ee4d477 100644
@@ -115,7 +115,7 @@ OPTIONS
 -f::
 --fields::
         Comma separated list of fields to print. Options are:
-        comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr.
+        comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, offs.
         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
tools/perf/builtin-script.c +17 -3
index aeec5bc..78797b3 100644
@@ -37,6 +37,7 @@ enum perf_output_field {
 	PERF_OUTPUT_SYM             = 1U << 8,
 	PERF_OUTPUT_DSO             = 1U << 9,
 	PERF_OUTPUT_ADDR            = 1U << 10,
+	PERF_OUTPUT_OFFSET          = 1U << 11,
 };
 
 struct output_option {
@@ -54,6 +55,7 @@ struct output_option {
 	{.str = "sym",   .field = PERF_OUTPUT_SYM},
 	{.str = "dso",   .field = PERF_OUTPUT_DSO},
 	{.str = "addr",  .field = PERF_OUTPUT_ADDR},
+	{.str = "offs",  .field = PERF_OUTPUT_OFFSET},
 };
 
 /* default set to maintain compatibility with current format */
@@ -190,6 +192,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
 		       "to symbols.\n");
 		return -EINVAL;
 	}
+	if (PRINT_FIELD(OFFSET) && !PRINT_FIELD(SYM)) {
+		pr_err("Display of offsets requested but symbol is not"
+		       "selected.\n");
+		return -EINVAL;
+	}
 	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 "
@@ -346,7 +353,10 @@ static void print_sample_addr(union perf_event *event,
 
 	if (PRINT_FIELD(SYM)) {
 		printf(" ");
-		symbol__print_symname(al.sym);
+		if (PRINT_FIELD(OFFSET))
+			symbol__print_symname_offs(al.sym, &al);
+		else
+			symbol__print_symname(al.sym);
 	}
 
 	if (PRINT_FIELD(DSO)) {
@@ -382,7 +392,8 @@ static void process_event(union perf_event *event __unused,
 		else
 			printf("\n");
 		perf_session__print_ip(event, sample, session,
-					      PRINT_FIELD(SYM), PRINT_FIELD(DSO));
+				       PRINT_FIELD(SYM), PRINT_FIELD(DSO),
+				       PRINT_FIELD(OFFSET));
 	}
 
 	printf("\n");
@@ -1078,7 +1089,10 @@ 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,addr",
+		     "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,offs",
 		     parse_output_fields),
 	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
 
tools/perf/util/session.c +5 -2
index 730fcd2..51d0a28 100644
@@ -1217,7 +1217,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 void perf_session__print_ip(union perf_event *event,
 			    struct perf_sample *sample,
 			    struct perf_session *session,
-			    int print_sym, int print_dso)
+			    int print_sym, int print_dso, int print_offset)
 {
 	struct addr_location al;
 	struct callchain_cursor *cursor = &session->callchain_cursor;
@@ -1264,7 +1264,10 @@ void perf_session__print_ip(union perf_event *event,
 		printf("%16" PRIx64, sample->ip);
 		if (print_sym) {
 			printf(" ");
-			symbol__print_symname(al.sym);
+			if (print_offset)
+				symbol__print_symname_offs(al.sym, &al);
+			else
+				symbol__print_symname(al.sym);
 		}
 
 		if (print_dso) {
tools/perf/util/session.h +2 -1
index 170601e..2689017 100644
@@ -171,7 +171,8 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 void perf_session__print_ip(union perf_event *event,
 				 struct perf_sample *sample,
 				 struct perf_session *session,
-				 int print_sym, int print_dso);
+				 int print_sym, int print_dso,
+				 int print_offset);
 
 int perf_session__cpu_bitmap(struct perf_session *session,
 			     const char *cpu_list, unsigned long *cpu_bitmap);
tools/perf/util/symbol.c +15 -7
index aa37485..28e14be 100644
@@ -175,16 +175,24 @@ static size_t symbol__fprintf(struct symbol *sym, FILE *fp)
 		       sym->name);
 }
 
-void symbol__print_symname(const struct symbol *sym)
+void symbol__print_symname_offs(const struct symbol *sym,
+				const struct addr_location *al)
 {
-	const char *symname;
+	unsigned long offset;
 
-	if (sym && sym->name)
-		symname = sym->name;
-	else
-		symname = "[unknown]";
+	if (sym && sym->name) {
+		printf("%s", sym->name);
+		if (al) {
+			offset = al->addr - sym->start;
+			printf("+0x%lx", offset);
+		}
+	} else
+		printf("[unknown]");
+}
 
-	printf("%s", symname);
+void symbol__print_symname(const struct symbol *sym)
+{
+	symbol__print_symname_offs(sym, NULL);
 }
 
 void dso__set_long_name(struct dso *dso, char *name)
tools/perf/util/symbol.h +2 -0
index 1ec17b4..554b2fe 100644
@@ -238,6 +238,8 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines);
 
 int symbol__init(void);
 void symbol__exit(void);
+void symbol__print_symname_offs(const struct symbol *sym,
+				const struct addr_location *al);
 void symbol__print_symname(const struct symbol *sym);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
 
Acked-by on v3 4/5
#10 lore raw

Re: [PATCH -tip v3 4/5] perf script: add the offset field specifier

Quoted 199 lines · Akihiro Nagai

Add the offset field specifier 'offs' to show the offset from the symbols in the output of perf-script. We can get the more detailed address information.

Output sample:

# perf script -f ip,addr,sym,offs
301ec016b0            _start+0x0 ffffffff81467612 irq_return+0x0
301ec016b0            _start+0x0 ffffffff81467612 irq_return+0x0
301ec04b70         _dl_start+0x0       301ec016b3 _start+0x3
301ec04b70         _dl_start+0x0 ffffffff81467612 irq_return+0x0
301ec04b96        _dl_start+0x26 ffffffff81467612 irq_return+0x0
301ec04b9d        _dl_start+0x2d ffffffff81467612 irq_return+0x0
301ec04c0d        _dl_start+0x9d       301ec04beb _dl_start+0x7b
301ec04bf0        _dl_start+0x80       301ec04c11 _dl_start+0xa1
[snip]

Changes in v2:
- change the way to output offset from '--show-symbol-offset' to 'offs' field.
- clean up codes.

Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc David Ahern <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---

 tools/perf/Documentation/perf-script.txt |    2 +-
 tools/perf/builtin-script.c              |   20 +++++++++++++++++---
 tools/perf/util/session.c                |    7 +++++--
 tools/perf/util/session.h                |    3 ++-
 tools/perf/util/symbol.c                 |   22 +++++++++++++++-------
 tools/perf/util/symbol.h                 |    2 ++
 6 files changed, 42 insertions(+), 14 deletions(-)
tools/perf/Documentation/perf-script.txt +1 -1
index db01786..ee4d477 100644
@@ -115,7 +115,7 @@ OPTIONS
 -f::
 --fields::
         Comma separated list of fields to print. Options are:
-        comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr.
+        comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, offs.
         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
tools/perf/builtin-script.c +17 -3
index aeec5bc..78797b3 100644
@@ -37,6 +37,7 @@ enum perf_output_field {
 	PERF_OUTPUT_SYM             = 1U << 8,
 	PERF_OUTPUT_DSO             = 1U << 9,
 	PERF_OUTPUT_ADDR            = 1U << 10,
+	PERF_OUTPUT_OFFSET          = 1U << 11,
 };
 
 struct output_option {
@@ -54,6 +55,7 @@ struct output_option {
 	{.str = "sym",   .field = PERF_OUTPUT_SYM},
 	{.str = "dso",   .field = PERF_OUTPUT_DSO},
 	{.str = "addr",  .field = PERF_OUTPUT_ADDR},
+	{.str = "offs",  .field = PERF_OUTPUT_OFFSET},
 };
 
 /* default set to maintain compatibility with current format */
@@ -190,6 +192,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
 		       "to symbols.\n");
 		return -EINVAL;
 	}
+	if (PRINT_FIELD(OFFSET) && !PRINT_FIELD(SYM)) {
+		pr_err("Display of offsets requested but symbol is not"
+		       "selected.\n");
+		return -EINVAL;
+	}
 	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 "
@@ -346,7 +353,10 @@ static void print_sample_addr(union perf_event *event,
 
 	if (PRINT_FIELD(SYM)) {
 		printf(" ");
-		symbol__print_symname(al.sym);
+		if (PRINT_FIELD(OFFSET))
+			symbol__print_symname_offs(al.sym, &al);
+		else
+			symbol__print_symname(al.sym);
 	}
 
 	if (PRINT_FIELD(DSO)) {
@@ -382,7 +392,8 @@ static void process_event(union perf_event *event __unused,
 		else
 			printf("\n");
 		perf_session__print_ip(event, sample, session,
-					      PRINT_FIELD(SYM), PRINT_FIELD(DSO));
+				       PRINT_FIELD(SYM), PRINT_FIELD(DSO),
+				       PRINT_FIELD(OFFSET));
 	}
 
 	printf("\n");
@@ -1078,7 +1089,10 @@ 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,addr",
+		     "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,offs",
 		     parse_output_fields),
 	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
 
tools/perf/util/session.c +5 -2
index 730fcd2..51d0a28 100644
@@ -1217,7 +1217,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 void perf_session__print_ip(union perf_event *event,
 			    struct perf_sample *sample,
 			    struct perf_session *session,
-			    int print_sym, int print_dso)
+			    int print_sym, int print_dso, int print_offset)
 {
 	struct addr_location al;
 	struct callchain_cursor *cursor = &session->callchain_cursor;
@@ -1264,7 +1264,10 @@ void perf_session__print_ip(union perf_event *event,
 		printf("%16" PRIx64, sample->ip);
 		if (print_sym) {
 			printf(" ");
-			symbol__print_symname(al.sym);
+			if (print_offset)
+				symbol__print_symname_offs(al.sym, &al);
+			else
+				symbol__print_symname(al.sym);
 		}
 
 		if (print_dso) {
tools/perf/util/session.h +2 -1
index 170601e..2689017 100644
@@ -171,7 +171,8 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 void perf_session__print_ip(union perf_event *event,
 				 struct perf_sample *sample,
 				 struct perf_session *session,
-				 int print_sym, int print_dso);
+				 int print_sym, int print_dso,
+				 int print_offset);
 
 int perf_session__cpu_bitmap(struct perf_session *session,
 			     const char *cpu_list, unsigned long *cpu_bitmap);
tools/perf/util/symbol.c +15 -7
index aa37485..28e14be 100644
@@ -175,16 +175,24 @@ static size_t symbol__fprintf(struct symbol *sym, FILE *fp)
 		       sym->name);
 }
 
-void symbol__print_symname(const struct symbol *sym)
+void symbol__print_symname_offs(const struct symbol *sym,
+				const struct addr_location *al)
 {
-	const char *symname;
+	unsigned long offset;
 
-	if (sym && sym->name)
-		symname = sym->name;
-	else
-		symname = "[unknown]";
+	if (sym && sym->name) {
+		printf("%s", sym->name);
+		if (al) {
+			offset = al->addr - sym->start;
+			printf("+0x%lx", offset);
+		}
+	} else
+		printf("[unknown]");
+}
 
-	printf("%s", symname);
+void symbol__print_symname(const struct symbol *sym)
+{
+	symbol__print_symname_offs(sym, NULL);
 }
 
 void dso__set_long_name(struct dso *dso, char *name)
tools/perf/util/symbol.h +0 -0
index 1ec17b4..554b2fe 100644

tools/perf/util/symbol.h void machines__destroy_guest_kernel_maps(struct rb_root *machines); · line 245

Quoted 8 lines
tools/perf/util/symbol.h +2 -0
@@ -238,6 +238,8 @@ void machines__destroy_guest_kernel_maps(struct rb_root *machines);
 
 int symbol__init(void);
 void symbol__exit(void);
+void symbol__print_symname_offs(const struct symbol *sym,
+				const struct addr_location *al);
 void symbol__print_symname(const struct symbol *sym);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
 
#11 lore raw

PATCH v3 5/5 perf script: add option resolving vmlinux path

In reply to Akihiro Nagai

Add the option get the path of [kernel.kallsyms]. Specify '--show-kernel-path' option to use this function. This patch enables other applications to use this output easily.

Without --show-kernel-path option

# perf script -f ip,dso
ffffffff81467612 irq_return ([kernel.kallsyms])
ffffffff81467612 irq_return ([kernel.kallsyms])
    7f24fc02a6b3 _start (/lib64/ld-2.14.so)
[snip]

With --show-kernel-path option

# perf script -f ip,dso --show-kernel-path
ffffffff81467612 irq_return (/lib/modules/3.0.0+/build/vmlinux)
ffffffff81467612 irq_return (/lib/modules/3.0.0+/build/vmlinux)
    7f24fc02a6b3 _start (/lib64/ld-2.14.so)
[snip]
Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc David Ahern <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---

 tools/perf/Documentation/perf-script.txt |    3 +++
 tools/perf/builtin-script.c              |    2 ++
 tools/perf/util/map.c                    |    9 ++++++---
 tools/perf/util/symbol.h                 |    1 +
 4 files changed, 12 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-script.txt +3 -0
index ee4d477..5383671 100644
@@ -188,6 +188,9 @@ OPTIONS
 	CPUs are specified with -: 0-2. Default is to report samples on all
 	CPUs.
 
+--show-kernel-path::
+	Try to resolve the path of [kernel.kallsyms]
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-script-perl[1],
tools/perf/builtin-script.c +2 -0
index 78797b3..ba5d3bb 100644
@@ -1095,6 +1095,8 @@ static const struct option options[] = {
 		     "addr,offs",
 		     parse_output_fields),
 	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
+	OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
+		    "Show the path of [kernel.kallsyms]"),
 
 	OPT_END()
 };
tools/perf/util/map.c +6 -3
index 530a5ea..6ba4909 100644
@@ -204,9 +204,12 @@ void map__print_dsoname(struct map *self)
 {
 	const char *dsoname;
 
-	if (self && self->dso && self->dso->name)
-		dsoname = self->dso->name;
-	else
+	if (self && self->dso && (self->dso->name || self->dso->long_name)) {
+		if (symbol_conf.show_kernel_path && self->dso->long_name)
+			dsoname = self->dso->long_name;
+		else if (self->dso->name)
+			dsoname = self->dso->name;
+	} else
 		dsoname = "[unknown]";
 
 	printf("%s", dsoname);
tools/perf/util/symbol.h +1 -0
index 554b2fe..3a63c92 100644
@@ -69,6 +69,7 @@ struct strlist;
 struct symbol_conf {
 	unsigned short	priv_size;
 	bool		try_vmlinux_path,
+			show_kernel_path,
 			use_modules,
 			sort_by_name,
 			show_nr_samples,
Acked-by on v3 5/5
#12 lore raw

Re: [PATCH -tip v3 5/5] perf script: add option resolving vmlinux path

Quoted 89 lines · Akihiro Nagai

Add the option get the path of [kernel.kallsyms]. Specify '--show-kernel-path' option to use this function. This patch enables other applications to use this output easily.

Without --show-kernel-path option

# perf script -f ip,dso
ffffffff81467612 irq_return ([kernel.kallsyms])
ffffffff81467612 irq_return ([kernel.kallsyms])
    7f24fc02a6b3 _start (/lib64/ld-2.14.so)
[snip]

With --show-kernel-path option

# perf script -f ip,dso --show-kernel-path
ffffffff81467612 irq_return (/lib/modules/3.0.0+/build/vmlinux)
ffffffff81467612 irq_return (/lib/modules/3.0.0+/build/vmlinux)
    7f24fc02a6b3 _start (/lib64/ld-2.14.so)
[snip]
Cc Peter Zijlstra <[email protected]>
Cc Frederic Weisbecker <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc David Ahern <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---

 tools/perf/Documentation/perf-script.txt |    3 +++
 tools/perf/builtin-script.c              |    2 ++
 tools/perf/util/map.c                    |    9 ++++++---
 tools/perf/util/symbol.h                 |    1 +
 4 files changed, 12 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-script.txt +3 -0
index ee4d477..5383671 100644
@@ -188,6 +188,9 @@ OPTIONS
 	CPUs are specified with -: 0-2. Default is to report samples on all
 	CPUs.
 
+--show-kernel-path::
+	Try to resolve the path of [kernel.kallsyms]
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-script-perl[1],
tools/perf/builtin-script.c +2 -0
index 78797b3..ba5d3bb 100644
@@ -1095,6 +1095,8 @@ static const struct option options[] = {
 		     "addr,offs",
 		     parse_output_fields),
 	OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
+	OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
+		    "Show the path of [kernel.kallsyms]"),
 
 	OPT_END()
 };
tools/perf/util/map.c +6 -3
index 530a5ea..6ba4909 100644
@@ -204,9 +204,12 @@ void map__print_dsoname(struct map *self)
 {
 	const char *dsoname;
 
-	if (self && self->dso && self->dso->name)
-		dsoname = self->dso->name;
-	else
+	if (self && self->dso && (self->dso->name || self->dso->long_name)) {
+		if (symbol_conf.show_kernel_path && self->dso->long_name)
+			dsoname = self->dso->long_name;
+		else if (self->dso->name)
+			dsoname = self->dso->name;
+	} else
 		dsoname = "[unknown]";
 
 	printf("%s", dsoname);
tools/perf/util/symbol.h +0 -0
index 554b2fe..3a63c92 100644

tools/perf/util/symbol.h struct strlist; · line 75

Quoted 7 lines
tools/perf/util/symbol.h +1 -0
@@ -69,6 +69,7 @@ struct strlist;
 struct symbol_conf {
 	unsigned short	priv_size;
 	bool		try_vmlinux_path,
+			show_kernel_path,
 			use_modules,
 			sort_by_name,
 			show_nr_samples,