Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf script: Show correct offsets for DWARF-based unwinding

When perf/data is recorded with the dwarf call-graph option, the
callchain shown by 'perf script' still shows the binary offsets of the
userspace symbols instead of their virtual addresses. Since the symbol
offset calculation is based on using virtual address as the ip, we see
incorrect offsets as well.

The use of virtual addresses affects the ability to find out the
line number in the corresponding source file to which an address
maps to as described in commit 67540759151a ("perf unwind: Use
addr_location::addr instead of ip for entries").

This has also been addressed by temporarily converting the virtual
address to the correponding binary offset so that it can be mapped
to the source line number correctly.

This is a follow-up for commit 19610184693c ("perf script: Show
virtual addresses instead of offsets").

This can be verified on a powerpc64le system running Fedora 27 as
shown below:

# perf probe -x /usr/lib64/libc-2.26.so -a inet_pton
# perf record -e probe_libc:inet_pton --call-graph=dwarf ping -6 -c 1 ::1

Before:

# perf report --stdio --no-children -s sym,srcline -g address

# Samples: 1 of event 'probe_libc:inet_pton'
# Event count (approx.): 1
#
# Overhead Symbol Source:Line
# ........ .................... ...........
#
100.00% [.] __GI___inet_pton inet_pton.c
|
---gaih_inet getaddrinfo.c:537 (inlined)
__GI_getaddrinfo getaddrinfo.c:2304 (inlined)
main ping.c:519
generic_start_main libc-start.c:308 (inlined)
__libc_start_main libc-start.c:102
...

# perf script -F comm,ip,sym,symoff,srcline,dso

ping
15af28 __GI___inet_pton+0xffff000099160008 (/usr/lib64/libc-2.26.so)
libc-2.26.so[ffff80004ca0af28]
10fa53 gaih_inet+0xffff000099160f43
libc-2.26.so[ffff80004c9bfa53] (inlined)
1105b3 __GI_getaddrinfo+0xffff000099160163
libc-2.26.so[ffff80004c9c05b3] (inlined)
2d6f main+0xfffffffd9f1003df (/usr/bin/ping)
ping[fffffffecf882d6f]
2369f generic_start_main+0xffff00009916013f
libc-2.26.so[ffff80004c8d369f] (inlined)
23897 __libc_start_main+0xffff0000991600b7 (/usr/lib64/libc-2.26.so)
libc-2.26.so[ffff80004c8d3897]

After:

# perf report --stdio --no-children -s sym,srcline -g address

# Samples: 1 of event 'probe_libc:inet_pton'
# Event count (approx.): 1
#
# Overhead Symbol Source:Line
# ........ .................... ...........
#
100.00% [.] __GI___inet_pton inet_pton.c
|
---gaih_inet.constprop.7 getaddrinfo.c:537
getaddrinfo getaddrinfo.c:2304
main ping.c:519
generic_start_main.isra.0 libc-start.c:308
__libc_start_main libc-start.c:102
...

# perf script -F comm,ip,sym,symoff,srcline,dso

ping
7fffb38aaf28 __GI___inet_pton+0x8 (/usr/lib64/libc-2.26.so)
inet_pton.c:68
7fffb385fa53 gaih_inet.constprop.7+0xf43 (/usr/lib64/libc-2.26.so)
getaddrinfo.c:537
7fffb38605b3 getaddrinfo+0x163 (/usr/lib64/libc-2.26.so)
getaddrinfo.c:2304
130782d6f main+0x3df (/usr/bin/ping)
ping.c:519
7fffb377369f generic_start_main.isra.0+0x13f (/usr/lib64/libc-2.26.so)
libc-start.c:308
7fffb3773897 __libc_start_main+0xb7 (/usr/lib64/libc-2.26.so)
libc-start.c:102

Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Milian Wolff <milian.wolff@kdab.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Fixes: 67540759151a ("perf unwind: Use addr_location::addr instead of ip for entries")
Link: http://lkml.kernel.org/r/20180703120555.32971-1-sandipan@linux.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Sandipan Das and committed by
Arnaldo Carvalho de Melo
2a9d5050 a7f660d6

+10 -3
+8 -1
tools/perf/util/machine.c
··· 2272 2272 { 2273 2273 struct callchain_cursor *cursor = arg; 2274 2274 const char *srcline = NULL; 2275 + u64 addr; 2275 2276 2276 2277 if (symbol_conf.hide_unresolved && entry->sym == NULL) 2277 2278 return 0; ··· 2280 2279 if (append_inlines(cursor, entry->map, entry->sym, entry->ip) == 0) 2281 2280 return 0; 2282 2281 2283 - srcline = callchain_srcline(entry->map, entry->sym, entry->ip); 2282 + /* 2283 + * Convert entry->ip from a virtual address to an offset in 2284 + * its corresponding binary. 2285 + */ 2286 + addr = map__map_ip(entry->map, entry->ip); 2287 + 2288 + srcline = callchain_srcline(entry->map, entry->sym, addr); 2284 2289 return callchain_cursor_append(cursor, entry->ip, 2285 2290 entry->map, entry->sym, 2286 2291 false, NULL, 0, 0, 0, srcline);
+1 -1
tools/perf/util/unwind-libdw.c
··· 77 77 if (__report_module(&al, ip, ui)) 78 78 return -1; 79 79 80 - e->ip = al.addr; 80 + e->ip = ip; 81 81 e->map = al.map; 82 82 e->sym = al.sym; 83 83
+1 -1
tools/perf/util/unwind-libunwind-local.c
··· 575 575 struct addr_location al; 576 576 577 577 e.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); 578 - e.ip = al.addr; 578 + e.ip = ip; 579 579 e.map = al.map; 580 580 581 581 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",