linux-stable/tools
Leo Yan 897dd75c10 perf symbol: Correct address for bss symbols
[ Upstream commit 2d86612aac ]

When using 'perf mem' and 'perf c2c', an issue is observed that tool
reports the wrong offset for global data symbols.  This is a common
issue on both x86 and Arm64 platforms.

Let's see an example, for a test program, below is the disassembly for
its .bss section which is dumped with objdump:

  ...

  Disassembly of section .bss:

  0000000000004040 <completed.0>:
  	...

  0000000000004080 <buf1>:
  	...

  00000000000040c0 <buf2>:
  	...

  0000000000004100 <thread>:
  	...

First we used 'perf mem record' to run the test program and then used
'perf --debug verbose=4 mem report' to observe what's the symbol info
for 'buf1' and 'buf2' structures.

  # ./perf mem record -e ldlat-loads,ldlat-stores -- false_sharing.exe 8
  # ./perf --debug verbose=4 mem report
    ...
    dso__load_sym_internal: adjusting symbol: st_value: 0x40c0 sh_addr: 0x4040 sh_offset: 0x3028
    symbol__new: buf2 0x30a8-0x30e8
    ...
    dso__load_sym_internal: adjusting symbol: st_value: 0x4080 sh_addr: 0x4040 sh_offset: 0x3028
    symbol__new: buf1 0x3068-0x30a8
    ...

The perf tool relies on libelf to parse symbols, in executable and
shared object files, 'st_value' holds a virtual address; 'sh_addr' is
the address at which section's first byte should reside in memory, and
'sh_offset' is the byte offset from the beginning of the file to the
first byte in the section.  The perf tool uses below formula to convert
a symbol's memory address to a file address:

  file_address = st_value - sh_addr + sh_offset
                    ^
                    ` Memory address

We can see the final adjusted address ranges for buf1 and buf2 are
[0x30a8-0x30e8) and [0x3068-0x30a8) respectively, apparently this is
incorrect, in the code, the structure for 'buf1' and 'buf2' specifies
compiler attribute with 64-byte alignment.

The problem happens for 'sh_offset', libelf returns it as 0x3028 which
is not 64-byte aligned, combining with disassembly, it's likely libelf
doesn't respect the alignment for .bss section, therefore, it doesn't
return the aligned value for 'sh_offset'.

Suggested by Fangrui Song, ELF file contains program header which
contains PT_LOAD segments, the fields p_vaddr and p_offset in PT_LOAD
segments contain the execution info.  A better choice for converting
memory address to file address is using the formula:

  file_address = st_value - p_vaddr + p_offset

This patch introduces elf_read_program_header() which returns the
program header based on the passed 'st_value', then it uses the formula
above to calculate the symbol file address; and the debugging log is
updated respectively.

After applying the change:

  # ./perf --debug verbose=4 mem report
    ...
    dso__load_sym_internal: adjusting symbol: st_value: 0x40c0 p_vaddr: 0x3d28 p_offset: 0x2d28
    symbol__new: buf2 0x30c0-0x3100
    ...
    dso__load_sym_internal: adjusting symbol: st_value: 0x4080 p_vaddr: 0x3d28 p_offset: 0x2d28
    symbol__new: buf1 0x3080-0x30c0
    ...

Fixes: f17e04afaf ("perf report: Fix ELF symbol parsing")
Reported-by: Chang Rui <changruinj@gmail.com>
Suggested-by: Fangrui Song <maskray@google.com>
Signed-off-by: Leo Yan <leo.yan@linaro.org>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220724060013.171050-2-leo.yan@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2022-08-11 12:48:40 +02:00
..
accounting tools/accounting/getdelays.c: fix netlink attribute length 2020-04-13 10:45:10 +02:00
arch x86/speculation: Rename RETPOLINE_AMD to RETPOLINE_LFENCE 2022-03-11 10:15:11 +01:00
bpf bpftool: Check malloc return value in mount_bpffs_for_pin 2021-07-28 11:13:48 +02:00
build tools build: Use $(shell ) instead of `` to get embedded libperl's ccopts 2022-04-15 14:15:06 +02:00
cgroup
firewire
gpio tools: gpio-hammer: Avoid potential overflow in main 2020-10-01 13:14:39 +02:00
hv Tools: hv: kvp: eliminate 'may be used uninitialized' warning 2019-09-10 10:33:50 +01:00
iio iio: iio-utils: Fix possible incorrect mask calculation 2019-07-31 07:27:02 +02:00
include bpf: Fix comment for helper bpf_current_task_under_cgroup() 2022-04-15 14:14:59 +02:00
kvm/kvm_stat tools/kvm_stat: Fix kvm_exit filter name 2020-02-11 04:34:08 -08:00
laptop
leds
lib libtraceevent: Fix build with binutils 2.35 2022-06-06 08:24:21 +02:00
memory-model
nfsd
objtool objtool: Don't fail on missing symbol table 2021-02-07 14:48:38 +01:00
pci tools: PCI: Fix broken pcitest compilation 2019-11-24 08:21:08 +01:00
pcmcia
perf perf symbol: Correct address for bss symbols 2022-08-11 12:48:40 +02:00
power tools: Factor HOSTCC, HOSTLD, HOSTAR definitions 2021-01-30 13:32:13 +01:00
scripts tools: Factor HOSTCC, HOSTLD, HOSTAR definitions 2021-01-30 13:32:13 +01:00
spi
testing selftests: forwarding: fix error message in learning_test 2022-07-12 16:29:03 +02:00
thermal/tmon tools/thermal/tmon: Add cross compiling support 2021-09-22 11:47:59 +02:00
time
usb usb: testusb: Fix for showing the connection speed 2021-10-09 14:11:03 +02:00
virtio virtio: fix test build after uio.h change 2019-01-13 09:51:03 +01:00
vm tools/vm/page-types: remove dependency on opt_file for idle page tracking 2021-10-09 14:11:03 +02:00
wmi
Makefile