kernel_optimize_test/tools/perf
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
..
arch perf symbol: Remove arch__symbols__fixup_end() 2022-05-09 09:05:09 +02:00
bench perf bench numa: Address compiler error on s390 2022-05-25 09:18:00 +02:00
Documentation perf c2c: Update documentation for metrics reorganization 2020-10-15 12:02:12 -03:00
examples/bpf
include/bpf
jvmti
pmu-events perf jevents: Fix event syntax error caused by ExtSel 2022-06-09 10:21:21 +02:00
python tweewide: Fix most Shebang lines 2021-05-22 11:40:55 +02:00
scripts perf scripts python: exported-sql-viewer.py: Fix warning display 2021-06-03 09:00:28 +02:00
tests perf tests: Remove bash construct from record+zstd_comp_decomp.sh 2021-11-26 10:39:13 +01:00
trace perf beauty: Update copy of linux/socket.h with the kernel sources 2021-06-23 14:42:54 +02:00
ui perf hist: Fix memory leak of a perf_hpp_fmt 2021-12-08 09:03:20 +01:00
util perf symbol: Correct address for bss symbols 2022-08-03 12:00:49 +02:00
.gitignore
Build
builtin-annotate.c
builtin-bench.c perf bench: Add build-id injection benchmark 2020-10-13 10:59:42 -03:00
builtin-buildid-cache.c perf tools: Pass build_id object to build_id__sprintf() 2020-10-14 08:46:22 -03:00
builtin-buildid-list.c
builtin-c2c.c perf c2c: Fix sorting in percent_rmt_hitm_cmp() 2022-06-14 18:32:37 +02:00
builtin-config.c
builtin-data.c
builtin-diff.c perf diff: Fix error return value in __cmd_diff() 2020-11-27 14:21:23 -03:00
builtin-evlist.c
builtin-ftrace.c perf ftrace: Fix access to pid in array when setting a pid filter 2021-05-07 11:04:31 +02:00
builtin-help.c
builtin-inject.c perf inject: Fix itrace space allowed for new attributes 2021-12-17 10:14:41 +01:00
builtin-kallsyms.c
builtin-kmem.c
builtin-kvm.c
builtin-list.c
builtin-lock.c perf lock: Don't free "lock_seq_stat" if read_count isn't zero 2020-11-12 17:55:41 -03:00
builtin-mem.c
builtin-probe.c
builtin-record.c perf record: Fix continue profiling after draining the buffer 2021-03-04 11:38:09 +01:00
builtin-report.c perf report: Set PERF_SAMPLE_DATA_SRC bit for Arm SPE event 2022-04-27 13:53:56 +02:00
builtin-sched.c perf sched: Fix record failure when CONFIG_SCHEDSTATS is not set 2021-07-28 14:35:36 +02:00
builtin-script.c perf script: Fix CPU filtering of a script's switch events 2022-01-05 12:40:34 +01:00
builtin-stat.c
builtin-timechart.c
builtin-top.c
builtin-trace.c perf trace: Fix segfault when trying to trace events by cgroup 2020-11-03 08:31:03 -03:00
builtin-version.c
builtin.h
check-headers.sh x86/insn: Add a __ignore_sync_check__ marker 2022-07-25 11:26:11 +02:00
command-list.txt
CREDITS
design.txt
Makefile
Makefile.config perf tools: Use Python devtools for version autodetection rather than runtime 2022-06-09 10:21:05 +02:00
Makefile.perf perf build: Fix ccache usage in $(CC) when generating arch errno table 2021-03-17 17:06:16 +01:00
MANIFEST
perf-archive.sh
perf-completion.sh
perf-read-vdso.c
perf-sys.h
perf-with-kcore.sh
perf.c perf tools: Fix perf's libperf_print callback 2022-04-13 21:01:07 +02:00
perf.h