kernel_optimize_test/tools
Leo Yan 3ec42508a6 perf symbol: Correct address for bss symbols
[ Upstream commit 2d86612aacb7805f72873691a2644d7279ed0630 ]

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-03 12:00:49 +02:00
..
accounting
arch tools arch: Update arch/x86/lib/mem{cpy,set}_64.S copies used in 'perf bench mem memcpy' - again 2022-07-25 11:26:56 +02:00
bootconfig tools/bootconfig: Fix tracing_on option checking in ftrace2bconf.sh 2021-09-26 14:08:59 +02:00
bpf tools/resolve_btfids: Do not print any commands when building silently 2022-02-08 18:30:39 +01:00
build tools build: Use $(shell ) instead of `` to get embedded libperl's ccopts 2022-04-13 21:01:10 +02:00
cgroup tools/cgroup/slabinfo.py: updated to work on current kernel 2021-05-07 11:04:31 +02:00
debugging
edid
firewire
firmware
gpio tools: gpio: fix %llu warning in gpio-watch.c 2021-01-27 11:55:20 +01:00
hv tools: hv: change http to https in hv_kvp_daemon.c 2020-07-06 10:46:23 +00:00
iio iio: add IIO_MOD_O2 modifier 2020-08-22 10:53:12 +01:00
include tools headers: Remove broken definition of __LITTLE_ENDIAN 2022-07-25 11:26:56 +02:00
io_uring tools/io_uring: fix compile breakage 2020-09-21 07:50:58 -06:00
kvm/kvm_stat tools/kvm_stat: Add restart delay 2021-04-16 11:43:20 +02:00
laptop
leds
lib libbpf: Fix logic for finding matching program for CO-RE relocation 2022-06-09 10:21:03 +02:00
memory-model tools/memory-model: Expand the cheatsheet.txt notion of relaxed 2020-09-04 11:58:15 -07:00
objtool objtool: Fix elf_create_undef_symbol() endianness 2022-07-25 11:26:56 +02:00
pci
pcmcia
perf perf symbol: Correct address for bss symbols 2022-08-03 12:00:49 +02:00
power tools/power turbostat: fix ICX DRAM power numbers 2022-06-09 10:20:51 +02:00
scripts tools: Allow proper CC/CXX/... override with LLVM=1 in Makefile.include 2021-07-31 08:16:10 +02:00
spi
testing selftests: forwarding: fix error message in learning_test 2022-07-12 16:32:22 +02:00
thermal/tmon tools/thermal/tmon: Add cross compiling support 2021-09-18 13:40:07 +02:00
time
usb usb: testusb: Fix for showing the connection speed 2021-10-09 14:40:56 +02:00
virtio tools/virtio: compile with -pthread 2022-05-25 09:17:53 +02:00
vm tools/vm/page-types: remove dependency on opt_file for idle page tracking 2021-10-09 14:40:57 +02:00
wmi
Makefile bpf: Compile resolve_btfids tool at kernel compilation start 2020-07-13 10:42:02 -07:00