perf/core fixes and improvements
Subsystems (4)
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling, this is on top of my previous pull
request, that is outstanding, perf-core-for-mingo-5.1-20190311.
Most of the patches plug exit path reference count and memory
leaks, some simple new features and then a late new one that has been thru 9 versions before being finally merged, the annotation of BPF programs, using the BTF information to have even the original source code intermixed with the JITed code.
Best Regards,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit dfcbc2f2994b8a3af3605a26dc29c07ad7378bf4:
tools lib bpf: Fix the build by adding a missing stdarg.h include (2019-03-11 17:14:31 -0300)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-5.1-20190321
for you to fetch changes up to f8dfeae009effc0b6dac2741cf8d7cbb91edb982:
perf bpf: Show more BPF program info in print_bpf_prog_info() (2019-03-21 11:27:04 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
BPF:
Song Liu:
- Add support for annotating BPF programs, using the PERF_RECORD_BPF_EVENT and PERF_RECORD_KSYMBOL recently added to the kernel and plugging binutils's libopcodes disassembly of BPF programs with the existing annotation interfaces in 'perf annotate', 'perf report' and 'perf top' various output formats (--stdio, --stdio2, --tui).
perf list:
Andi Kleen:
- Filter metrics when using substring search.
perf record:
Andi Kleen:
- Allow to limit number of reported perf.data files
- Clarify help for --switch-output.
perf report:
Andi Kleen
- Indicate JITed code better.
- Show all sort keys in help output.
perf script:
Andi Kleen:
- Support relative time.
perf stat:
Andi Kleen:
- Improve scaling.
General:
Changbin Du:
- Fix some mostly error path memory and reference count leaks found using gcc's ASan and UBSan.
Vendor events:
Mamatha Inamdar:
- Remove P8 HW events which are not supported.
----------------------------------------------------------------
Andi Kleen (8):
perf list: Filter metrics too
perf record: Allow to limit number of reported perf.data files perf record: Clarify help for --switch-output
perf report: Show all sort keys in help output
perf report: Indicate JITed code better in report perf script: Support relative time
perf stat: Fix --no-scale
perf stat: Improve scaling
Arnaldo Carvalho de Melo (1):
perf evsel: Free evsel->counts in perf_evsel__exit()
Changbin Du (15):
perf tools: Add doc about how to build perf with Asan and UBSan
perf list: Don't forget to drop the reference to the allocated thread_map perf tools: Fix errors under optimization level '-Og'
perf config: Fix an error in the config template documentation
perf config: Fix a memory leak in collect_config()
perf build-id: Fix memory leak in print_sdt_events()
perf top: Delete the evlist before perf_session, fixing heap-use-after-free issue perf top: Fix error handling in cmd_top()
perf hist: Add missing map__put() in error case
perf map: Remove map from 'names' tree in __maps__remove()
perf maps: Purge all maps from the 'names' tree
perf top: Fix global-buffer-overflow issue
perf tests: Fix a memory leak of cpu_map object in the openat_syscall_event_on_all_cpus test perf tests: Fix memory leak by expr__find_other() in test__expr()
perf tests: Fix a memory leak in test__perf_evsel__tp_sched_test()
Mamatha Inamdar (1):
perf vendor events: Remove P8 HW events which are not supported
Song Liu (19):
perf record: Replace option --bpf-event with --no-bpf-event
tools lib bpf: Introduce bpf_program__get_prog_info_linear()
bpftool: use bpf_program__get_prog_info_linear() in prog.c:do_dump()
perf bpf: Synthesize bpf events with bpf_program__get_prog_info_linear() perf bpf: Make synthesize_bpf_events() receive perf_session pointer instead of perf_tool perf bpf: Save bpf_prog_info in a rbtree in perf_env
perf bpf: Save bpf_prog_info information as headers to perf.data
perf bpf: Save BTF in a rbtree in perf_env
perf bpf: Save BTF information as headers to perf.data
perf top: Add option --no-bpf-event
perf feature detection: Add -lopcodes to feature-libbfd
perf symbols: Introduce DSO_BINARY_TYPE__BPF_PROG_INFO
perf bpf: Process PERF_BPF_EVENT_PROG_LOAD for annotation
perf build: Check what binutils's 'disassembler()' signature to use
perf annotate: Enable annotation of BPF programs
perf evlist: Introduce side band thread
perf tools: Save bpf_prog_info and BTF of new BPF programs
perf bpf: Extract logic to create program names from perf_event__synthesize_one_bpf_prog() perf bpf: Show more BPF program info in print_bpf_prog_info()
tools/bpf/bpftool/prog.c | 266 ++------- tools/build/Makefile.feature | 6 +- tools/build/feature/test-all.c | 5 + tools/lib/bpf/libbpf.c | 253 ++++++++- tools/lib/bpf/libbpf.h | 63 +++ tools/lib/bpf/libbpf.map | 3 + tools/perf/Documentation/Build.txt | 24 + tools/perf/Documentation/perf-config.txt | 2 +- tools/perf/Documentation/perf-record.txt | 4 + tools/perf/Documentation/perf-script.txt | 3 + tools/perf/Documentation/perf-stat.txt | 5 +- tools/perf/Makefile.config | 15 +- tools/perf/bench/epoll-ctl.c | 2 +- tools/perf/bench/epoll-wait.c | 2 +- tools/perf/builtin-list.c | 2 +- tools/perf/builtin-record.c | 50 +- tools/perf/builtin-report.c | 5 +- tools/perf/builtin-script.c | 18 +- tools/perf/builtin-stat.c | 3 +- tools/perf/builtin-top.c | 62 ++- tools/perf/perf.c | 1 + tools/perf/perf.h | 2 +- .../perf/pmu-events/arch/powerpc/power8/other.json | 594 --------------------- tools/perf/tests/attr/test-record-C0 | 2 +- tools/perf/tests/attr/test-record-basic | 2 +- tools/perf/tests/attr/test-record-branch-any | 2 +- .../perf/tests/attr/test-record-branch-filter-any | 2 +- .../tests/attr/test-record-branch-filter-any_call | 2 +- .../tests/attr/test-record-branch-filter-any_ret | 2 +- tools/perf/tests/attr/test-record-branch-filter-hv | 2 +- .../tests/attr/test-record-branch-filter-ind_call | 2 +- tools/perf/tests/attr/test-record-branch-filter-k | 2 +- tools/perf/tests/attr/test-record-branch-filter-u | 2 +- tools/perf/tests/attr/test-record-count | 2 +- tools/perf/tests/attr/test-record-data | 2 +- tools/perf/tests/attr/test-record-freq | 2 +- tools/perf/tests/attr/test-record-graph-default | 2 +- tools/perf/tests/attr/test-record-graph-dwarf | 2 +- tools/perf/tests/attr/test-record-graph-fp | 2 +- tools/perf/tests/attr/test-record-group | 2 +- tools/perf/tests/attr/test-record-group-sampling | 2 +- tools/perf/tests/attr/test-record-group1 | 2 +- tools/perf/tests/attr/test-record-no-buffering | 2 +- tools/perf/tests/attr/test-record-no-inherit | 2 +- tools/perf/tests/attr/test-record-no-samples | 2 +- tools/perf/tests/attr/test-record-period | 2 +- tools/perf/tests/attr/test-record-raw | 2 +- tools/perf/tests/backward-ring-buffer.c | 2 +- tools/perf/tests/evsel-tp-sched.c | 1 + tools/perf/tests/expr.c | 5 +- tools/perf/tests/openat-syscall-all-cpus.c | 4 +- tools/perf/util/annotate.c | 163 +++++- tools/perf/util/annotate.h | 1 + tools/perf/util/bpf-event.c | 425 +++++++++++---- tools/perf/util/bpf-event.h | 42 +- tools/perf/util/build-id.c | 1 + tools/perf/util/config.c | 3 +- tools/perf/util/data.c | 11 +- tools/perf/util/data.h | 2 +- tools/perf/util/dso.c | 43 +- tools/perf/util/dso.h | 8 + tools/perf/util/env.c | 155 ++++++ tools/perf/util/env.h | 24 + tools/perf/util/evlist.c | 119 +++++ tools/perf/util/evlist.h | 12 + tools/perf/util/evsel.c | 8 +- tools/perf/util/evsel.h | 6 + tools/perf/util/header.c | 253 ++++++++- tools/perf/util/header.h | 2 + tools/perf/util/hist.c | 4 +- tools/perf/util/map.c | 18 + tools/perf/util/ordered-events.c | 2 + tools/perf/util/parse-events.c | 2 + tools/perf/util/session.c | 1 + tools/perf/util/sort.c | 52 ++ tools/perf/util/sort.h | 2 + tools/perf/util/stat.c | 12 +- tools/perf/util/symbol.c | 1 + 78 files changed, 1794 insertions(+), 1028 deletions(-)
Test results:
The first ones are container based builds of tools/perf with and without libelf support. Where clang is available, it is also used to build perf with/without libelf, and building with LIBCLANGLLVM=1 (built-in clang) with gcc and clang when clang and its devel libraries are installed.
The objtool and samples/bpf/ builds are disabled now that I'm switching from using the sources in a local volume to fetching them from a http server to build it inside the container, to make it easier to build in a container cluster. Those will come back later.
Several are cross builds, the ones with -x-ARCH and the android one, and those may not have all the features built, due to lack of multi-arch devel packages, available and being used so far on just a few, like debian:experimental-x-{arm64,mipsel}.
The 'perf test' one will perform a variety of tests exercising tools/perf/util/, tools/lib/{bpf,traceevent,etc}, as well as run perf commands with a variety of command line event specifications to then intercept the sys_perf_event syscall to check that the perf_event_attr fields are set up as expected, among a variety of other unit tests.
Then there is the 'make -C tools/perf build-test' ones, that build tools/perf/ with a variety of feature sets, exercising the build with an incomplete set of features as well as with a complete one. It is planned to have it run on each of the containers mentioned above, using some container orchestration infrastructure. Get in contact if interested in helping having this in place.
$ export PERF_TARBALL=http://192.168.124.1/perf/perf-5.0.0.tar.xz $ time dm 1 alpine:3.4 : Ok gcc (Alpine 5.3.0) 5.3.0 2 alpine:3.5 : Ok gcc (Alpine 6.2.1) 6.2.1 20160822 3 alpine:3.6 : Ok gcc (Alpine 6.3.0) 6.3.0 4 alpine:3.7 : Ok gcc (Alpine 6.4.0) 6.4.0 5 alpine:3.8 : Ok gcc (Alpine 6.4.0) 6.4.0 6 alpine:3.9 : Ok gcc (Alpine 8.2.0) 8.2.0 7 alpine:edge : Ok gcc (Alpine 8.3.0) 8.3.0 8 amazonlinux:1 : Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28) 9 amazonlinux:2 : Ok gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5) 10 android-ndk:r12b-arm : Ok arm-linux-androideabi-gcc (GCC) 4.9.x 20150123 (prerelease) 11 android-ndk:r15c-arm : Ok arm-linux-androideabi-gcc (GCC) 4.9.x 20150123 (prerelease) 12 centos:5 : Ok gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-55) 13 centos:6 : Ok gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23) 14 centos:7 : Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36) 15 clearlinux:latest : Ok gcc (Clear Linux OS for Intel Architecture) 8.3.1 20190317 gcc-8-branch@269736 16 debian:7 : Ok gcc (Debian 4.7.2-5) 4.7.2 17 debian:8 : Ok gcc (Debian 4.9.2-10+deb8u2) 4.9.2 18 debian:9 : Ok gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516 19 debian:experimental : Ok gcc (Debian 8.3.0-2) 8.3.0 20 debian:experimental-x-arm64 : Ok aarch64-linux-gnu-gcc (Debian 8.3.0-2) 8.3.0 21 debian:experimental-x-mips : Ok mips-linux-gnu-gcc (Debian 8.3.0-2) 8.3.0 22 debian:experimental-x-mips64 : Ok mips64-linux-gnuabi64-gcc (Debian 8.3.0-2) 8.3.0 23 fedora:20 : Ok gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7) 24 fedora:22 : Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) 25 fedora:23 : Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) 26 fedora:24 : Ok gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1) 27 fedora:24-x-ARC-uClibc : Ok arc-linux-gcc (ARCompact ISA Linux uClibc toolchain 2017.09-rc2) 7.1.1 20170710 28 fedora:25 : Ok gcc (GCC) 6.4.1 20170727 (Red Hat 6.4.1-1) 29 fedora:26 : Ok gcc (GCC) 7.3.1 20180130 (Red Hat 7.3.1-2) 30 fedora:27 : Ok gcc (GCC) 7.3.1 20180712 (Red Hat 7.3.1-6) 31 fedora:28 : Ok gcc (GCC) 8.2.1 20181215 (Red Hat 8.2.1-6) 32 fedora:29 : Ok gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2) 33 fedora:30 : Ok gcc (GCC) 9.0.1 20190227 (Red Hat 9.0.1-0.8) 34 fedora:rawhide : Ok gcc (GCC) 9.0.1 20190227 (Red Hat 9.0.1-0.8) 35 gentoo-stage3-amd64:latest : Ok gcc (Gentoo 8.2.0-r6 p1.7) 8.2.0 36 mageia:5 : Ok gcc (GCC) 4.9.2 37 mageia:6 : Ok gcc (Mageia 5.5.0-1.mga6) 5.5.0 38 opensuse:15.1 : Ok gcc (SUSE Linux) 7.4.0 39 opensuse:42.3 : Ok gcc (SUSE Linux) 4.8.5 40 opensuse:tumbleweed : Ok gcc (SUSE Linux) 8.3.1 20190226 [gcc-8-branch revision 269204] 41 oraclelinux:6 : Ok gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-23.0.1) 42 oraclelinux:7 : Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36.0.1) 43 ubuntu:12.04.5 : Ok gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 44 ubuntu:14.04.4 : Ok gcc (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4 45 ubuntu:14.04.4-x-linaro-arm64 : Ok aarch64-linux-gnu-gcc (Linaro GCC 5.5-2017.10) 5.5.0 46 ubuntu:16.04 : Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609 47 ubuntu:16.04-x-arm : Ok arm-linux-gnueabihf-gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 48 ubuntu:16.04-x-arm64 : Ok aarch64-linux-gnu-gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 49 ubuntu:16.04-x-powerpc : Ok powerpc-linux-gnu-gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 50 ubuntu:16.04-x-powerpc64 : Ok powerpc64-linux-gnu-gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 51 ubuntu:16.04-x-powerpc64el : Ok powerpc64le-linux-gnu-gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 52 ubuntu:16.04-x-s390 : Ok s390x-linux-gnu-gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 53 ubuntu:17.10 : Ok gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0 54 ubuntu:18.04 : Ok gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 55 ubuntu:18.04-x-arm : Ok arm-linux-gnueabihf-gcc (Ubuntu/Linaro 7.3.0-27ubuntu1~18.04) 7.3.0 56 ubuntu:18.04-x-arm64 : Ok aarch64-linux-gnu-gcc (Ubuntu/Linaro 7.3.0-27ubuntu1~18.04) 7.3.0 57 ubuntu:18.04-x-m68k : Ok m68k-linux-gnu-gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 58 ubuntu:18.04-x-powerpc : Ok powerpc-linux-gnu-gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 59 ubuntu:18.04-x-powerpc64 : Ok powerpc64-linux-gnu-gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 60 ubuntu:18.04-x-powerpc64el : Ok powerpc64le-linux-gnu-gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 61 ubuntu:18.04-x-riscv64 : Ok riscv64-linux-gnu-gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 62 ubuntu:18.04-x-s390 : Ok s390x-linux-gnu-gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 63 ubuntu:18.04-x-sh4 : Ok sh4-linux-gnu-gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 64 ubuntu:18.04-x-sparc64 : Ok sparc64-linux-gnu-gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 65 ubuntu:18.10 : Ok gcc (Ubuntu 8.2.0-7ubuntu1) 8.2.0 66 ubuntu:19.04 : Ok gcc (Ubuntu 8.3.0-2ubuntu2) 8.3.0 67 ubuntu:19.04-x-alpha : Ok alpha-linux-gnu-gcc (Ubuntu 8.3.0-2ubuntu1) 8.3.0 68 ubuntu:19.04-x-arm64 : FAIL aarch64-linux-gnu-gcc (Ubuntu/Linaro 8.3.0-2ubuntu1) 8.3.0 69 ubuntu:19.04-x-hppa : Ok hppa-linux-gnu-gcc (Ubuntu 8.3.0-2ubuntu1) 8.3.0
The gcc got pdated on that ubuntu 19.04-x-arm64 container and caught this, that is already being addressed by Mathieu and Solomon Tan, the problem is not being introduced by this patchset.
LD /tmp/build/perf/util/scripting-engines/perf-in.o
util/cs-etm-decoder/cs-etm-decoder.c: In function 'cs_etm_decoder__buffer_range':
util/cs-etm-decoder/cs-etm-decoder.c:383:2: error: enumeration value 'OCSD_INSTR_WFI_WFE' not handled in switch [-Werror=switch-enum]
switch (elem->last_i_type) {
^~~~~~
CC /tmp/build/perf/util/intel-pt-decoder/intel-pt-insn-decoder.o # uname -a
Linux quaco 5.0.0+ #2 SMP Tue Mar 12 15:15:22 -03 2019 x86_64 x86_64 x86_64 GNU/Linux
# git log --oneline -1
f8dfeae009ef perf bpf: Show more BPF program info in print_bpf_prog_info()
# perf version --build-options
perf version 5.0.gf8dfea
dwarf: [ on ] # HAVE_DWARF_SUPPORT
dwarf_getlocations: [ on ] # HAVE_DWARF_GETLOCATIONS_SUPPORT
glibc: [ on ] # HAVE_GLIBC_SUPPORT
gtk2: [ on ] # HAVE_GTK2_SUPPORT
syscall_table: [ on ] # HAVE_SYSCALL_TABLE_SUPPORT
libbfd: [ on ] # HAVE_LIBBFD_SUPPORT
libelf: [ on ] # HAVE_LIBELF_SUPPORT
libnuma: [ on ] # HAVE_LIBNUMA_SUPPORT
numa_num_possible_cpus: [ on ] # HAVE_LIBNUMA_SUPPORT
libperl: [ on ] # HAVE_LIBPERL_SUPPORT
libpython: [ on ] # HAVE_LIBPYTHON_SUPPORT
libslang: [ on ] # HAVE_SLANG_SUPPORT
libcrypto: [ on ] # HAVE_LIBCRYPTO_SUPPORT
libunwind: [ on ] # HAVE_LIBUNWIND_SUPPORT
libdw-dwarf-unwind: [ on ] # HAVE_DWARF_SUPPORT
zlib: [ on ] # HAVE_ZLIB_SUPPORT
lzma: [ on ] # HAVE_LZMA_SUPPORT
get_cpuid: [ on ] # HAVE_AUXTRACE_SUPPORT
bpf: [ on ] # HAVE_LIBBPF_SUPPORT
# perf test
1: vmlinux symtab matches kallsyms : Ok
2: Detect openat syscall event : Ok
3: Detect openat syscall event on all cpus : Ok
4: Read samples using the mmap interface : Ok
5: Test data source output : Ok
6: Parse event definition strings : Ok
7: Simple expression parser : Ok
8: PERF_RECORD_* events & perf_sample fields : Ok
9: Parse perf pmu format : Ok
10: DSO data read : Ok
11: DSO data cache : Ok
12: DSO data reopen : Ok
13: Roundtrip evsel->name : Ok
14: Parse sched tracepoints fields : Ok
15: syscalls:sys_enter_openat event fields : Ok
16: Setup struct perf_event_attr : Ok
17: Match and link multiple hists : Ok
18: 'import perf' in python : Ok
19: Breakpoint overflow signal handler : Ok
20: Breakpoint overflow sampling : Ok
21: Breakpoint accounting : Ok
22: Watchpoint :
22.1: Read Only Watchpoint : Skip
22.2: Write Only Watchpoint : Ok
22.3: Read / Write Watchpoint : Ok
22.4: Modify Watchpoint : Ok
23: Number of exit events of a simple workload : Ok
24: Software clock events period values : Ok
25: Object code reading : Ok
26: Sample parsing : Ok
27: Use a dummy software event to keep tracking : Ok
28: Parse with no sample_id_all bit set : Ok
29: Filter hist entries : Ok
30: Lookup mmap thread : Ok
31: Share thread mg : Ok
32: Sort output of hist entries : Ok
33: Cumulate child hist entries : Ok
34: Track with sched_switch : Ok
35: Filter fds with revents mask in a fdarray : Ok
36: Add fd to a fdarray, making it autogrow : Ok
37: kmod_path__parse : Ok
38: Thread map : Ok
39: LLVM search and compile :
39.1: Basic BPF llvm compile : Ok
39.2: kbuild searching : Ok
39.3: Compile source for BPF prologue generation : Ok
39.4: Compile source for BPF relocation : Ok
40: Session topology : Ok
41: BPF filter :
41.1: Basic BPF filtering : Ok
41.2: BPF pinning : Ok
41.3: BPF prologue generation : Ok
41.4: BPF relocation checker : Ok
42: Synthesize thread map : Ok
43: Remove thread map : Ok
44: Synthesize cpu map : Ok
45: Synthesize stat config : Ok
46: Synthesize stat : Ok
47: Synthesize stat round : Ok
48: Synthesize attr update : Ok
49: Event times : Ok
50: Read backward ring buffer : Ok
51: Print cpu map : Ok
52: Probe SDT events : Ok
53: is_printable_array : Ok
54: Print bitmap : Ok
55: perf hooks : Ok
56: builtin clang support : Skip (not compiled in)
57: unit_number__scnprintf : Ok
58: mem2node : Ok
59: x86 rdpmc : Ok
60: Convert perf time to TSC : Ok
61: DWARF unwind : Ok
62: x86 instruction decoder - new instructions : Ok
63: x86 bp modify : Ok
64: probe libc's inet_pton & backtrace it with ping : Ok
65: Use vfs_getname probe to get syscall args filenames : Ok
66: Add vfs_getname probe to get syscall args filenames : Ok
67: Check open filename arg using perf trace + vfs_getname: Ok $ make -C tools/perf build-test
make: Entering directory '/home/acme/git/perf/tools/perf'
- tarpkg: ./tests/perf-targz-src-pkg .
make_no_libpython_O: make NO_LIBPYTHON=1
make_minimal_O: make NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1
make_util_pmu_bison_o_O: make util/pmu-bison.o
make_no_slang_O: make NO_SLANG=1
make_no_gtk2_O: make NO_GTK2=1
make_install_bin_O: make install-bin
make_install_prefix_slash_O: make install prefix=/tmp/krava/
make_doc_O: make doc
make_cscope_O: make cscope
make_help_O: make help
make_with_clangllvm_O: make LIBCLANGLLVM=1
make_no_backtrace_O: make NO_BACKTRACE=1
make_no_libdw_dwarf_unwind_O: make NO_LIBDW_DWARF_UNWIND=1
make_with_babeltrace_O: make LIBBABELTRACE=1
g make_perf_o_O: make perf.o
make_no_libbpf_O: make NO_LIBBPF=1
make_no_libaudit_O: make NO_LIBAUDIT=1
make_no_newt_O: make NO_NEWT=1
make_install_O: make install
make_no_libelf_O: make NO_LIBELF=1
make_no_libbionic_O: make NO_LIBBIONIC=1
make_tags_O: make tags
make_no_demangle_O: make NO_DEMANGLE=1
make_no_libperl_O: make NO_LIBPERL=1
make_no_ui_O: make NO_NEWT=1 NO_SLANG=1 NO_GTK2=1
make_util_map_o_O: make util/map.o
make_no_libnuma_O: make NO_LIBNUMA=1
make_install_prefix_O: make install prefix=/tmp/krava
make_pure_O: make
make_static_O: make LDFLAGS=-static
make_no_libunwind_O: make NO_LIBUNWIND=1
make_debug_O: make DEBUG=1
make_no_auxtrace_O: make NO_AUXTRACE=1
make_clean_all_O: make clean all
make_no_scripts_O: make NO_LIBPYTHON=1 NO_LIBPERL=1
OK
make: Leaving directory '/home/acme/git/perf/tools/perf'Arnaldo Carvalho de Melo
maintainerPATCH 1/44 perf list: Filter metrics too
From: Andi Kleen <[email protected]>
When a filter is specified on the command line, filter the metrics too.
Before:
% perf list foo
List of pre-defined events (to be used in -e):
Metric Groups:
DSB:
DSB_Coverage
[Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)]
... more metrics ...
After:
% perf list foo
List of pre-defined events (to be used in -e):
Metric Groups:
LPU-Reference: [email protected]
--- tools/perf/builtin-list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/builtin-list.c +1 -1
@@ -119,7 +119,7 @@ int cmd_list(int argc, const char **argv) details_flag);print_tracepoint_events (NULL , s, raw_dump);print_sdt_events (NULL , s, raw_dump); -metricgroup__print (true, true,NULL , raw_dump, details_flag); +metricgroup__print (true, true, s, raw_dump, details_flag);free (s); } }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 2/44 perf record: Allow to limit number of reported perf.data files
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
When doing long term recording and waiting for some event to snapshot on, we often only care about the last minute or so.
The --switch-output command line option supports rotating the perf.data file when the size exceeds a threshold. But the disk would still be filled with unnecessary old files.
Add a new option to only keep a number of rotated files, so that the disk space usage can be limited.
LPU-Reference: [email protected]
--- tools/perf/Documentation/perf-record.txt | 4 ++++ tools/perf/builtin-record.c | 30 +++++++++++++++++++++++- tools/perf/util/data.c | 11 ++++----- tools/perf/util/data.h | 2 +- 4 files changed, 39 insertions(+), 8 deletions(-)
tools/perf/Documentation/perf-record.txt +4 -0
@@ -495,6 +495,10 @@ overhead. You can still switch them on with: --switch-output --no-no-buildid --no-no-buildid-cache +--switch-max-files=N:: + +When rotating perf.data with --switch-output, only keep N files. + --dry-run:: Parse options then exit. --dry-run can be used to detect errors in cmdline options.
tools/perf/builtin-record.c +29 -1
@@ -62,6 +62,9 @@ struct switch_output {unsigned long time;const char *str;bool set; +char **filenames; +int num_files; +int cur_file; };struct record {
@@ -892,6 +895,7 @@ record__switch_output(struct record *rec, bool at_exit) {struct perf_data *data = &rec->data;int fd, err; +char *new_filename;/* Same Size: "2015122520103046"*/ char timestamp[] ="InvalidTimestamp" ;
@@ -912,7 +916,7 @@ record__switch_output(struct record *rec, bool at_exit) fd =perf_data__switch (data, timestamp, rec->session->header.data_offset, - at_exit); + at_exit, &new_filename);if (fd >=0 && !at_exit) { rec->bytes_written =0 ; rec->session->header.data_size =0 ;
@@ -922,6 +926,21 @@ record__switch_output(struct record *rec, bool at_exit)fprintf (stderr,"[ perf record: Dump %s.%s ]\n" , data->path, timestamp); +if (rec->switch_output.num_files) { +int n = rec->switch_output.cur_file +1 ; + +if (n >= rec->switch_output.num_files) + n =0 ; + rec->switch_output.cur_file = n; +if (rec->switch_output.filenames[n]) { +remove (rec->switch_output.filenames[n]); +free (rec->switch_output.filenames[n]); + } + rec->switch_output.filenames[n] = new_filename; + }else { +free (new_filename); + } +/* Output tracking events */ if (!at_exit) {record__synthesize (rec, false);
@@ -1973,6 +1992,8 @@ static struct option __record_options[] = { &record.switch_output.set, "signal,size,time", "Switch output when receive SIGUSR2 or cross size,time threshold", "signal"), +OPT_INTEGER (0 ,"switch-max-files" , &record.switch_output.num_files, +"Limit number of switch output generated files" ),OPT_BOOLEAN (0 ,"dry-run" , &dry_run,"Parse options then exit" ), #ifdef HAVE_AIO_SUPPORT
@@ -2059,6 +2080,13 @@ int cmd_record(int argc, const char **argv)alarm (rec->switch_output.time); } +if (rec->switch_output.num_files) { + rec->switch_output.filenames =calloc (sizeof (char *), + rec->switch_output.num_files); +if (!rec->switch_output.filenames) +return -EINVAL ; + } +/* * Allow aliases to facilitate the lookup of symbols for address * filters. Refer to auxtrace_parse_filters().
tools/perf/util/data.c +5 -6
@@ -361,9 +361,9 @@ ssize_t perf_data__write(struct perf_data *data,int perf_data__switch (struct perf_data *data,const char *postfix, -size_t pos,bool at_exit) +size_t pos,bool at_exit, +char **new_filepath) { -char *new_filepath;int ret;if (check_pipe (data))
@@ -371,15 +371,15 @@ int perf_data__switch(struct perf_data *data,if (perf_data__is_read (data))return -EINVAL ; -if (asprintf (&new_filepath,"%s.%s" , data->path, postfix) <0 ) +if (asprintf (new_filepath,"%s.%s" , data->path, postfix) <0 )return -ENOMEM ;/* * Only fire a warning, don't return error, continue fill * original file. */ -if (rename (data->path, new_filepath)) -pr_warning ("Failed to rename %s to %s\n" , data->path, new_filepath); +if (rename (data->path, *new_filepath)) +pr_warning ("Failed to rename %s to %s\n" , data->path, *new_filepath);if (!at_exit) {close (data->file.fd);
@@ -396,7 +396,6 @@ int perf_data__switch(struct perf_data *data, } ret = data->file.fd; out: -free (new_filepath);return ret; }
tools/perf/util/data.h +1 -1
@@ -70,7 +70,7 @@ ssize_t perf_data_file__write(struct perf_data_file *file,*/ int perf_data__switch (struct perf_data *data,const char *postfix, -size_t pos,bool at_exit); +size_t pos,bool at_exit,char **new_filepath);int perf_data__create_dir (struct perf_data *data,int nr);int perf_data__open_dir (struct perf_data *data);
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 3/44 perf record: Clarify help for --switch-output
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
The help description for --switch-output looks like there are multiple comma separated fields. But it's actually a choice of different options. Make it clear and less confusing.
Before:
% perf record -h
...
--switch-output[=<signal,size,time>]
Switch output when receive SIGUSR2 or cross size,time threshold
After:
% perf record -h
...
--switch-output[=<signal or size[BKMG] or time[smhd]>]
Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold
LPU-Reference: [email protected]
--- tools/perf/builtin-record.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/builtin-record.c +2 -2
@@ -1989,8 +1989,8 @@ static struct option __record_options[] = {OPT_BOOLEAN (0 ,"timestamp-boundary" , &record.timestamp_boundary,"Record timestamp boundary (time of first/last samples)" ),OPT_STRING_OPTARG_SET (0 ,"switch-output" , &record.switch_output.str, - &record.switch_output.set,"signal,size,time" , -"Switch output when receive SIGUSR2 or cross size,time threshold" , + &record.switch_output.set,"signal or size[BKMG] or time[smhd]" , +"Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold" ,"signal" ),OPT_INTEGER (0 ,"switch-max-files" , &record.switch_output.num_files, "Limit number of switch output generated files"),
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 4/44 perf report: Show all sort keys in help output
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Show all the supported sort keys in the command line help output, so that it's not needed to refer to the manpage.
Before:
% perf report -h
...
-s, --sort <key[,key2...]>
sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ... Please refer the man page for the complete list.
After:
% perf report -h
...
-s, --sort <key[,key2...]>
sort by key(s): overhead overhead_sys overhead_us overhead_guest_sys overhead_guest_us overhead_children sample period pid comm dso symbol parent cpu ...
LPU-Reference: [email protected]
--- tools/perf/builtin-report.c | 5 ++-- tools/perf/util/sort.c | 52 +++++++++++++++++++++++++++++++++++++ tools/perf/util/sort.h | 2 ++ 3 files changed, 56 insertions(+), 3 deletions(-)
tools/perf/builtin-report.c +2 -3
@@ -1083,10 +1083,9 @@ int cmd_report(int argc, const char **argv)OPT_BOOLEAN (0 ,"header-only" , &report.header_only,"Show only data header." ),OPT_STRING ('s' ,"sort" , &sort_order,"key[,key2...]" , -"sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." -" Please refer the man page for the complete list." ), +sort_help ("sort by key(s):" )),OPT_STRING ('F' ,"fields" , &field_order,"key[,keys...]" , -"output field(s): overhead, period, sample plus all of sort keys" ), +sort_help ("output field(s): overhead period sample " )),OPT_BOOLEAN (0 ,"show-cpu-utilization" , &symbol_conf.show_cpu_utilization,"Show sample percentage for different cpu modes" ), OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
tools/perf/util/sort.c +52 -0
61 lines not on this page · raw message
tools/perf/util/sort.h +2 -0
@@ -296,6 +296,8 @@ void reset_output_field(void);void sort__setup_elide (FILE *fp);void perf_hpp__set_elide (int idx,bool elide); +const char *sort_help (const char *prefix); +int report_parse_ignore_callees_opt (const struct option *opt,const char *arg,int unset);bool is_strict_order (const char *order);
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 5/44 perf report: Indicate JITed code better in report
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Print [TID] tid %d instead of the crypted /tmp/perf-%d.map default.
% cat >loop.java
public class loop {
public static void main(String[] args)
{
for (;;);
} }
^D
% javac loop.java
% perf record java loop
^C
Before:
% perf report --stdio
...
56.09% java perf-34724.map [.] 0x00007fd5bd021896
19.12% java perf-34724.map [.] 0x00007fd5bd021887
9.79% java perf-34724.map [.] 0x00007fd5bd021783
8.97% java perf-34724.map [.] 0x00007fd5bd02175bAfter:
% perf report --stdio
...
56.09% java [JIT] tid 34724 [.] 0x00007fd5bd021896
19.12% java [JIT] tid 34724 [.] 0x00007fd5bd021887
9.79% java [JIT] tid 34724 [.] 0x00007fd5bd021783
8.97% java [JIT] tid 34724 [.] 0x00007fd5bd02175bLPU-Reference: [email protected]
--- tools/perf/util/dso.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-)
tools/perf/util/dso.c +24 -18
@@ -1141,28 +1141,34 @@ void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)static void dso__set_basename (struct dso *dso) { -/* -* basename() may modify path buffer, so we must pass -* a copy. -*/ -char *base, *lname =strdup (dso->long_name); +char *base, *lname; +int tid; -if (!lname) -return ; - -/* -* basename() may return a pointer to internal -* storage which is reused in subsequent calls -* so copy the result. -*/ - base =strdup (basename (lname)); +if (sscanf (dso->long_name,"/tmp/perf-%d.map" , &tid) ==1 ) { +if (asprintf (&base,"[JIT] tid %d" , tid) <0 ) +return ; + }else { +/* +* basename() may modify path buffer, so we must pass +* a copy. +*/ + lname =strdup (dso->long_name); +if (!lname) +return ; -free (lname); +/* +* basename() may return a pointer to internal +* storage which is reused in subsequent calls +* so copy the result. +*/ + base =strdup (basename (lname)); -if (!base) -return ; +free (lname); -dso__set_short_name (dso, base, true); +if (!base) +return ; + } +dso__set_short_name (dso, base, true); }int dso__name_len (const struct dso *dso)
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 6/44 perf script: Support relative time
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
When comparing time stamps in 'perf script' traces it can be annoying to work with the full perf time stamps.
Add a --reltime option that displays time stamps relative to the trace start to make it easier to read the traces.
Note: not currently supported for --time. Report an error in this case.
Before:
% perf script
swapper 0 [000] 245402.891216: 1 cycles:ppp: ffffffffa0068814 native_write_msr+0x4 ([kernel.kallsyms])
swapper 0 [000] 245402.891223: 1 cycles:ppp: ffffffffa0068814 native_write_msr+0x4 ([kernel.kallsyms])
swapper 0 [000] 245402.891227: 5 cycles:ppp: ffffffffa0068814 native_write_msr+0x4 ([kernel.kallsyms])
swapper 0 [000] 245402.891231: 41 cycles:ppp: ffffffffa0068816 native_write_msr+0x6 ([kernel.kallsyms])
swapper 0 [000] 245402.891235: 355 cycles:ppp: ffffffffa000dd51 intel_bts_enable_local+0x21 ([kernel.kallsyms])
swapper 0 [000] 245402.891239: 3084 cycles:ppp: ffffffffa0a0150a end_repeat_nmi+0x48 ([kernel.kallsyms])After:
% perf script --reltime
swapper 0 [000] 0.000000: 1 cycles:ppp: ffffffffa0068814 native_write_msr+0x4 ([kernel.kallsyms])
swapper 0 [000] 0.000006: 1 cycles:ppp: ffffffffa0068814 native_write_msr+0x4 ([kernel.kallsyms])
swapper 0 [000] 0.000010: 5 cycles:ppp: ffffffffa0068814 native_write_msr+0x4 ([kernel.kallsyms])
swapper 0 [000] 0.000014: 41 cycles:ppp: ffffffffa0068816 native_write_msr+0x6 ([kernel.kallsyms])
swapper 0 [000] 0.000018: 355 cycles:ppp: ffffffffa000dd51 intel_bts_enable_local+0x21 ([kernel.kallsyms])
swapper 0 [000] 0.000022: 3084 cycles:ppp: ffffffffa0a0150a end_repeat_nmi+0x48 ([kernel.kallsyms])Committer notes:
Do not use 'time' as the name of a variable, as this breaks the build on older glibcs:
cc1: warnings being treated as errors
builtin-script.c: In function 'perf_sample__fprintf_start':
builtin-script.c:691: warning: declaration of 'time' shadows a global declaration /usr/include/time.h:187: warning: shadowed declaration is here
LPU-Reference: [email protected]
--- tools/perf/Documentation/perf-script.txt | 3 +++ tools/perf/builtin-script.c | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-script.txt +3 -0
@@ -380,6 +380,9 @@ include::itrace.txt[] Set the maximum number of program blocks to print with brstackasm for each sample. +--reltime:: + Print time stamps relative to trace start. + --per-event-dump:: Create per event files with a "perf.data.EVENT.dump" name instead of printing to stdout, useful, for instance, for generating flamegraphs.
tools/perf/builtin-script.c +16 -2
@@ -53,6 +53,8 @@static char const *script_name;static char const *generate_script_lang; +static bool reltime; +static u64 initial_time;static bool debug_mode;static u64 last_timestamp;static u64 nr_unordered;
@@ -686,7 +688,13 @@ static int perf_sample__fprintf_start(struct perf_sample *sample, }if (PRINT_FIELD (TIME )) { - nsecs = sample->time; +u64 t = sample->time; +if (reltime) { +if (!initial_time) + initial_time = sample->time; + t = sample->time - initial_time; + } + nsecs = t; secs = nsecs /NSEC_PER_SEC ; nsecs -= secs *NSEC_PER_SEC ;
@@ -694,7 +702,7 @@ static int perf_sample__fprintf_start(struct perf_sample *sample, printed +=fprintf (fp,"%5lu.%09llu: " , secs, nsecs); else {char sample_time[32 ]; -timestamp__scnprintf_usec (sample->time, sample_time,sizeof (sample_time)); +timestamp__scnprintf_usec (t, sample_time,sizeof (sample_time)); printed +=fprintf (fp,"%12s: " , sample_time); } }
@@ -3413,6 +3421,7 @@ int cmd_script(int argc, const char **argv)"Set the maximum stack depth when parsing the callchain, " "anything beyond the specified depth will be ignored. " "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), +OPT_BOOLEAN (0 ,"reltime" , &reltime,"Show time stamps relative to start" ),OPT_BOOLEAN ('I' ,"show-info" , &show_full_info,"display extended information from perf.data file" ), OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -3487,6 +3496,11 @@ int cmd_script(int argc, const char **argv) } } +if (script.time_str && reltime) { +fprintf (stderr,"Don't combine --reltime with --time\n" ); +return -1 ; + } +if (itrace_synth_opts.callchain && itrace_synth_opts.callchain_sz > scripting_max_stack) scripting_max_stack = itrace_synth_opts.callchain_sz;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 7/44 perf stat: Fix --no-scale
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
The -c option to enable multiplex scaling has been useless for quite some time because scaling is default.
It's only useful as --no-scale to disable scaling. But the non scaling code path has bitrotted and doesn't print anything because perf output code relies on value run/ena information.
Also even when we don't want to scale a value it's still useful to show its multiplex percentage.
This patch:
- Fixes help and documentation to show --no-scale instead of -c
- Removes -c, only keeps the long option because -c doesn't support negatives.
- Enables running/enabled even with --no-scale
- And fixes some other problems in the no-scale output.
Before:
$ perf stat --no-scale -e cycles true
Performance counter stats for 'true':
<not counted> cycles
0.000984154 seconds time elapsed
After:
$ ./perf stat --no-scale -e cycles true
Performance counter stats for 'true':
706,070 cycles
0.001219821 seconds time elapsedLPU-Reference: [email protected]
--- tools/perf/Documentation/perf-stat.txt | 5 ++--- tools/perf/builtin-stat.c | 3 ++- tools/perf/util/evsel.c | 3 +-- tools/perf/util/stat.c | 12 ++++-------- 4 files changed, 9 insertions(+), 14 deletions(-)
tools/perf/Documentation/perf-stat.txt +2 -3
@@ -72,9 +72,8 @@ report:: --all-cpus:: system-wide collection from all CPUs (default if no target is specified) --c:: ---scale:: - scale/normalize counter values +--no-scale:: + Don't scale/normalize counter values -d:: --detailed::
tools/perf/builtin-stat.c +2 -1
@@ -718,7 +718,8 @@ static struct option stat_options[] = { "system-wide collection from all CPUs"),OPT_BOOLEAN ('g' ,"group" , &group,"put the counters into a counter group" ), -OPT_BOOLEAN ('c' ,"scale" , &stat_config.scale,"scale/normalize counters" ), +OPT_BOOLEAN (0 ,"scale" , &stat_config.scale, +"Use --no-scale to disable counter scaling for multiplexing" ),OPT_INCR ('v' ,"verbose" , &verbose,"be more verbose (show counter open errors, etc)" ), OPT_INTEGER('r', "repeat", &stat_config.run_count,
tools/perf/util/evsel.c +1 -2
@@ -1344,8 +1344,7 @@ void perf_counts_values__scale(struct perf_counts_values *count, scaled =1 ; count->val = (u64)((double ) count->val * count->ena / count->run +0.5 ); } - }else - count->ena = count->run =0 ; + }if (pscaled) *pscaled = scaled;
tools/perf/util/stat.c +4 -8
@@ -291,10 +291,8 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evselbreak ;case AGGR_GLOBAL : aggr->val += count->val; -if (config->scale) { - aggr->ena += count->ena; - aggr->run += count->run; - } + aggr->ena += count->ena; + aggr->run += count->run;case AGGR_UNSET :default :break ;
@@ -442,10 +440,8 @@ int create_perf_stat_counter(struct perf_evsel *evsel,struct perf_event_attr *attr = &evsel->attr;struct perf_evsel *leader = evsel->leader; -if (config->scale) { - attr->read_format =PERF_FORMAT_TOTAL_TIME_ENABLED | -PERF_FORMAT_TOTAL_TIME_RUNNING ; - } + attr->read_format =PERF_FORMAT_TOTAL_TIME_ENABLED | +PERF_FORMAT_TOTAL_TIME_RUNNING ;/* * The event is part of non trivial group, let's enable
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 8/44 perf stat: Improve scaling
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
The multiplexing scaling in perf stat mysteriously adds 0.5 to the value. This dates back to the original perf tool. Other scaling code doesn't use that strange convention. Remove the extra 0.5.
Before:
$ perf stat -e 'cycles,cycles,cycles,cycles,cycles,cycles' grep -rq foo
Performance counter stats for 'grep -rq foo':
6,403,580 cycles (81.62%)
6,404,341 cycles (81.64%)
6,402,983 cycles (81.62%)
6,399,941 cycles (81.63%)
6,399,451 cycles (81.62%)
6,436,105 cycles (91.87%) 0.005843799 seconds time elapsed
0.002905000 seconds user
0.002902000 seconds sysAfter:
$ perf stat -e 'cycles,cycles,cycles,cycles,cycles,cycles' grep -rq foo
Performance counter stats for 'grep -rq foo':
6,422,704 cycles (81.68%)
6,401,842 cycles (81.68%)
6,398,432 cycles (81.68%)
6,397,098 cycles (81.68%)
6,396,074 cycles (81.67%)
6,434,980 cycles (91.62%) 0.005884437 seconds time elapsed
0.003580000 seconds user
0.002356000 seconds sysLPU-Reference: [email protected]
--- tools/perf/util/evsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/evsel.c +1 -1
@@ -1342,7 +1342,7 @@ void perf_counts_values__scale(struct perf_counts_values *count, count->val =0 ; }else if (count->run < count->ena) { scaled =1 ; - count->val = (u64)((double ) count->val * count->ena / count->run +0.5 ); + count->val = (u64)((double ) count->val * count->ena / count->run); } }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 9/44 perf vendor events: Remove P8 HW events which are not supported
In reply to Arnaldo Carvalho de MeloFrom: Mamatha Inamdar <[email protected]>
This patch is to remove following hardware events from JSON file which are not supported on POWER8.
pm_co_disp_fail
pm_co_tm_sc_footprint
pm_iside_disp
pm_iside_disp_fail
pm_iside_disp_fail_other
pm_iside_mru_touch
pm_l2_castout_mod
pm_l2_castout_shr
pm_l2_dc_inv
pm_l2_disp_all_l2miss
pm_l2_grp_guess_correct
pm_l2_grp_guess_wrong
pm_l2_ic_inv
pm_l2_inst
pm_l2_inst_miss
pm_l2_ld
pm_l2_ld_disp
pm_l2_ld_hit
pm_l2_ld_miss
pm_l2_loc_guess_correct
pm_l2_loc_guess_wrong
pm_l2_rcld_disp
pm_l2_rcld_disp_fail_addr
pm_l2_rcld_disp_fail_other
pm_l2_rcst_disp
pm_l2_rcst_disp_fail_addr
pm_l2_rcst_disp_fail_other
pm_l2_rc_st_done
pm_l2_rty_ld
pm_l2_sn_m_rd_done
pm_l2_sn_m_wr_done
pm_l2_sn_sx_i_done
pm_l2_st_disp
pm_l2_st_hit
pm_l2_sys_guess_correct
pm_l2_sys_guess_wrong
pm_l2_sys_pump
pm_l3_ci_hit
pm_l3_ci_miss
pm_l3_cinj
pm_l3_co
pm_l3_co_lco
pm_l3_grp_guess_correct
pm_l3_grp_guess_wrong_high
pm_l3_grp_guess_wrong_low
pm_l3_hit
pm_l3_l2_co_hit
pm_l3_l2_co_miss
pm_l3_lat_ci_hit
pm_l3_lat_ci_miss
pm_l3_ld_hit
pm_l3_ld_miss
pm_l3_loc_guess_correct
pm_l3_loc_guess_wrong
pm_l3_miss
pm_l3_p0_co_l31
pm_l3_p0_co_mem
pm_l3_p0_co_rty
pm_l3_p0_grp_pump
pm_l3_p0_lco_data
pm_l3_p0_lco_no_data
pm_l3_p0_lco_rty
pm_l3_p0_node_pump
pm_l3_p0_pf_rty
pm_l3_p0_sn_hit
pm_l3_p0_sn_inv
pm_l3_p0_sn_miss
pm_l3_p0_sys_pump
pm_l3_p1_co_l31
pm_l3_p1_co_mem
pm_l3_p1_co_rty
pm_l3_p1_grp_pump
pm_l3_p1_lco_data
pm_l3_p1_lco_no_data
pm_l3_p1_lco_rty
pm_l3_p1_node_pump
pm_l3_p1_pf_rty
pm_l3_p1_sn_hit
pm_l3_p1_sn_inv
pm_l3_p1_sn_miss
pm_l3_p1_sys_pump
pm_l3_pf_hit_l3
pm_l3_sys_guess_correct
pm_l3_sys_guess_wrong
pm_l3_trans_pf
pm_l3_wi0_busy
pm_l3_wi_usage
pm_non_tm_rst_sc
pm_rd_clearing_sc
pm_rd_forming_sc
pm_rd_hit_pf
pm_snp_tm_hit_m
pm_snp_tm_hit_t
pm_st_caused_fail
pm_tm_cam_overflow
pm_tm_cap_overflow
pm_tm_fav_caused_fail
pm_tm_ld_caused_fail
pm_tm_ld_conf
pm_tm_rst_sc
pm_tm_sc_co
pm_tm_st_caused_fail
pm_tm_st_conf
--- .../pmu-events/arch/powerpc/power8/other.json | 594 ------------------ 1 file changed, 594 deletions(-)
tools/perf/pmu-events/arch/powerpc/power8/other.json +0 -594
@@ -347,18 +347,6 @@ "BriefDescription": "CO mach 0 Busy. Used by PMU to sample ave RC livetime(mach0 used as sample point)", "PublicDescription": "" }, - {, - "EventCode": "0x517082", - "EventName": "PM_CO_DISP_FAIL", - "BriefDescription": "CO dispatch failed due to all CO machines being busy", - "PublicDescription": "" - }, - {, - "EventCode": "0x527084", - "EventName": "PM_CO_TM_SC_FOOTPRINT", - "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3)", - "PublicDescription": "" - }, {, "EventCode": "0x3608a", "EventName": "PM_CO_USAGE",
@@ -1577,36 +1565,12 @@ "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another core's L3 on the same chip due to a instruction side request", "PublicDescription": "" }, - {, - "EventCode": "0x617082", - "EventName": "PM_ISIDE_DISP", - "BriefDescription": "All i-side dispatch attempts", - "PublicDescription": "" - }, - {, - "EventCode": "0x627084", - "EventName": "PM_ISIDE_DISP_FAIL", - "BriefDescription": "All i-side dispatch attempts that failed due to a addr collision with another machine", - "PublicDescription": "" - }, - {, - "EventCode": "0x627086", - "EventName": "PM_ISIDE_DISP_FAIL_OTHER", - "BriefDescription": "All i-side dispatch attempts that failed due to a reason other than addrs collision", - "PublicDescription": "" - }, {, "EventCode": "0x4608e", "EventName": "PM_ISIDE_L2MEMACC", "BriefDescription": "valid when first beat of data comes in for an i-side fetch where data came from mem(or L4)", "PublicDescription": "" }, - {, - "EventCode": "0x44608e", - "EventName": "PM_ISIDE_MRU_TOUCH", - "BriefDescription": "Iside L2 MRU touch", - "PublicDescription": "" - }, {, "EventCode": "0x30ac", "EventName": "PM_ISU_REF_FX0",
@@ -1733,222 +1697,36 @@ "BriefDescription": "Instruction Demand sectors wriittent into IL1", "PublicDescription": "" }, - {, - "EventCode": "0x417080", - "EventName": "PM_L2_CASTOUT_MOD", - "BriefDescription": "L2 Castouts - Modified (M, Mu, Me)", - "PublicDescription": "" - }, - {, - "EventCode": "0x417082", - "EventName": "PM_L2_CASTOUT_SHR", - "BriefDescription": "L2 Castouts - Shared (T, Te, Si, S)", - "PublicDescription": "" - }, {, "EventCode": "0x27084", "EventName": "PM_L2_CHIP_PUMP", "BriefDescription": "RC requests that were local on chip pump attempts", "PublicDescription": "" }, - {, - "EventCode": "0x427086", - "EventName": "PM_L2_DC_INV", - "BriefDescription": "Dcache invalidates from L2", - "PublicDescription": "" - }, - {, - "EventCode": "0x44608c", - "EventName": "PM_L2_DISP_ALL_L2MISS", - "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2miss", - "PublicDescription": "" - }, {, "EventCode": "0x27086", "EventName": "PM_L2_GROUP_PUMP", "BriefDescription": "RC requests that were on Node Pump attempts", "PublicDescription": "" }, - {, - "EventCode": "0x626084", - "EventName": "PM_L2_GRP_GUESS_CORRECT", - "BriefDescription": "L2 guess grp and guess was correct (data intra-6chip AND ^on-chip)", - "PublicDescription": "" - }, - {, - "EventCode": "0x626086", - "EventName": "PM_L2_GRP_GUESS_WRONG", - "BriefDescription": "L2 guess grp and guess was not correct (ie data on-chip OR beyond-6chip)", - "PublicDescription": "" - }, - {, - "EventCode": "0x427084", - "EventName": "PM_L2_IC_INV", - "BriefDescription": "Icache Invalidates from L2", - "PublicDescription": "" - }, - {, - "EventCode": "0x436088", - "EventName": "PM_L2_INST", - "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)", - "PublicDescription": "" - }, - {, - "EventCode": "0x43608a", - "EventName": "PM_L2_INST_MISS", - "BriefDescription": "All successful i-side dispatches that were an L2miss for this thread (excludes i_l2mru_tch reqs)", - "PublicDescription": "" - }, - {, - "EventCode": "0x416080", - "EventName": "PM_L2_LD", - "BriefDescription": "All successful D-side Load dispatches for this thread", - "PublicDescription": "" - }, - {, - "EventCode": "0x437088", - "EventName": "PM_L2_LD_DISP", - "BriefDescription": "All successful load dispatches", - "PublicDescription": "" - }, - {, - "EventCode": "0x43708a", - "EventName": "PM_L2_LD_HIT", - "BriefDescription": "All successful load dispatches that were L2 hits", - "PublicDescription": "" - }, - {, - "EventCode": "0x426084", - "EventName": "PM_L2_LD_MISS", - "BriefDescription": "All successful D-Side Load dispatches that were an L2miss for this thread", - "PublicDescription": "" - }, - {, - "EventCode": "0x616080", - "EventName": "PM_L2_LOC_GUESS_CORRECT", - "BriefDescription": "L2 guess loc and guess was correct (ie data local)", - "PublicDescription": "" - }, - {, - "EventCode": "0x616082", - "EventName": "PM_L2_LOC_GUESS_WRONG", - "BriefDescription": "L2 guess loc and guess was not correct (ie data not on chip)", - "PublicDescription": "" - }, - {, - "EventCode": "0x516080", - "EventName": "PM_L2_RCLD_DISP", - "BriefDescription": "L2 RC load dispatch attempt", - "PublicDescription": "" - }, - {, - "EventCode": "0x516082", - "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR", - "BriefDescription": "L2 RC load dispatch attempt failed due to address collision with RC/CO/SN/SQ", - "PublicDescription": "" - }, - {, - "EventCode": "0x526084", - "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER", - "BriefDescription": "L2 RC load dispatch attempt failed due to other reasons", - "PublicDescription": "" - }, - {, - "EventCode": "0x536088", - "EventName": "PM_L2_RCST_DISP", - "BriefDescription": "L2 RC store dispatch attempt", - "PublicDescription": "" - }, - {, - "EventCode": "0x53608a", - "EventName": "PM_L2_RCST_DISP_FAIL_ADDR", - "BriefDescription": "L2 RC store dispatch attempt failed due to address collision with RC/CO/SN/SQ", - "PublicDescription": "" - }, - {, - "EventCode": "0x54608c", - "EventName": "PM_L2_RCST_DISP_FAIL_OTHER", - "BriefDescription": "L2 RC store dispatch attempt failed due to other reasons", - "PublicDescription": "" - }, - {, - "EventCode": "0x537088", - "EventName": "PM_L2_RC_ST_DONE", - "BriefDescription": "RC did st to line that was Tx or Sx", - "PublicDescription": "" - }, - {, - "EventCode": "0x63708a", - "EventName": "PM_L2_RTY_LD", - "BriefDescription": "RC retries on PB for any load from core", - "PublicDescription": "" - }, {, "EventCode": "0x3708a", "EventName": "PM_L2_RTY_ST", "BriefDescription": "RC retries on PB for any store from core", "PublicDescription": "" }, - {, - "EventCode": "0x54708c", - "EventName": "PM_L2_SN_M_RD_DONE", - "BriefDescription": "SNP dispatched for a read and was M", - "PublicDescription": "" - }, - {, - "EventCode": "0x54708e", - "EventName": "PM_L2_SN_M_WR_DONE", - "BriefDescription": "SNP dispatched for a write and was M", - "PublicDescription": "" - }, - {, - "EventCode": "0x53708a", - "EventName": "PM_L2_SN_SX_I_DONE", - "BriefDescription": "SNP dispatched and went from Sx or Tx to Ix", - "PublicDescription": "" - }, {, "EventCode": "0x17080", "EventName": "PM_L2_ST", "BriefDescription": "All successful D-side store dispatches for this thread", "PublicDescription": "" }, - {, - "EventCode": "0x44708c", - "EventName": "PM_L2_ST_DISP", - "BriefDescription": "All successful store dispatches", - "PublicDescription": "" - }, - {, - "EventCode": "0x44708e", - "EventName": "PM_L2_ST_HIT", - "BriefDescription": "All successful store dispatches that were L2Hits", - "PublicDescription": "" - }, {, "EventCode": "0x17082", "EventName": "PM_L2_ST_MISS", "BriefDescription": "All successful D-side store dispatches for this thread that were L2 Miss", "PublicDescription": "" }, - {, - "EventCode": "0x636088", - "EventName": "PM_L2_SYS_GUESS_CORRECT", - "BriefDescription": "L2 guess sys and guess was correct (ie data beyond-6chip)", - "PublicDescription": "" - }, - {, - "EventCode": "0x63608a", - "EventName": "PM_L2_SYS_GUESS_WRONG", - "BriefDescription": "L2 guess sys and guess was not correct (ie data ^beyond-6chip)", - "PublicDescription": "" - }, - {, - "EventCode": "0x617080", - "EventName": "PM_L2_SYS_PUMP", - "BriefDescription": "RC requests that were system pump attempts", - "PublicDescription": "" - }, {, "EventCode": "0x1e05e", "EventName": "PM_L2_TM_REQ_ABORT",
@@ -1961,36 +1739,12 @@ "BriefDescription": "TM marked store abort", "PublicDescription": "" }, - {, - "EventCode": "0x23808a", - "EventName": "PM_L3_CINJ", - "BriefDescription": "l3 ci of cache inject", - "PublicDescription": "" - }, - {, - "EventCode": "0x128084", - "EventName": "PM_L3_CI_HIT", - "BriefDescription": "L3 Castins Hit (total count", - "PublicDescription": "" - }, - {, - "EventCode": "0x128086", - "EventName": "PM_L3_CI_MISS", - "BriefDescription": "L3 castins miss (total count", - "PublicDescription": "" - }, {, "EventCode": "0x819082", "EventName": "PM_L3_CI_USAGE", "BriefDescription": "rotating sample of 16 CI or CO actives", "PublicDescription": "" }, - {, - "EventCode": "0x438088", - "EventName": "PM_L3_CO", - "BriefDescription": "l3 castout occurring ( does not include casthrough or log writes (cinj/dmaw)", - "PublicDescription": "" - }, {, "EventCode": "0x83908b", "EventName": "PM_L3_CO0_ALLOC",
@@ -2009,120 +1763,18 @@ "BriefDescription": "L3 CO to L3.1 OR of port 0 and 1 ( lossy)", "PublicDescription": "" }, - {, - "EventCode": "0x238088", - "EventName": "PM_L3_CO_LCO", - "BriefDescription": "Total L3 castouts occurred on LCO", - "PublicDescription": "" - }, {, "EventCode": "0x28084", "EventName": "PM_L3_CO_MEM", "BriefDescription": "L3 CO to memory OR of port 0 and 1 ( lossy)", "PublicDescription": "" }, - {, - "EventCode": "0xb19082", - "EventName": "PM_L3_GRP_GUESS_CORRECT", - "BriefDescription": "Initial scope=group and data from same group (near) (pred successful)", - "PublicDescription": "" - }, - {, - "EventCode": "0xb3908a", - "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH", - "BriefDescription": "Initial scope=group but data from local node. Predition too high", - "PublicDescription": "" - }, - {, - "EventCode": "0xb39088", - "EventName": "PM_L3_GRP_GUESS_WRONG_LOW", - "BriefDescription": "Initial scope=group but data from outside group (far or rem). Prediction too Low", - "PublicDescription": "" - }, - {, - "EventCode": "0x218080", - "EventName": "PM_L3_HIT", - "BriefDescription": "L3 Hits", - "PublicDescription": "" - }, - {, - "EventCode": "0x138088", - "EventName": "PM_L3_L2_CO_HIT", - "BriefDescription": "L2 castout hits", - "PublicDescription": "" - }, - {, - "EventCode": "0x13808a", - "EventName": "PM_L3_L2_CO_MISS", - "BriefDescription": "L2 castout miss", - "PublicDescription": "" - }, - {, - "EventCode": "0x14808c", - "EventName": "PM_L3_LAT_CI_HIT", - "BriefDescription": "L3 Lateral Castins Hit", - "PublicDescription": "" - }, - {, - "EventCode": "0x14808e", - "EventName": "PM_L3_LAT_CI_MISS", - "BriefDescription": "L3 Lateral Castins Miss", - "PublicDescription": "" - }, - {, - "EventCode": "0x228084", - "EventName": "PM_L3_LD_HIT", - "BriefDescription": "L3 demand LD Hits", - "PublicDescription": "" - }, - {, - "EventCode": "0x228086", - "EventName": "PM_L3_LD_MISS", - "BriefDescription": "L3 demand LD Miss", - "PublicDescription": "" - }, {, "EventCode": "0x1e052", "EventName": "PM_L3_LD_PREF", "BriefDescription": "L3 Load Prefetches", "PublicDescription": "" }, - {, - "EventCode": "0xb19080", - "EventName": "PM_L3_LOC_GUESS_CORRECT", - "BriefDescription": "initial scope=node/chip and data from local node (local) (pred successful)", - "PublicDescription": "" - }, - {, - "EventCode": "0xb29086", - "EventName": "PM_L3_LOC_GUESS_WRONG", - "BriefDescription": "Initial scope=node but data from out side local node (near or far or rem). Prediction too Low", - "PublicDescription": "" - }, - {, - "EventCode": "0x218082", - "EventName": "PM_L3_MISS", - "BriefDescription": "L3 Misses", - "PublicDescription": "" - }, - {, - "EventCode": "0x54808c", - "EventName": "PM_L3_P0_CO_L31", - "BriefDescription": "l3 CO to L3.1 (lco) port 0", - "PublicDescription": "" - }, - {, - "EventCode": "0x538088", - "EventName": "PM_L3_P0_CO_MEM", - "BriefDescription": "l3 CO to memory port 0", - "PublicDescription": "" - }, - {, - "EventCode": "0x929084", - "EventName": "PM_L3_P0_CO_RTY", - "BriefDescription": "L3 CO received retry port 0", - "PublicDescription": "" - }, {, "EventCode": "0xa29084", "EventName": "PM_L3_P0_GRP_PUMP",
@@ -2147,120 +1799,6 @@ "BriefDescription": "L3 LCO received retry port 0", "PublicDescription": "" }, - {, - "EventCode": "0xa19080", - "EventName": "PM_L3_P0_NODE_PUMP", - "BriefDescription": "L3 pf sent with nodal scope port 0", - "PublicDescription": "" - }, - {, - "EventCode": "0x919080", - "EventName": "PM_L3_P0_PF_RTY", - "BriefDescription": "L3 PF received retry port 0", - "PublicDescription": "" - }, - {, - "EventCode": "0x939088", - "EventName": "PM_L3_P0_SN_HIT", - "BriefDescription": "L3 snoop hit port 0", - "PublicDescription": "" - }, - {, - "EventCode": "0x118080", - "EventName": "PM_L3_P0_SN_INV", - "BriefDescription": "Port0 snooper detects someone doing a store to a line thats Sx", - "PublicDescription": "" - }, - {, - "EventCode": "0x94908c", - "EventName": "PM_L3_P0_SN_MISS", - "BriefDescription": "L3 snoop miss port 0", - "PublicDescription": "" - }, - {, - "EventCode": "0xa39088", - "EventName": "PM_L3_P0_SYS_PUMP", - "BriefDescription": "L3 pf sent with sys scope port 0", - "PublicDescription": "" - }, - {, - "EventCode": "0x54808e", - "EventName": "PM_L3_P1_CO_L31", - "BriefDescription": "l3 CO to L3.1 (lco) port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0x53808a", - "EventName": "PM_L3_P1_CO_MEM", - "BriefDescription": "l3 CO to memory port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0x929086", - "EventName": "PM_L3_P1_CO_RTY", - "BriefDescription": "L3 CO received retry port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0xa29086", - "EventName": "PM_L3_P1_GRP_PUMP", - "BriefDescription": "L3 pf sent with grp scope port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0x528086", - "EventName": "PM_L3_P1_LCO_DATA", - "BriefDescription": "lco sent with data port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0x518082", - "EventName": "PM_L3_P1_LCO_NO_DATA", - "BriefDescription": "dataless l3 lco sent port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0xa4908e", - "EventName": "PM_L3_P1_LCO_RTY", - "BriefDescription": "L3 LCO received retry port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0xa19082", - "EventName": "PM_L3_P1_NODE_PUMP", - "BriefDescription": "L3 pf sent with nodal scope port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0x919082", - "EventName": "PM_L3_P1_PF_RTY", - "BriefDescription": "L3 PF received retry port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0x93908a", - "EventName": "PM_L3_P1_SN_HIT", - "BriefDescription": "L3 snoop hit port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0x118082", - "EventName": "PM_L3_P1_SN_INV", - "BriefDescription": "Port1 snooper detects someone doing a store to a line thats Sx", - "PublicDescription": "" - }, - {, - "EventCode": "0x94908e", - "EventName": "PM_L3_P1_SN_MISS", - "BriefDescription": "L3 snoop miss port 1", - "PublicDescription": "" - }, - {, - "EventCode": "0xa3908a", - "EventName": "PM_L3_P1_SYS_PUMP", - "BriefDescription": "L3 pf sent with sys scope port 1", - "PublicDescription": "" - }, {, "EventCode": "0x84908d", "EventName": "PM_L3_PF0_ALLOC",
@@ -2273,12 +1811,6 @@ "BriefDescription": "lifetime, sample of PF machine 0 valid", "PublicDescription": "" }, - {, - "EventCode": "0x428084", - "EventName": "PM_L3_PF_HIT_L3", - "BriefDescription": "l3 pf hit in l3", - "PublicDescription": "" - }, {, "EventCode": "0x18080", "EventName": "PM_L3_PF_MISS_L3",
@@ -2369,42 +1901,12 @@ "BriefDescription": "Data stream touchto L3", "PublicDescription": "" }, - {, - "EventCode": "0xb29084", - "EventName": "PM_L3_SYS_GUESS_CORRECT", - "BriefDescription": "Initial scope=system and data from outside group (far or rem)(pred successful)", - "PublicDescription": "" - }, - {, - "EventCode": "0xb4908c", - "EventName": "PM_L3_SYS_GUESS_WRONG", - "BriefDescription": "Initial scope=system but data from local or near. Predction too high", - "PublicDescription": "" - }, - {, - "EventCode": "0x24808e", - "EventName": "PM_L3_TRANS_PF", - "BriefDescription": "L3 Transient prefetch", - "PublicDescription": "" - }, {, "EventCode": "0x18081", "EventName": "PM_L3_WI0_ALLOC", "BriefDescription": "lifetime, sample of Write Inject machine 0 valid", "PublicDescription": "0.0" }, - {, - "EventCode": "0x418080", - "EventName": "PM_L3_WI0_BUSY", - "BriefDescription": "lifetime, sample of Write Inject machine 0 valid", - "PublicDescription": "" - }, - {, - "EventCode": "0x418082", - "EventName": "PM_L3_WI_USAGE", - "BriefDescription": "rotating sample of 8 WI actives", - "PublicDescription": "" - }, {, "EventCode": "0xc080", "EventName": "PM_LD_REF_L1_LSU0",
@@ -3311,12 +2813,6 @@ "BriefDescription": "Dispatch time non favored tbegin", "PublicDescription": "" }, - {, - "EventCode": "0x328084", - "EventName": "PM_NON_TM_RST_SC", - "BriefDescription": "non tm snp rst tm sc", - "PublicDescription": "" - }, {, "EventCode": "0x2001a", "EventName": "PM_NTCG_ALL_FIN",
@@ -3419,24 +2915,6 @@ "BriefDescription": "Continuous 16 cycle(2to1) window where this signals rotates thru sampling each L2 RC machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running", "PublicDescription": "" }, - {, - "EventCode": "0x34808e", - "EventName": "PM_RD_CLEARING_SC", - "BriefDescription": "rd clearing sc", - "PublicDescription": "" - }, - {, - "EventCode": "0x34808c", - "EventName": "PM_RD_FORMING_SC", - "BriefDescription": "rd forming sc", - "PublicDescription": "" - }, - {, - "EventCode": "0x428086", - "EventName": "PM_RD_HIT_PF", - "BriefDescription": "rd machine hit l3 pf machine", - "PublicDescription": "" - }, {, "EventCode": "0x20004", "EventName": "PM_REAL_SRQ_FULL",
@@ -3503,18 +2981,6 @@ "BriefDescription": "TLBIE snoop", "PublicDescription": "TLBIE snoopSnoop TLBIE" }, - {, - "EventCode": "0x338088", - "EventName": "PM_SNP_TM_HIT_M", - "BriefDescription": "snp tm st hit m mu", - "PublicDescription": "" - }, - {, - "EventCode": "0x33808a", - "EventName": "PM_SNP_TM_HIT_T", - "BriefDescription": "snp tm_st_hit t tn te", - "PublicDescription": "" - }, {, "EventCode": "0x4608c", "EventName": "PM_SN_USAGE",
@@ -3533,12 +2999,6 @@ "BriefDescription": "STCX executed reported at sent to nest", "PublicDescription": "STCX executed reported at sent to nest42" }, - {, - "EventCode": "0x717080", - "EventName": "PM_ST_CAUSED_FAIL", - "BriefDescription": "Non TM St caused any thread to fail", - "PublicDescription": "" - }, {, "EventCode": "0x3090", "EventName": "PM_SWAP_CANCEL",
@@ -3623,18 +3083,6 @@ "BriefDescription": "Tm any tbegin", "PublicDescription": "" }, - {, - "EventCode": "0x318082", - "EventName": "PM_TM_CAM_OVERFLOW", - "BriefDescription": "l3 tm cam overflow during L2 co of SC", - "PublicDescription": "" - }, - {, - "EventCode": "0x74708c", - "EventName": "PM_TM_CAP_OVERFLOW", - "BriefDescription": "TM Footprint Capactiy Overflow", - "PublicDescription": "" - }, {, "EventCode": "0x20ba", "EventName": "PM_TM_END_ALL",
@@ -3689,48 +3137,6 @@ "BriefDescription": "Transactional conflict from LSU, whatever gets reported to texas", "PublicDescription": "Transactional conflict from LSU, whatever gets reported to texas 42" }, - {, - "EventCode": "0x727086", - "EventName": "PM_TM_FAV_CAUSED_FAIL", - "BriefDescription": "TM Load (fav) caused another thread to fail", - "PublicDescription": "" - }, - {, - "EventCode": "0x717082", - "EventName": "PM_TM_LD_CAUSED_FAIL", - "BriefDescription": "Non TM Ld caused any thread to fail", - "PublicDescription": "" - }, - {, - "EventCode": "0x727084", - "EventName": "PM_TM_LD_CONF", - "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)", - "PublicDescription": "" - }, - {, - "EventCode": "0x328086", - "EventName": "PM_TM_RST_SC", - "BriefDescription": "tm snp rst tm sc", - "PublicDescription": "" - }, - {, - "EventCode": "0x318080", - "EventName": "PM_TM_SC_CO", - "BriefDescription": "l3 castout tm Sc line", - "PublicDescription": "" - }, - {, - "EventCode": "0x73708a", - "EventName": "PM_TM_ST_CAUSED_FAIL", - "BriefDescription": "TM Store (fav or non-fav) caused another thread to fail", - "PublicDescription": "" - }, - {, - "EventCode": "0x737088", - "EventName": "PM_TM_ST_CONF", - "BriefDescription": "TM Store (fav or non-fav) ran into conflict (failed)", - "PublicDescription": "" - }, {, "EventCode": "0x20bc", "EventName": "PM_TM_TBEGIN",
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 10/44 perf tools: Add doc about how to build perf with Asan and UBSan
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
AddressSanitizer (or ASan) and UndefinedBehaviorSanitizer (or UBSan) are very useful tools to detect program bugs:
- AddressSanitizer (or ASan) is a GCC feature that detects memory corruption bugs such as buffer overflows and memory leaks.
- UndefinedBehaviorSanitizer (or UBSan) is a fast undefined behavior detector supported by GCC. UBSan detects undefined behaviors of programs at runtime.
This patch adds a document about how to use them on perf. Later patches will fix some of the issues disclosed by them.
--- tools/perf/Documentation/Build.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
tools/perf/Documentation/Build.txt +24 -0
@@ -47,3 +47,27 @@ Those objects are then used in final linking: NOTE this description is omitting other libraries involved, only focusing on build framework outcomes + +3) Build with ASan or UBSan +========================== + $ cd tools/perf + $ make DESTDIR=/usr + $ make DESTDIR=/usr install + +AddressSanitizer (or ASan) is a GCC feature that detects memory corruption bugs +such as buffer overflows and memory leaks. + + $ cd tools/perf + $ make DEBUG=1 EXTRA_CFLAGS='-fno-omit-frame-pointer -fsanitize=address' + $ ASAN_OPTIONS=log_path=asan.log ./perf record -a + +ASan outputs all detected issues into a log file named 'asan.log.<pid>'. + +UndefinedBehaviorSanitizer (or UBSan) is a fast undefined behavior detector +supported by GCC. UBSan detects undefined behaviors of programs at runtime. + + $ cd tools/perf + $ make DEBUG=1 EXTRA_CFLAGS='-fno-omit-frame-pointer -fsanitize=undefined' + $ UBSAN_OPTIONS=print_stacktrace=1 ./perf record -a + +If UBSan detects any problem at runtime, it outputs a “runtime error:” message.
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 11/44 perf list: Don't forget to drop the reference to the allocated thread_map
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
Detected via gcc's ASan:
Direct leak of 2048 byte(s) in 64 object(s) allocated from:
6 #0 0x7f606512e370 in __interceptor_realloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xee370)
7 #1 0x556b0f1d7ddd in thread_map__realloc util/thread_map.c:43
8 #2 0x556b0f1d84c7 in thread_map__new_by_tid util/thread_map.c:85
9 #3 0x556b0f0e045e in is_event_supported util/parse-events.c:2250
10 #4 0x556b0f0e1aa1 in print_hwcache_events util/parse-events.c:2382
11 #5 0x556b0f0e3231 in print_events util/parse-events.c:2514
12 #6 0x556b0ee0a66e in cmd_list /home/changbin/work/linux/tools/perf/builtin-list.c:58
13 #7 0x556b0f01e0ae in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
14 #8 0x556b0f01e859 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
15 #9 0x556b0f01edc8 in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
16 #10 0x556b0f01f71f in main /home/changbin/work/linux/tools/perf/perf.c:520
17 #11 0x7f6062ccf09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)--- tools/perf/util/parse-events.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/parse-events.c +1 -0
@@ -2271,6 +2271,7 @@ static bool is_event_supported(u8 type, unsigned config)perf_evsel__delete (evsel); } +thread_map__put (tmap);return ret; }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 12/44 perf tools: Fix errors under optimization level '-Og'
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
Optimization level '-Og' offers a reasonable level of optimization while maintaining fast compilation and a good debugging experience. This patch tries to make it work.
$ make DEBUG=1 EXTRA_CFLAGS='-Og'
bench/epoll-ctl.c: In function ‘do_threads’:
bench/epoll-ctl.c:274:9: error: ‘ret’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
return ret;
^~~
...--- tools/lib/bpf/libbpf.c | 2 +- tools/perf/bench/epoll-ctl.c | 2 +- tools/perf/bench/epoll-wait.c | 2 +- tools/perf/tests/backward-ring-buffer.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-)
tools/lib/bpf/libbpf.c +1 -1
@@ -622,7 +622,7 @@ bpf_object__init_maps(struct bpf_object *obj, int flags)bool strict = !(flags &MAPS_RELAX_COMPAT );int i, map_idx, map_def_sz, nr_maps =0 ;Elf_Scn *scn; -Elf_Data *data; +Elf_Data *data =NULL ;Elf_Data *symbols = obj->efile.symbols;if (obj->efile.maps_shndx <0 )
tools/perf/bench/epoll-ctl.c +1 -1
@@ -224,7 +224,7 @@ static int do_threads(struct worker *worker, struct cpu_map *cpu)pthread_attr_t thread_attr, *attrp =NULL ;cpu_set_t cpuset;unsigned int i, j; -int ret; +int ret =0 ;if (!noaffinity)pthread_attr_init (&thread_attr);
tools/perf/bench/epoll-wait.c +1 -1
@@ -293,7 +293,7 @@ static int do_threads(struct worker *worker, struct cpu_map *cpu)pthread_attr_t thread_attr, *attrp =NULL ;cpu_set_t cpuset;unsigned int i, j; -int ret, events =EPOLLIN ; +int ret =0 , events =EPOLLIN ;if (oneshot) events |=EPOLLONESHOT ;
tools/perf/tests/backward-ring-buffer.c +1 -1
@@ -18,7 +18,7 @@ static void testcase(void)int i;for (i =0 ; i <NR_ITERS ; i++) { -char proc_name[10 ]; +char proc_name[15 ];snprintf (proc_name,sizeof (proc_name),"p:%d\n" , i);prctl (PR_SET_NAME , proc_name);
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 13/44 perf config: Fix an error in the config template documentation
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
The option 'sort-order' should be 'sort_order'.
--- tools/perf/Documentation/perf-config.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/Documentation/perf-config.txt +1 -1
@@ -114,7 +114,7 @@ Given a $HOME/.perfconfig like this: [report] # Defaults - sort-order = comm,dso,symbol + sort_order = comm,dso,symbol percent-limit = 0 queue-size = 0 children = true
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 14/44 perf config: Fix a memory leak in collect_config()
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
Detected with gcc's ASan:
Direct leak of 66 byte(s) in 5 object(s) allocated from:
#0 0x7ff3b1f32070 in __interceptor_strdup (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x3b070)
#1 0x560c8761034d in collect_config util/config.c:597
#2 0x560c8760d9cb in get_value util/config.c:169
#3 0x560c8760dfd7 in perf_parse_file util/config.c:285
#4 0x560c8760e0d2 in perf_config_from_file util/config.c:476
#5 0x560c876108fd in perf_config_set__init util/config.c:661
#6 0x560c87610c72 in perf_config_set__new util/config.c:709
#7 0x560c87610d2f in perf_config__init util/config.c:718
#8 0x560c87610e5d in perf_config util/config.c:730
#9 0x560c875ddea0 in main /home/changbin/work/linux/tools/perf/perf.c:442
#10 0x7ff3afb8609a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)--- tools/perf/util/config.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
tools/perf/util/config.c +1 -2
@@ -633,11 +633,10 @@ static int collect_config(const char *var, const char *value, } ret =set_value (item, value); -return ret; out_free:free (key); -return -1 ; +return ret; } int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 15/44 perf build-id: Fix memory leak in print_sdt_events()
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
Detected with gcc's ASan:
Direct leak of 4356 byte(s) in 120 object(s) allocated from:
#0 0x7ff1a2b5a070 in __interceptor_strdup (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x3b070)
#1 0x55719aef4814 in build_id_cache__origname util/build-id.c:215
#2 0x55719af649b6 in print_sdt_events util/parse-events.c:2339
#3 0x55719af66272 in print_events util/parse-events.c:2542
#4 0x55719ad1ecaa in cmd_list /home/changbin/work/linux/tools/perf/builtin-list.c:58
#5 0x55719aec745d in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#6 0x55719aec7d1a in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#7 0x55719aec8184 in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#8 0x55719aeca41a in main /home/changbin/work/linux/tools/perf/perf.c:520
#9 0x7ff1a07ae09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)--- tools/perf/util/build-id.c | 1 + tools/perf/util/parse-events.c | 1 + 2 files changed, 2 insertions(+)
tools/perf/util/build-id.c +1 -0
@@ -185,6 +185,7 @@ char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size)return bf; } +/* The caller is responsible to free the returned buffer. */ char *build_id_cache__origname (const char *sbuild_id) {char *linkname;
tools/perf/util/parse-events.c +1 -0
@@ -2342,6 +2342,7 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,printf (" %-50s [%s]\n" , buf,"SDT event" );free (buf); } +free (path); }else printf (" %-50s [%s]\n" , nd->s,"SDT event" );if (nd2) {
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 16/44 perf top: Delete the evlist before perf_session, fixing heap-use-after-free issue
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
The evlist should be destroyed before the perf session.
Detected with gcc's ASan:
=================================================================
==27350==ERROR: AddressSanitizer: heap-use-after-free on address 0x62b000002e38 at pc 0x5611da276999 bp 0x7ffce8f1d1a0 sp 0x7ffce8f1d190 WRITE of size 8 at 0x62b000002e38 thread T0
#0 0x5611da276998 in __list_del /home/work/linux/tools/include/linux/list.h:89
#1 0x5611da276d4a in __list_del_entry /home/work/linux/tools/include/linux/list.h:102
#2 0x5611da276e77 in list_del_init /home/work/linux/tools/include/linux/list.h:145
#3 0x5611da2781cd in thread__put util/thread.c:130
#4 0x5611da2cc0a8 in __thread__zput util/thread.h:68
#5 0x5611da2d2dcb in hist_entry__delete util/hist.c:1148
#6 0x5611da2cdf91 in hists__delete_entry util/hist.c:337
#7 0x5611da2ce19e in hists__delete_entries util/hist.c:365
#8 0x5611da2db2ab in hists__delete_all_entries util/hist.c:2639
#9 0x5611da2db325 in hists_evsel__exit util/hist.c:2651
#10 0x5611da1c5352 in perf_evsel__exit util/evsel.c:1304
#11 0x5611da1c5390 in perf_evsel__delete util/evsel.c:1309
#12 0x5611da1b35f0 in perf_evlist__purge util/evlist.c:124
#13 0x5611da1b38e2 in perf_evlist__delete util/evlist.c:148
#14 0x5611da069781 in cmd_top /home/changbin/work/linux/tools/perf/builtin-top.c:1645
#15 0x5611da17d038 in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#16 0x5611da17d577 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#17 0x5611da17d97b in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#18 0x5611da17e0e9 in main /home/changbin/work/linux/tools/perf/perf.c:520
#19 0x7fdcc970f09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)
#20 0x5611d9ff35c9 in _start (/home/work/linux/tools/perf/perf+0x3e95c9) 0x62b000002e38 is located 11320 bytes inside of 27448-byte region [0x62b000000200,0x62b000006d38) freed by thread T0 here:
#0 0x7fdccb04ab70 in free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xedb70)
#1 0x5611da260df4 in perf_session__delete util/session.c:201
#2 0x5611da063de5 in __cmd_top /home/changbin/work/linux/tools/perf/builtin-top.c:1300
#3 0x5611da06973c in cmd_top /home/changbin/work/linux/tools/perf/builtin-top.c:1642
#4 0x5611da17d038 in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#5 0x5611da17d577 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#6 0x5611da17d97b in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#7 0x5611da17e0e9 in main /home/changbin/work/linux/tools/perf/perf.c:520
#8 0x7fdcc970f09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)previously allocated by thread T0 here:
#0 0x7fdccb04b138 in calloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xee138)
#1 0x5611da26010c in zalloc util/util.h:23
#2 0x5611da260824 in perf_session__new util/session.c:118
#3 0x5611da0633a6 in __cmd_top /home/changbin/work/linux/tools/perf/builtin-top.c:1192
#4 0x5611da06973c in cmd_top /home/changbin/work/linux/tools/perf/builtin-top.c:1642
#5 0x5611da17d038 in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#6 0x5611da17d577 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#7 0x5611da17d97b in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#8 0x5611da17e0e9 in main /home/changbin/work/linux/tools/perf/perf.c:520
#9 0x7fdcc970f09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a) SUMMARY: AddressSanitizer: heap-use-after-free /home/work/linux/tools/include/linux/list.h:89 in __list_del Shadow bytes around the buggy address:
0x0c567fff8570: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c567fff8580: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c567fff8590: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c567fff85a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c567fff85b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c567fff85c0: fd fd fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd
0x0c567fff85d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c567fff85e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c567fff85f0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c567fff8600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c567fff8610: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==27350==ABORTING
--- tools/perf/builtin-top.c | 42 ++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 23 deletions(-)
tools/perf/builtin-top.c +19 -23
@@ -1189,23 +1189,19 @@ static int __cmd_top(struct perf_top *top)pthread_t thread, thread_process;int ret; - top->session =perf_session__new (NULL , false,NULL ); -if (top->session ==NULL ) -return -1 ; -if (!top->annotation_opts.objdump_path) { ret =perf_env__lookup_objdump (&top->session->header.env, &top->annotation_opts.objdump_path);if (ret) - goto out_delete; +return ret; } ret =callchain_param__setup_sample_type (&callchain_param);if (ret) - goto out_delete; +return ret;if (perf_session__register_idle_thread (top->session) <0 ) - goto out_delete; +return ret;if (top->nr_threads_synthesize >1 )perf_set_multithreaded ();
@@ -1227,13 +1223,18 @@ static int __cmd_top(struct perf_top *top)if (perf_hpp_list.socket) { ret =perf_env__read_cpu_topology_map (&perf_env); -if (ret <0 ) - goto out_err_cpu_topo; +if (ret <0 ) { +char errbuf[BUFSIZ ]; +const char *err =str_error_r (-ret, errbuf,sizeof (errbuf)); + +ui__error ("Could not read the CPU topology map: %s\n" , err); +return ret; + } } ret =perf_top__start_counters (top);if (ret) - goto out_delete; +return ret; top->session->evlist = top->evlist;perf_session__set_id_hdr_size (top->session);
@@ -1252,7 +1253,7 @@ static int __cmd_top(struct perf_top *top) ret =-1 ;if (pthread_create (&thread_process,NULL , process_thread, top)) {ui__error ("Could not create process thread.\n" ); - goto out_delete; +return ret; } if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
@@ -1296,19 +1297,7 @@ static int __cmd_top(struct perf_top *top) out_join_thread:pthread_cond_signal (&top->qe.cond);pthread_join (thread_process,NULL ); -out_delete: -perf_session__delete (top->session); - top->session =NULL ; -return ret; - -out_err_cpu_topo: { -char errbuf[BUFSIZ ]; -const char *err =str_error_r (-ret, errbuf,sizeof (errbuf)); - -ui__error ("Could not read the CPU topology map: %s\n" , err); - goto out_delete; -} } static int
@@ -1639,10 +1628,17 @@ int cmd_top(int argc, const char **argv)signal (SIGWINCH , winch_sig); } + top.session =perf_session__new (NULL , false,NULL ); +if (top.session ==NULL ) { + status =-1 ; + goto out_delete_evlist; + } + status =__cmd_top (&top); out_delete_evlist:perf_evlist__delete (top.evlist); +perf_session__delete (top.session);return status; }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 17/44 perf top: Fix error handling in cmd_top()
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
We should go to the cleanup path, to avoid leaks, detected using gcc's ASan.
--- tools/perf/builtin-top.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
tools/perf/builtin-top.c +3 -2
@@ -1617,8 +1617,9 @@ int cmd_top(int argc, const char **argv)annotation_config__init (); symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name ==NULL ); -if (symbol__init (NULL ) <0 ) -return -1 ; + status =symbol__init (NULL ); +if (status <0 ) + goto out_delete_evlist;sort__setup_elide (stdout);
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 18/44 perf hist: Add missing map__put() in error case
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
We need to map__put() before returning from failure of sample__resolve_callchain().
Detected with gcc's ASan.
--- tools/perf/util/hist.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/hist.c +3 -1
@@ -1111,8 +1111,10 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, err =sample__resolve_callchain (iter->sample, &callchain_cursor, &iter->parent, iter->evsel, al, max_stack_depth); -if (err) +if (err) { +map__put (alm);return err; + } err = iter->ops->prepare_entry (iter, al);if (err)
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 19/44 perf map: Remove map from 'names' tree in __maps__remove()
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
There are two trees for each map inserted by maps__insert(), so remove it from the 'names' tree in __maps__remove().
Detected with gcc's ASan.
--- tools/perf/util/map.c | 3 +++ 1 file changed, 3 insertions(+)
tools/perf/util/map.c +3 -0
@@ -917,6 +917,9 @@ static void __maps__remove(struct maps *maps, struct map *map) {rb_erase_init (&map->rb_node, &maps->entries);map__put (map); + +rb_erase_init (&map->rb_node_name, &maps->names); +map__put (map); }void maps__remove (struct maps *maps,struct map *map)
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 20/44 perf maps: Purge all maps from the 'names' tree
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
Add function __maps__purge_names() to purge all maps from the names tree. We need to cleanup the names tree in maps__exit().
Detected with gcc's ASan.
--- tools/perf/util/map.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
tools/perf/util/map.c +15 -0
@@ -577,10 +577,25 @@ static void __maps__purge(struct maps *maps) } } +static void __maps__purge_names (struct maps *maps) +{ +struct rb_root *root = &maps->names; +struct rb_node *next =rb_first (root); + +while (next) { + struct map *pos = rb_entry(next, struct map, rb_node_name); + + next =rb_next (&pos->rb_node_name); +rb_erase_init (&pos->rb_node_name, root); +map__put (pos); + } +} +static void maps__exit (struct maps *maps) {down_write (&maps->lock);__maps__purge (maps); +__maps__purge_names (maps);up_write (&maps->lock); }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 21/44 perf top: Fix global-buffer-overflow issue
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
The array str[] should have six elements.
=================================================================
==4322==ERROR: AddressSanitizer: global-buffer-overflow on address 0x56463844e300 at pc 0x564637e7ad0d bp 0x7f30c8c89d10 sp 0x7f30c8c89d00 READ of size 8 at 0x56463844e300 thread T9
#0 0x564637e7ad0c in __ordered_events__flush util/ordered-events.c:316
#1 0x564637e7b0e4 in ordered_events__flush util/ordered-events.c:338
#2 0x564637c6a57d in process_thread /home/changbin/work/linux/tools/perf/builtin-top.c:1073
#3 0x7f30d173a163 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x8163)
#4 0x7f30cfffbdee in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x11adee) 0x56463844e300 is located 32 bytes to the left of global variable 'flags' defined in 'util/trace-event-parse.c:229:26' (0x56463844e320) of size 192 0x56463844e300 is located 0 bytes to the right of global variable 'str' defined in 'util/ordered-events.c:268:28' (0x56463844e2e0) of size 32
SUMMARY: AddressSanitizer: global-buffer-overflow util/ordered-events.c:316 in __ordered_events__flush
Shadow bytes around the buggy address:
0x0ac947081c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ac947081c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ac947081c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ac947081c40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ac947081c50: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 00 00 00 00
=>0x0ac947081c60:[f9]f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x0ac947081c70: 00 00 00 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9
0x0ac947081c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ac947081c90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ac947081ca0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ac947081cb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Thread T9 created by T0 here:
#0 0x7f30d179de5f in __interceptor_pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x4ae5f)
#1 0x564637c6b954 in __cmd_top /home/changbin/work/linux/tools/perf/builtin-top.c:1253
#2 0x564637c7173c in cmd_top /home/changbin/work/linux/tools/perf/builtin-top.c:1642
#3 0x564637d85038 in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#4 0x564637d85577 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#5 0x564637d8597b in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#6 0x564637d860e9 in main /home/changbin/work/linux/tools/perf/perf.c:520
#7 0x7f30cff0509a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)--- tools/perf/util/ordered-events.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/util/ordered-events.c +2 -0
@@ -270,6 +270,8 @@ static int __ordered_events__flush(struct ordered_events *oe, enum oe_flush how,"FINAL" ,"ROUND" ,"HALF " , +"TOP " , + "TIME ", };int err;bool show_progress = false;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 22/44 perf evsel: Free evsel->counts in perf_evsel__exit()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Using gcc's ASan, Changbin reports:
=================================================================
==7494==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 48 byte(s) in 1 object(s) allocated from:
#0 0x7f0333a89138 in calloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xee138)
#1 0x5625e5330a5e in zalloc util/util.h:23
#2 0x5625e5330a9b in perf_counts__new util/counts.c:10
#3 0x5625e5330ca0 in perf_evsel__alloc_counts util/counts.c:47
#4 0x5625e520d8e5 in __perf_evsel__read_on_cpu util/evsel.c:1505
#5 0x5625e517a985 in perf_evsel__read_on_cpu /home/work/linux/tools/perf/util/evsel.h:347
#6 0x5625e517ad1a in test__openat_syscall_event tests/openat-syscall.c:47
#7 0x5625e51528e6 in run_test tests/builtin-test.c:358
#8 0x5625e5152baf in test_and_print tests/builtin-test.c:388
#9 0x5625e51543fe in __cmd_test tests/builtin-test.c:583
#10 0x5625e515572f in cmd_test tests/builtin-test.c:722
#11 0x5625e51c3fb8 in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#12 0x5625e51c44f7 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#13 0x5625e51c48fb in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#14 0x5625e51c5069 in main /home/changbin/work/linux/tools/perf/perf.c:520
#15 0x7f033214d09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)Indirect leak of 72 byte(s) in 1 object(s) allocated from:
#0 0x7f0333a89138 in calloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xee138)
#1 0x5625e532560d in zalloc util/util.h:23
#2 0x5625e532566b in xyarray__new util/xyarray.c:10
#3 0x5625e5330aba in perf_counts__new util/counts.c:15
#4 0x5625e5330ca0 in perf_evsel__alloc_counts util/counts.c:47
#5 0x5625e520d8e5 in __perf_evsel__read_on_cpu util/evsel.c:1505
#6 0x5625e517a985 in perf_evsel__read_on_cpu /home/work/linux/tools/perf/util/evsel.h:347
#7 0x5625e517ad1a in test__openat_syscall_event tests/openat-syscall.c:47
#8 0x5625e51528e6 in run_test tests/builtin-test.c:358
#9 0x5625e5152baf in test_and_print tests/builtin-test.c:388
#10 0x5625e51543fe in __cmd_test tests/builtin-test.c:583
#11 0x5625e515572f in cmd_test tests/builtin-test.c:722
#12 0x5625e51c3fb8 in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#13 0x5625e51c44f7 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#14 0x5625e51c48fb in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#15 0x5625e51c5069 in main /home/changbin/work/linux/tools/perf/perf.c:520
#16 0x7f033214d09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)His patch took care of evsel->prev_raw_counts, but the above backtraces are about evsel->counts, so fix that instead.
--- tools/perf/util/evsel.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/evsel.c +1 -0
@@ -1292,6 +1292,7 @@ void perf_evsel__exit(struct perf_evsel *evsel) {assert (list_empty (&evsel->node));assert (evsel->evlist ==NULL ); +perf_evsel__free_counts (evsel);perf_evsel__free_fd (evsel);perf_evsel__free_id (evsel);perf_evsel__free_config_terms (evsel);
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 23/44 perf tests: Fix a memory leak of cpu_map object in the openat_syscall_event_on_all_cpus test
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
=================================================================
==7497==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7f0333a88f30 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xedf30)
#1 0x5625e5326213 in cpu_map__trim_new util/cpumap.c:45
#2 0x5625e5326703 in cpu_map__read util/cpumap.c:103
#3 0x5625e53267ef in cpu_map__read_all_cpu_map util/cpumap.c:120
#4 0x5625e5326915 in cpu_map__new util/cpumap.c:135
#5 0x5625e517b355 in test__openat_syscall_event_on_all_cpus tests/openat-syscall-all-cpus.c:36
#6 0x5625e51528e6 in run_test tests/builtin-test.c:358
#7 0x5625e5152baf in test_and_print tests/builtin-test.c:388
#8 0x5625e51543fe in __cmd_test tests/builtin-test.c:583
#9 0x5625e515572f in cmd_test tests/builtin-test.c:722
#10 0x5625e51c3fb8 in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#11 0x5625e51c44f7 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#12 0x5625e51c48fb in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#13 0x5625e51c5069 in main /home/changbin/work/linux/tools/perf/perf.c:520
#14 0x7f033214d09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)--- tools/perf/tests/openat-syscall-all-cpus.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/tests/openat-syscall-all-cpus.c +3 -1
@@ -45,7 +45,7 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, intif (IS_ERR (evsel)) {tracing_path__strerror_open_tp (errno, errbuf,sizeof (errbuf),"syscalls" ,"sys_enter_openat" );pr_debug ("%s\n" , errbuf); - goto out_thread_map_delete; + goto out_cpu_map_delete; }if (perf_evsel__open (evsel, cpus, threads) <0 ) {
@@ -119,6 +119,8 @@ int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, intperf_evsel__close_fd (evsel); out_evsel_delete:perf_evsel__delete (evsel); +out_cpu_map_delete: +cpu_map__put (cpus); out_thread_map_delete:thread_map__put (threads);return err;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 24/44 perf tests: Fix memory leak by expr__find_other() in test__expr()
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
=================================================================
==7506==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 13 byte(s) in 3 object(s) allocated from:
#0 0x7f03339d6070 in __interceptor_strdup (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x3b070)
#1 0x5625e53aaef0 in expr__find_other util/expr.y:221
#2 0x5625e51bcd3f in test__expr tests/expr.c:52
#3 0x5625e51528e6 in run_test tests/builtin-test.c:358
#4 0x5625e5152baf in test_and_print tests/builtin-test.c:388
#5 0x5625e51543fe in __cmd_test tests/builtin-test.c:583
#6 0x5625e515572f in cmd_test tests/builtin-test.c:722
#7 0x5625e51c3fb8 in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#8 0x5625e51c44f7 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#9 0x5625e51c48fb in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#10 0x5625e51c5069 in main /home/changbin/work/linux/tools/perf/perf.c:520
#11 0x7f033214d09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)--- tools/perf/tests/expr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/perf/tests/expr.c +4 -1
@@ -19,7 +19,7 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)const char *p;const char **other;double val; -int ret; +int i, ret;struct parse_ctx ctx;int num_other;
@@ -56,6 +56,9 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)TEST_ASSERT_VAL ("find other" , !strcmp (other[1 ],"BAZ" ));TEST_ASSERT_VAL ("find other" , !strcmp (other[2 ],"BOZO" ));TEST_ASSERT_VAL ("find other" , other[3 ] ==NULL ); + +for (i =0 ; i < num_other; i++) +free ((void *)other[i]);free ((void *)other);return 0 ;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 25/44 perf tests: Fix a memory leak in test__perf_evsel__tp_sched_test()
In reply to Arnaldo Carvalho de MeloFrom: Changbin Du <[email protected]>
=================================================================
==20875==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1160 byte(s) in 1 object(s) allocated from:
#0 0x7f1b6fc84138 in calloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xee138)
#1 0x55bd50005599 in zalloc util/util.h:23
#2 0x55bd500068f5 in perf_evsel__newtp_idx util/evsel.c:327
#3 0x55bd4ff810fc in perf_evsel__newtp /home/work/linux/tools/perf/util/evsel.h:216
#4 0x55bd4ff81608 in test__perf_evsel__tp_sched_test tests/evsel-tp-sched.c:69
#5 0x55bd4ff528e6 in run_test tests/builtin-test.c:358
#6 0x55bd4ff52baf in test_and_print tests/builtin-test.c:388
#7 0x55bd4ff543fe in __cmd_test tests/builtin-test.c:583
#8 0x55bd4ff5572f in cmd_test tests/builtin-test.c:722
#9 0x55bd4ffc4087 in run_builtin /home/changbin/work/linux/tools/perf/perf.c:302
#10 0x55bd4ffc45c6 in handle_internal_command /home/changbin/work/linux/tools/perf/perf.c:354
#11 0x55bd4ffc49ca in run_argv /home/changbin/work/linux/tools/perf/perf.c:398
#12 0x55bd4ffc5138 in main /home/changbin/work/linux/tools/perf/perf.c:520
#13 0x7f1b6e34809a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a)Indirect leak of 19 byte(s) in 1 object(s) allocated from:
#0 0x7f1b6fc83f30 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0xedf30)
#1 0x7f1b6e3ac30f in vasprintf (/lib/x86_64-linux-gnu/libc.so.6+0x8830f)--- tools/perf/tests/evsel-tp-sched.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/tests/evsel-tp-sched.c +1 -0
@@ -85,5 +85,6 @@ int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtesif (perf_evsel__test_field (evsel,"target_cpu" ,4 , true)) ret =-1 ; +perf_evsel__delete (evsel);return ret; }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 26/44 perf record: Replace option --bpf-event with --no-bpf-event
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
Currently, monitoring of BPF programs through bpf_event is off by default for 'perf record'.
To turn it on, the user need to use option "--bpf-event". As BPF gets wider adoption in different subsystems, this option becomes inconvenient.
This patch makes bpf_event on by default, and adds option "--no-bpf-event" to turn it off. Since option --bpf-event is not released yet, it is safe to remove it.
--- tools/perf/builtin-record.c | 2 +- tools/perf/perf.h | 2 +- tools/perf/util/bpf-event.c | 2 +- tools/perf/util/evsel.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-)
tools/perf/builtin-record.c +1 -1
@@ -1891,7 +1891,7 @@ static struct option __record_options[] = {OPT_BOOLEAN (0 ,"tail-synthesize" , &record.opts.tail_synthesize,"synthesize non-sample events at the end of output" ),OPT_BOOLEAN (0 ,"overwrite" , &record.opts.overwrite,"use overwrite mode" ), -OPT_BOOLEAN (0 ,"bpf-event" , &record.opts.bpf_event,"record bpf events" ), +OPT_BOOLEAN (0 ,"no-bpf-event" , &record.opts.no_bpf_event,"record bpf events" ),OPT_BOOLEAN (0 ,"strict-freq" , &record.opts.strict_freq,"Fail if the specified frequency can't be used" ), OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
tools/perf/perf.h +1 -1
@@ -66,7 +66,7 @@ struct record_opts {bool ignore_missing_thread;bool strict_freq;bool sample_id; -bool bpf_event; +bool no_bpf_event;unsigned int freq;unsigned int mmap_pages;unsigned int auxtrace_mmap_pages;
tools/perf/util/bpf-event.c +1 -1
@@ -187,7 +187,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, }/* Synthesize PERF_RECORD_BPF_EVENT */ -if (opts->bpf_event) { +if (!opts->no_bpf_event) { *bpf_event = (struct bpf_event ){ .header = { .type =PERF_RECORD_BPF_EVENT ,
tools/perf/util/evsel.c +1 -1
@@ -1036,7 +1036,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, attr->mmap2 = track && !perf_missing_features.mmap2; attr->comm = track; attr->ksymbol = track && !perf_missing_features.ksymbol; - attr->bpf_event = track && opts->bpf_event && + attr->bpf_event = track && !opts->no_bpf_event && !perf_missing_features.bpf_event;if (opts->record_namespaces)
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 27/44 tools lib bpf: Introduce bpf_program__get_prog_info_linear()
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
Currently, bpf_prog_info includes 9 arrays. The user has the option to fetch any combination of these arrays. However, this requires a lot of handling.
This work becomes more tricky when we need to store bpf_prog_info to a file, because these arrays are allocated independently.
This patch introduces 'struct bpf_prog_info_linear', which stores arrays of bpf_prog_info in continuous memory.
Helper functions are introduced to unify the work to get different sets of bpf_prog_info. Specifically, bpf_program__get_prog_info_linear() allows the user to select which arrays to fetch, and handles details for the user.
Please see the comments right before 'enum bpf_prog_info_array' for more details and examples.
--- tools/lib/bpf/libbpf.c | 251 +++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 63 ++++++++++ tools/lib/bpf/libbpf.map | 3 + 3 files changed, 317 insertions(+)
tools/lib/bpf/libbpf.c +251 -0
@@ -112,6 +112,11 @@ void libbpf_print(enum libbpf_print_level level, const char *format, ...)# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ#endif +static inline __u64 ptr_to_u64 (const void *ptr) +{ +return (__u64 ) (unsigned long ) ptr; +} +struct bpf_capabilities {/* v4.14: kernel support for program & map names. */ __u32 name:1 ;
@@ -2997,3 +3002,249 @@ bpf_perf_event_read_simple(void *mmap_mem, size_t mmap_size, size_t page_size,ring_buffer_write_tail (header, data_tail);return ret; } + +struct bpf_prog_info_array_desc { +int array_offset;/* e.g. offset of jited_prog_insns */ +int count_offset;/* e.g. offset of jited_prog_len */ +int size_offset;/* > 0: offset of rec size, +* < 0: fix size of -size_offset +*/ +}; + +static struct bpf_prog_info_array_desc bpf_prog_info_array_desc[] = { + [BPF_PROG_INFO_JITED_INSNS ] = { + offsetof(struct bpf_prog_info , jited_prog_insns), + offsetof(struct bpf_prog_info , jited_prog_len), +-1 , + }, + [BPF_PROG_INFO_XLATED_INSNS ] = { + offsetof(struct bpf_prog_info , xlated_prog_insns), + offsetof(struct bpf_prog_info , xlated_prog_len), +-1 , + }, + [BPF_PROG_INFO_MAP_IDS ] = { + offsetof(struct bpf_prog_info , map_ids), + offsetof(struct bpf_prog_info , nr_map_ids), + -(int )sizeof (__u32), + }, + [BPF_PROG_INFO_JITED_KSYMS ] = { + offsetof(struct bpf_prog_info , jited_ksyms), + offsetof(struct bpf_prog_info , nr_jited_ksyms), + -(int )sizeof (__u64), + }, + [BPF_PROG_INFO_JITED_FUNC_LENS ] = { + offsetof(struct bpf_prog_info , jited_func_lens), + offsetof(struct bpf_prog_info , nr_jited_func_lens), + -(int )sizeof (__u32), + }, + [BPF_PROG_INFO_FUNC_INFO ] = { + offsetof(struct bpf_prog_info , func_info), + offsetof(struct bpf_prog_info , nr_func_info), + offsetof(struct bpf_prog_info , func_info_rec_size), + }, + [BPF_PROG_INFO_LINE_INFO ] = { + offsetof(struct bpf_prog_info , line_info), + offsetof(struct bpf_prog_info , nr_line_info), + offsetof(struct bpf_prog_info , line_info_rec_size), + }, + [BPF_PROG_INFO_JITED_LINE_INFO ] = { + offsetof(struct bpf_prog_info , jited_line_info), + offsetof(struct bpf_prog_info , nr_jited_line_info), + offsetof(struct bpf_prog_info , jited_line_info_rec_size), + }, + [BPF_PROG_INFO_PROG_TAGS ] = { + offsetof(struct bpf_prog_info , prog_tags), + offsetof(struct bpf_prog_info , nr_prog_tags), + -(int )sizeof (__u8) *BPF_TAG_SIZE , + }, + +}; + +static __u32 bpf_prog_info_read_offset_u32 (struct bpf_prog_info *info,int offset) +{ +__u32 *array = (__u32 *)info; + +if (offset >=0 ) +return array[offset /sizeof (__u32)]; +return -(int )offset; +} + +static __u64 bpf_prog_info_read_offset_u64 (struct bpf_prog_info *info,int offset) +{ +__u64 *array = (__u64 *)info; + +if (offset >=0 ) +return array[offset /sizeof (__u64)]; +return -(int )offset; +} + +static void bpf_prog_info_set_offset_u32 (struct bpf_prog_info *info,int offset, +__u32 val) +{ +__u32 *array = (__u32 *)info; + +if (offset >=0 ) + array[offset /sizeof (__u32)] = val; +} + +static void bpf_prog_info_set_offset_u64 (struct bpf_prog_info *info,int offset, +__u64 val) +{ +__u64 *array = (__u64 *)info; + +if (offset >=0 ) + array[offset /sizeof (__u64)] = val; +} + +struct bpf_prog_info_linear * +bpf_program__get_prog_info_linear (int fd,__u64 arrays) +{ +struct bpf_prog_info_linear *info_linear; +struct bpf_prog_info info = {}; +__u32 info_len =sizeof (info); +__u32 data_len =0 ; +int i, err; +void *ptr; + +if (arrays >>BPF_PROG_INFO_LAST_ARRAY ) +return ERR_PTR (-EINVAL ); + +/* step 1: get array dimensions */ + err =bpf_obj_get_info_by_fd (fd, &info, &info_len); +if (err) { +pr_debug ("can't get prog info: %s" ,strerror (errno)); +return ERR_PTR (-EFAULT ); + } + +/* step 2: calculate total size of all arrays */ +for (i =BPF_PROG_INFO_FIRST_ARRAY ; i <BPF_PROG_INFO_LAST_ARRAY ; ++i) { +bool include_array = (arrays & (1UL << i)) >0 ; +struct bpf_prog_info_array_desc *desc; +__u32 count, size; + + desc = bpf_prog_info_array_desc + i; + +/* kernel is too old to support this field */ +if (info_len < desc->array_offset +sizeof (__u32) || + info_len < desc->count_offset +sizeof (__u32) || + (desc->size_offset >0 && info_len < desc->size_offset)) + include_array = false; + +if (!include_array) { + arrays &= ~(1UL << i);/* clear the bit */ +continue ; + } + + count =bpf_prog_info_read_offset_u32 (&info, desc->count_offset); + size =bpf_prog_info_read_offset_u32 (&info, desc->size_offset); + + data_len += count * size; + } + +/* step 3: allocate continuous memory */ + data_len =roundup (data_len,sizeof (__u64)); + info_linear =malloc (sizeof (struct bpf_prog_info_linear ) + data_len); +if (!info_linear) +return ERR_PTR (-ENOMEM ); + +/* step 4: fill data to info_linear->info */ + info_linear->arrays = arrays; +memset (&info_linear->info,0 ,sizeof (info)); + ptr = info_linear->data; + +for (i =BPF_PROG_INFO_FIRST_ARRAY ; i <BPF_PROG_INFO_LAST_ARRAY ; ++i) { +struct bpf_prog_info_array_desc *desc; +__u32 count, size; + +if ((arrays & (1UL << i)) ==0 ) +continue ; + + desc = bpf_prog_info_array_desc + i; + count =bpf_prog_info_read_offset_u32 (&info, desc->count_offset); + size =bpf_prog_info_read_offset_u32 (&info, desc->size_offset); +bpf_prog_info_set_offset_u32 (&info_linear->info, + desc->count_offset, count); +bpf_prog_info_set_offset_u32 (&info_linear->info, + desc->size_offset, size); +bpf_prog_info_set_offset_u64 (&info_linear->info, + desc->array_offset, +ptr_to_u64 (ptr)); + ptr += count * size; + } + +/* step 5: call syscall again to get required arrays */ + err =bpf_obj_get_info_by_fd (fd, &info_linear->info, &info_len); +if (err) { +pr_debug ("can't get prog info: %s" ,strerror (errno)); +free (info_linear); +return ERR_PTR (-EFAULT ); + } + +/* step 6: verify the data */ +for (i =BPF_PROG_INFO_FIRST_ARRAY ; i <BPF_PROG_INFO_LAST_ARRAY ; ++i) { +struct bpf_prog_info_array_desc *desc; +__u32 v1, v2; + +if ((arrays & (1UL << i)) ==0 ) +continue ; + + desc = bpf_prog_info_array_desc + i; + v1 =bpf_prog_info_read_offset_u32 (&info, desc->count_offset); + v2 =bpf_prog_info_read_offset_u32 (&info_linear->info, + desc->count_offset); +if (v1 != v2) +pr_warning ("%s: mismatch in element count\n" , __func__); + + v1 =bpf_prog_info_read_offset_u32 (&info, desc->size_offset); + v2 =bpf_prog_info_read_offset_u32 (&info_linear->info, + desc->size_offset); +if (v1 != v2) +pr_warning ("%s: mismatch in rec size\n" , __func__); + } + +/* step 7: update info_len and data_len */ + info_linear->info_len =sizeof (struct bpf_prog_info ); + info_linear->data_len = data_len; + +return info_linear; +} + +void bpf_program__bpil_addr_to_offs (struct bpf_prog_info_linear *info_linear) +{ +int i; + +for (i =BPF_PROG_INFO_FIRST_ARRAY ; i <BPF_PROG_INFO_LAST_ARRAY ; ++i) { +struct bpf_prog_info_array_desc *desc; +__u64 addr, offs; + +if ((info_linear->arrays & (1UL << i)) ==0 ) +continue ; + + desc = bpf_prog_info_array_desc + i; + addr =bpf_prog_info_read_offset_u64 (&info_linear->info, + desc->array_offset); + offs = addr -ptr_to_u64 (info_linear->data); +bpf_prog_info_set_offset_u64 (&info_linear->info, + desc->array_offset, offs); + } +} + +void bpf_program__bpil_offs_to_addr (struct bpf_prog_info_linear *info_linear) +{ +int i; + +for (i =BPF_PROG_INFO_FIRST_ARRAY ; i <BPF_PROG_INFO_LAST_ARRAY ; ++i) { +struct bpf_prog_info_array_desc *desc; +__u64 addr, offs; + +if ((info_linear->arrays & (1UL << i)) ==0 ) +continue ; + + desc = bpf_prog_info_array_desc + i; + offs =bpf_prog_info_read_offset_u64 (&info_linear->info, + desc->array_offset); + addr = offs +ptr_to_u64 (info_linear->data); +bpf_prog_info_set_offset_u64 (&info_linear->info, + desc->array_offset, addr); + } +}
tools/lib/bpf/libbpf.h +63 -0
69 lines not on this page · raw message
tools/lib/bpf/libbpf.map +3 -0
@@ -153,4 +153,7 @@ LIBBPF_0.0.2 { xsk_socket__delete; xsk_umem__fd; xsk_socket__fd; + bpf_program__get_prog_info_linear; + bpf_program__bpil_addr_to_offs; + bpf_program__bpil_offs_to_addr; } LIBBPF_0.0.1;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 28/44 bpftool: use bpf_program__get_prog_info_linear() in prog.c:do_dump()
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
This patches uses bpf_program__get_prog_info_linear() to simplify the logic in prog.c do_dump().
Committer testing:
Before:
# bpftool prog dump xlated id 208 > /tmp/dump.xlated.before # bpftool prog dump jited id 208 > /tmp/dump.jited.before # bpftool map dump id 107 > /tmp/map.dump.before
After:
# ~acme/git/perf/tools/bpf/bpftool/bpftool map dump id 107 > /tmp/map.dump.after # ~acme/git/perf/tools/bpf/bpftool/bpftool prog dump xlated id 208 > /tmp/dump.xlated.after # ~acme/git/perf/tools/bpf/bpftool/bpftool prog dump jited id 208 > /tmp/dump.jited.after
# diff -u /tmp/dump.xlated.before /tmp/dump.xlated.after
# diff -u /tmp/dump.jited.before /tmp/dump.jited.after
# diff -u /tmp/map.dump.before /tmp/map.dump.after
# ~acme/git/perf/tools/bpf/bpftool/bpftool prog dump xlated id 208
0: (bf) r6 = r1
1: (85) call bpf_get_current_pid_tgid#80800
2: (63) *(u32 *)(r10 -328) = r0
3: (bf) r2 = r10
4: (07) r2 += -328
5: (18) r1 = map[id:107]
7: (85) call __htab_map_lookup_elem#85680
8: (15) if r0 == 0x0 goto pc+1
9: (07) r0 += 56
10: (b7) r7 = 0
11: (55) if r0 != 0x0 goto pc+52
12: (bf) r1 = r10
13: (07) r1 += -328
14: (b7) r2 = 64
15: (bf) r3 = r6
16: (85) call bpf_probe_read#-46848
17: (bf) r2 = r10
18: (07) r2 += -320
19: (18) r1 = map[id:106]
21: (07) r1 += 208
22: (61) r0 = *(u32 *)(r2 +0)
23: (35) if r0 >= 0x200 goto pc+3
24: (67) r0 <<= 3
25: (0f) r0 += r1
26: (05) goto pc+1
27: (b7) r0 = 0
28: (15) if r0 == 0x0 goto pc+35
29: (71) r1 = *(u8 *)(r0 +0)
30: (15) if r1 == 0x0 goto pc+33
31: (b7) r5 = 64
32: (79) r1 = *(u64 *)(r10 -320)
33: (15) if r1 == 0x2 goto pc+2
34: (15) if r1 == 0x101 goto pc+3
35: (55) if r1 != 0x15 goto pc+19
36: (79) r3 = *(u64 *)(r6 +16)
37: (05) goto pc+1
38: (79) r3 = *(u64 *)(r6 +24)
39: (15) if r3 == 0x0 goto pc+15
40: (b7) r1 = 0
41: (63) *(u32 *)(r10 -260) = r1
42: (bf) r1 = r10
43: (07) r1 += -256
44: (b7) r2 = 256
45: (85) call bpf_probe_read_str#-46704
46: (b7) r5 = 328
47: (63) *(u32 *)(r10 -264) = r0
48: (bf) r1 = r0
49: (67) r1 <<= 32
50: (77) r1 >>= 32
51: (25) if r1 > 0xff goto pc+3
52: (07) r0 += 72
53: (57) r0 &= 255
54: (bf) r5 = r0
55: (bf) r4 = r10
56: (07) r4 += -328
57: (bf) r1 = r6
58: (18) r2 = map[id:105]
60: (18) r3 = 0xffffffff
62: (85) call bpf_perf_event_output_tp#-45104
63: (bf) r7 = r0
64: (bf) r0 = r7
65: (95) exit
#--- tools/bpf/bpftool/prog.c | 266 +++++++++------------------------------ 1 file changed, 59 insertions(+), 207 deletions(-)
tools/bpf/bpftool/prog.c +59 -207
@@ -401,41 +401,31 @@ static int do_show(int argc, char **argv)static int do_dump (int argc,char **argv) { -unsigned int finfo_rec_size, linfo_rec_size, jited_linfo_rec_size; -void *func_info =NULL , *linfo =NULL , *jited_linfo =NULL ; -unsigned int nr_finfo, nr_linfo =0 , nr_jited_linfo =0 ; +struct bpf_prog_info_linear *info_linear;struct bpf_prog_linfo *prog_linfo =NULL ; -unsigned long *func_ksyms =NULL ; -struct bpf_prog_info info = {}; -unsigned int *func_lens =NULL ; +enum {DUMP_JITED ,DUMP_XLATED } mode;const char *disasm_opt =NULL ; -unsigned int nr_func_ksyms; -unsigned int nr_func_lens; +struct bpf_prog_info *info;struct dump_data dd = {}; -__u32 len =sizeof (info); +void *func_info =NULL ;struct btf *btf =NULL ; -unsigned int buf_size;char *filepath =NULL ;bool opcodes = false;bool visual = false;char func_sig[1024 ];unsigned char *buf;bool linum = false; -__u32 *member_len; -__u64 *member_ptr; +__u32 member_len; +__u64 arrays;ssize_t n; -int err;int fd;if (is_prefix (*argv,"jited" )) {if (disasm_init ())return -1 ; - - member_len = &info.jited_prog_len; - member_ptr = &info.jited_prog_insns; + mode =DUMP_JITED ; }else if (is_prefix (*argv,"xlated" )) { - member_len = &info.xlated_prog_len; - member_ptr = &info.xlated_prog_insns; + mode =DUMP_XLATED ; }else {p_err ("expected 'xlated' or 'jited', got: %s" , *argv);return -1 ;
@@ -474,175 +464,50 @@ static int do_dump(int argc, char **argv)return -1 ; } - err =bpf_obj_get_info_by_fd (fd, &info, &len); -if (err) { -p_err ("can't get prog info: %s" ,strerror (errno)); -return -1 ; - } - -if (!*member_len) { -p_info ("no instructions returned" ); -close (fd); -return 0 ; - } +if (mode ==DUMP_JITED ) + arrays =1UL <<BPF_PROG_INFO_JITED_INSNS ; +else + arrays =1UL <<BPF_PROG_INFO_XLATED_INSNS ; - buf_size = *member_len; + arrays |=1UL <<BPF_PROG_INFO_JITED_KSYMS ; + arrays |=1UL <<BPF_PROG_INFO_JITED_FUNC_LENS ; + arrays |=1UL <<BPF_PROG_INFO_FUNC_INFO ; + arrays |=1UL <<BPF_PROG_INFO_LINE_INFO ; + arrays |=1UL <<BPF_PROG_INFO_JITED_LINE_INFO ; - buf =malloc (buf_size); -if (!buf) { -p_err ("mem alloc failed" ); -close (fd); + info_linear =bpf_program__get_prog_info_linear (fd, arrays); +close (fd); +if (IS_ERR_OR_NULL (info_linear)) { +p_err ("can't get prog info: %s" ,strerror (errno));return -1 ; } - nr_func_ksyms = info.nr_jited_ksyms; -if (nr_func_ksyms) { - func_ksyms =malloc (nr_func_ksyms *sizeof (__u64)); -if (!func_ksyms) { -p_err ("mem alloc failed" ); -close (fd); - goto err_free; - } - } - - nr_func_lens = info.nr_jited_func_lens; -if (nr_func_lens) { - func_lens =malloc (nr_func_lens *sizeof (__u32)); -if (!func_lens) { -p_err ("mem alloc failed" ); -close (fd); + info = &info_linear->info; +if (mode ==DUMP_JITED ) { +if (info->jited_prog_len ==0 ) { +p_info ("no instructions returned" ); goto err_free; } - } - - nr_finfo = info.nr_func_info; - finfo_rec_size = info.func_info_rec_size; -if (nr_finfo && finfo_rec_size) { - func_info =malloc (nr_finfo * finfo_rec_size); -if (!func_info) { -p_err ("mem alloc failed" ); -close (fd); + buf = (unsigned char *)(info->jited_prog_insns); + member_len = info->jited_prog_len; + }else {/* DUMP_XLATED */ +if (info->xlated_prog_len ==0 ) { +p_err ("error retrieving insn dump: kernel.kptr_restrict set?" ); goto err_free; } + buf = (unsigned char *)info->xlated_prog_insns; + member_len = info->xlated_prog_len; } - linfo_rec_size = info.line_info_rec_size; -if (info.nr_line_info && linfo_rec_size && info.btf_id) { - nr_linfo = info.nr_line_info; - linfo =malloc (nr_linfo * linfo_rec_size); -if (!linfo) { -p_err ("mem alloc failed" ); -close (fd); - goto err_free; - } - } - - jited_linfo_rec_size = info.jited_line_info_rec_size; -if (info.nr_jited_line_info && - jited_linfo_rec_size && - info.nr_jited_ksyms && - info.nr_jited_func_lens && - info.btf_id) { - nr_jited_linfo = info.nr_jited_line_info; - jited_linfo =malloc (nr_jited_linfo * jited_linfo_rec_size); -if (!jited_linfo) { -p_err ("mem alloc failed" ); -close (fd); - goto err_free; - } - } - -memset (&info,0 ,sizeof (info)); - - *member_ptr =ptr_to_u64 (buf); - *member_len = buf_size; - info.jited_ksyms =ptr_to_u64 (func_ksyms); - info.nr_jited_ksyms = nr_func_ksyms; - info.jited_func_lens =ptr_to_u64 (func_lens); - info.nr_jited_func_lens = nr_func_lens; - info.nr_func_info = nr_finfo; - info.func_info_rec_size = finfo_rec_size; - info.func_info =ptr_to_u64 (func_info); - info.nr_line_info = nr_linfo; - info.line_info_rec_size = linfo_rec_size; - info.line_info =ptr_to_u64 (linfo); - info.nr_jited_line_info = nr_jited_linfo; - info.jited_line_info_rec_size = jited_linfo_rec_size; - info.jited_line_info =ptr_to_u64 (jited_linfo); - - err =bpf_obj_get_info_by_fd (fd, &info, &len); -close (fd); -if (err) { -p_err ("can't get prog info: %s" ,strerror (errno)); - goto err_free; - } - -if (*member_len > buf_size) { -p_err ("too many instructions returned" ); - goto err_free; - } - -if (info.nr_jited_ksyms > nr_func_ksyms) { -p_err ("too many addresses returned" ); - goto err_free; - } - -if (info.nr_jited_func_lens > nr_func_lens) { -p_err ("too many values returned" ); - goto err_free; - } - -if (info.nr_func_info != nr_finfo) { -p_err ("incorrect nr_func_info %d vs. expected %d" , - info.nr_func_info, nr_finfo); - goto err_free; - } - -if (info.func_info_rec_size != finfo_rec_size) { -p_err ("incorrect func_info_rec_size %d vs. expected %d" , - info.func_info_rec_size, finfo_rec_size); - goto err_free; - } - -if (linfo && info.nr_line_info != nr_linfo) { -p_err ("incorrect nr_line_info %u vs. expected %u" , - info.nr_line_info, nr_linfo); - goto err_free; - } - -if (info.line_info_rec_size != linfo_rec_size) { -p_err ("incorrect line_info_rec_size %u vs. expected %u" , - info.line_info_rec_size, linfo_rec_size); - goto err_free; - } - -if (jited_linfo && info.nr_jited_line_info != nr_jited_linfo) { -p_err ("incorrect nr_jited_line_info %u vs. expected %u" , - info.nr_jited_line_info, nr_jited_linfo); - goto err_free; - } - -if (info.jited_line_info_rec_size != jited_linfo_rec_size) { -p_err ("incorrect jited_line_info_rec_size %u vs. expected %u" , - info.jited_line_info_rec_size, jited_linfo_rec_size); - goto err_free; - } - -if ((member_len == &info.jited_prog_len && - info.jited_prog_insns ==0 ) || - (member_len == &info.xlated_prog_len && - info.xlated_prog_insns ==0 )) { -p_err ("error retrieving insn dump: kernel.kptr_restrict set?" ); - goto err_free; - } - -if (info.btf_id &&btf__get_from_id (info.btf_id, &btf)) { +if (info->btf_id &&btf__get_from_id (info->btf_id, &btf)) {p_err ("failed to get btf" ); goto err_free; } -if (nr_linfo) { - prog_linfo =bpf_prog_linfo__new (&info); + func_info = (void *)info->func_info; + +if (info->nr_line_info) { + prog_linfo =bpf_prog_linfo__new (info);if (!prog_linfo)p_info ("error in processing bpf_line_info. continue without it." ); }
@@ -655,9 +520,9 @@ static int do_dump(int argc, char **argv) goto err_free; } - n =write (fd, buf, *member_len); + n =write (fd, buf, member_len);close (fd); -if (n != *member_len) { +if (n != member_len) {p_err ("error writing output file: %s" , n <0 ?strerror (errno) :"short write" ); goto err_free;
@@ -665,19 +530,19 @@ static int do_dump(int argc, char **argv)if (json_output)jsonw_null (json_wtr); - }else if (member_len == &info.jited_prog_len) { + }else if (mode ==DUMP_JITED ) {const char *name =NULL ; -if (info.ifindex) { - name =ifindex_to_bfd_params (info.ifindex, - info.netns_dev, - info.netns_ino, +if (info->ifindex) { + name =ifindex_to_bfd_params (info->ifindex, + info->netns_dev, + info->netns_ino, &disasm_opt);if (!name) goto err_free; } -if (info.nr_jited_func_lens && info.jited_func_lens) { +if (info->nr_jited_func_lens && info->jited_func_lens) {struct kernel_sym *sym =NULL ;struct bpf_func_info *record;char sym_name[SYM_MAX_NAME ];
@@ -685,17 +550,16 @@ static int do_dump(int argc, char **argv)__u64 *ksyms =NULL ;__u32 *lens;__u32 i; - -if (info.nr_jited_ksyms) { +if (info->nr_jited_ksyms) {kernel_syms_load (&dd); - ksyms = (__u64 *) info.jited_ksyms; + ksyms = (__u64 *) info->jited_ksyms; }if (json_output)jsonw_start_array (json_wtr); - lens = (__u32 *) info.jited_func_lens; -for (i =0 ; i < info.nr_jited_func_lens; i++) { + lens = (__u32 *) info->jited_func_lens; +for (i =0 ; i < info->nr_jited_func_lens; i++) {if (ksyms) { sym =kernel_syms_search (&dd, ksyms[i]);if (sym)
@@ -707,7 +571,7 @@ static int do_dump(int argc, char **argv) }if (func_info) { - record = func_info + i * finfo_rec_size; + record = func_info + i * info->func_info_rec_size;btf_dumper_type_only (btf, record->type_id, func_sig,sizeof (func_sig));
@@ -744,49 +608,37 @@ static int do_dump(int argc, char **argv)if (json_output)jsonw_end_array (json_wtr); }else { -disasm_print_insn (buf, *member_len, opcodes, name, +disasm_print_insn (buf, member_len, opcodes, name, disasm_opt, btf,NULL ,0 ,0 , false); } }else if (visual) {if (json_output)jsonw_null (json_wtr);else -dump_xlated_cfg (buf, *member_len); +dump_xlated_cfg (buf, member_len); }else {kernel_syms_load (&dd); - dd.nr_jited_ksyms = info.nr_jited_ksyms; - dd.jited_ksyms = (__u64 *) info.jited_ksyms; + dd.nr_jited_ksyms = info->nr_jited_ksyms; + dd.jited_ksyms = (__u64 *) info->jited_ksyms; dd.btf = btf; dd.func_info = func_info; - dd.finfo_rec_size = finfo_rec_size; + dd.finfo_rec_size = info->func_info_rec_size; dd.prog_linfo = prog_linfo;if (json_output) -dump_xlated_json (&dd, buf, *member_len, opcodes, +dump_xlated_json (&dd, buf, member_len, opcodes, linum);else -dump_xlated_plain (&dd, buf, *member_len, opcodes, +dump_xlated_plain (&dd, buf, member_len, opcodes, linum);kernel_syms_destroy (&dd); } -free (buf); -free (func_ksyms); -free (func_lens); -free (func_info); -free (linfo); -free (jited_linfo); -bpf_prog_linfo__free (prog_linfo); +free (info_linear);return 0 ; err_free: -free (buf); -free (func_ksyms); -free (func_lens); -free (func_info); -free (linfo); -free (jited_linfo); -bpf_prog_linfo__free (prog_linfo); +free (info_linear);return -1 ; }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 29/44 perf bpf: Synthesize bpf events with bpf_program__get_prog_info_linear()
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
With bpf_program__get_prog_info_linear, we can simplify the logic that synthesizes bpf events.
This patch doesn't change the behavior of the code.
Commiter notes:
Needed this (for all four variables), suggested by Song, to overcome build failure on debian experimental cross building to MIPS 32-bit:
- u8 (*prog_tags)[BPF_TAG_SIZE] = (void *)(info->prog_tags);
+ u8 (*prog_tags)[BPF_TAG_SIZE] = (void *)(uintptr_t)(info->prog_tags);
util/bpf-event.c: In function 'perf_event__synthesize_one_bpf_prog':
util/bpf-event.c:143:35: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
u8 (*prog_tags)[BPF_TAG_SIZE] = (void *)(info->prog_tags);
^
util/bpf-event.c:144:22: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
__u32 *prog_lens = (__u32 *)(info->jited_func_lens);
^
util/bpf-event.c:145:23: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
__u64 *prog_addrs = (__u64 *)(info->jited_ksyms);
^
util/bpf-event.c:146:22: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
void *func_infos = (void *)(info->func_info);
^cc1: all warnings being treated as errors
--- tools/perf/util/bpf-event.c | 118 ++++++++++++------------------------ 1 file changed, 40 insertions(+), 78 deletions(-)
tools/perf/util/bpf-event.c +40 -78
@@ -3,7 +3,9 @@#include <stdlib.h> #include <bpf/bpf.h> #include <bpf/btf.h> +#include <bpf/libbpf.h> #include <linux/btf.h> +#include <linux/err.h> #include "bpf-event.h" #include "debug.h" #include "symbol.h"
@@ -49,99 +51,62 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, {struct ksymbol_event *ksymbol_event = &event->ksymbol_event;struct bpf_event *bpf_event = &event->bpf_event; -u32 sub_prog_cnt, i, func_info_rec_size =0 ; -u8 (*prog_tags)[BPF_TAG_SIZE ] =NULL ; -struct bpf_prog_info info = { .type =0 , }; -u32 info_len =sizeof (info); -void *func_infos =NULL ; -u64 *prog_addrs =NULL ; +struct bpf_prog_info_linear *info_linear; +struct bpf_prog_info *info;struct btf *btf =NULL ; -u32 *prog_lens =NULL ;bool has_btf = false; -char errbuf[512 ]; +u32 sub_prog_cnt, i;int err =0 ; +u64 arrays; -/* Call bpf_obj_get_info_by_fd() to get sizes of arrays */ - err =bpf_obj_get_info_by_fd (fd, &info, &info_len); + arrays =1UL <<BPF_PROG_INFO_JITED_KSYMS ; + arrays |=1UL <<BPF_PROG_INFO_JITED_FUNC_LENS ; + arrays |=1UL <<BPF_PROG_INFO_FUNC_INFO ; + arrays |=1UL <<BPF_PROG_INFO_PROG_TAGS ; -if (err) { -pr_debug ("%s: failed to get BPF program info: %s, aborting\n" , - __func__,str_error_r (errno, errbuf,sizeof (errbuf))); + info_linear =bpf_program__get_prog_info_linear (fd, arrays); +if (IS_ERR_OR_NULL (info_linear)) { + info_linear =NULL ; +pr_debug ("%s: failed to get BPF program info. aborting\n" , __func__);return -1 ; } -if (info_len < offsetof(struct bpf_prog_info , prog_tags)) { + +if (info_linear->info_len < offsetof(struct bpf_prog_info , prog_tags)) {pr_debug ("%s: the kernel is too old, aborting\n" , __func__);return -2 ; } + info = &info_linear->info; +/* number of ksyms, func_lengths, and tags should match */ - sub_prog_cnt = info.nr_jited_ksyms; -if (sub_prog_cnt != info.nr_prog_tags || - sub_prog_cnt != info.nr_jited_func_lens) + sub_prog_cnt = info->nr_jited_ksyms; +if (sub_prog_cnt != info->nr_prog_tags || + sub_prog_cnt != info->nr_jited_func_lens)return -1 ;/* check BTF func info support */ -if (info.btf_id && info.nr_func_info && info.func_info_rec_size) { +if (info->btf_id && info->nr_func_info && info->func_info_rec_size) {/* btf func info number should be same as sub_prog_cnt */ -if (sub_prog_cnt != info.nr_func_info) { +if (sub_prog_cnt != info->nr_func_info) {pr_debug ("%s: mismatch in BPF sub program count and BTF function info count, aborting\n" , __func__); -return -1 ; - } -if (btf__get_from_id (info.btf_id, &btf)) { -pr_debug ("%s: failed to get BTF of id %u, aborting\n" , __func__, info.btf_id); -return -1 ; + err =-1 ; + goto out; } - func_info_rec_size = info.func_info_rec_size; - func_infos =calloc (sub_prog_cnt, func_info_rec_size); -if (!func_infos) { -pr_debug ("%s: failed to allocate memory for func_infos, aborting\n" , __func__); -return -1 ; +if (btf__get_from_id (info->btf_id, &btf)) { +pr_debug ("%s: failed to get BTF of id %u, aborting\n" , __func__, info->btf_id); + err =-1 ; + btf =NULL ; + goto out; } has_btf = true; } -/* -* We need address, length, and tag for each sub program. -* Allocate memory and call bpf_obj_get_info_by_fd() again -*/ - prog_addrs =calloc (sub_prog_cnt,sizeof (u64)); -if (!prog_addrs) { -pr_debug ("%s: failed to allocate memory for prog_addrs, aborting\n" , __func__); - goto out; - } - prog_lens =calloc (sub_prog_cnt,sizeof (u32)); -if (!prog_lens) { -pr_debug ("%s: failed to allocate memory for prog_lens, aborting\n" , __func__); - goto out; - } - prog_tags =calloc (sub_prog_cnt,BPF_TAG_SIZE ); -if (!prog_tags) { -pr_debug ("%s: failed to allocate memory for prog_tags, aborting\n" , __func__); - goto out; - } - -memset (&info,0 ,sizeof (info)); - info.nr_jited_ksyms = sub_prog_cnt; - info.nr_jited_func_lens = sub_prog_cnt; - info.nr_prog_tags = sub_prog_cnt; - info.jited_ksyms =ptr_to_u64 (prog_addrs); - info.jited_func_lens =ptr_to_u64 (prog_lens); - info.prog_tags =ptr_to_u64 (prog_tags); - info_len =sizeof (info); -if (has_btf) { - info.nr_func_info = sub_prog_cnt; - info.func_info_rec_size = func_info_rec_size; - info.func_info =ptr_to_u64 (func_infos); - } - - err =bpf_obj_get_info_by_fd (fd, &info, &info_len); -if (err) { -pr_debug ("%s: failed to get BPF program info, aborting\n" , __func__); - goto out; - } -/* Synthesize PERF_RECORD_KSYMBOL */ for (i =0 ; i < sub_prog_cnt; i++) { +u8 (*prog_tags)[BPF_TAG_SIZE ] = (void *)(uintptr_t )(info->prog_tags); +__u32 *prog_lens = (__u32 *)(uintptr_t )(info->jited_func_lens); +__u64 *prog_addrs = (__u64 *)(uintptr_t )(info->jited_ksyms); +void *func_infos = (void *)(uintptr_t )(info->func_info);const struct bpf_func_info *finfo;const char *short_name =NULL ;const struct btf_type *t;
@@ -163,13 +128,13 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,KSYM_NAME_LEN - name_len, prog_tags[i], BPF_TAG_SIZE);if (has_btf) { - finfo = func_infos + i * info.func_info_rec_size; + finfo = func_infos + i * info->func_info_rec_size; t =btf__type_by_id (btf, finfo->type_id); short_name =btf__name_by_offset (btf, t->name_off); }else if (i ==0 && sub_prog_cnt ==1 ) {/* no subprog */ -if (info.name[0 ]) - short_name = info.name; +if (info->name[0 ]) + short_name = info->name; }else short_name ="F" ;if (short_name)
@@ -195,9 +160,9 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, }, .type = PERF_BPF_EVENT_PROG_LOAD, .flags = 0, - .id = info.id, + .id = info->id, }; -memcpy (bpf_event->tag, prog_tags[i],BPF_TAG_SIZE ); +memcpy (bpf_event->tag, info->tag,BPF_TAG_SIZE );memset ((void *)event + event->header.size,0 , machine->id_hdr_size); event->header.size += machine->id_hdr_size; err = perf_tool__process_synth_event(tool, event,
@@ -205,10 +170,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, } out: -free (prog_tags); -free (prog_lens); -free (prog_addrs); -free (func_infos); +free (info_linear);free (btf);return err ?-1 :0 ; }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 30/44 perf bpf: Make synthesize_bpf_events() receive perf_session pointer instead of perf_tool
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
This patch changes the arguments of perf_event__synthesize_bpf_events() to include perf_session* instead of perf_tool*. perf_session will be used in the next patch.
--- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/bpf-event.c | 8 +++++--- tools/perf/util/bpf-event.h | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-)
tools/perf/builtin-record.c +1 -1
@@ -1114,7 +1114,7 @@ static int record__synthesize(struct record *rec, bool tail)return err; } - err =perf_event__synthesize_bpf_events (tool, process_synthesized_event, + err =perf_event__synthesize_bpf_events (session, process_synthesized_event, machine, opts);if (err <0 )pr_warning ("Couldn't synthesize bpf events.\n" );
tools/perf/builtin-top.c +1 -1
@@ -1208,7 +1208,7 @@ static int __cmd_top(struct perf_top *top)init_process_thread (top); - ret =perf_event__synthesize_bpf_events (&top->tool, perf_event__process, + ret =perf_event__synthesize_bpf_events (top->session, perf_event__process, &top->session->machines.host, &top->record_opts);if (ret <0 )
tools/perf/util/bpf-event.c +5 -3
@@ -10,6 +10,7 @@#include "debug.h" #include "symbol.h" #include "machine.h" +#include "session.h" #define ptr_to_u64 (ptr) ((__u64)(unsigned long)(ptr))
@@ -42,7 +43,7 @@ int machine__process_bpf_event(struct machine *machine __maybe_unused,* -1 for failures; * -2 for lack of kernel support. */ -static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool, +static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, perf_event__handler_t process, struct machine *machine, int fd,
@@ -52,6 +53,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,struct ksymbol_event *ksymbol_event = &event->ksymbol_event;struct bpf_event *bpf_event = &event->bpf_event;struct bpf_prog_info_linear *info_linear; +struct perf_tool *tool = session->tool;struct bpf_prog_info *info;struct btf *btf =NULL ;bool has_btf = false;
@@ -175,7 +177,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_tool *tool,return err ?-1 :0 ; } -int perf_event__synthesize_bpf_events (struct perf_tool *tool, +int perf_event__synthesize_bpf_events (struct perf_session *session,perf_event__handler_t process,struct machine *machine,struct record_opts *opts)
@@ -209,7 +211,7 @@ int perf_event__synthesize_bpf_events(struct perf_tool *tool,continue ; } - err =perf_event__synthesize_one_bpf_prog (tool, process, + err =perf_event__synthesize_one_bpf_prog (session, process, machine, fd, event, opts);close (fd);
tools/perf/util/bpf-event.h +2 -2
@@ -15,7 +15,7 @@ struct record_opts;int machine__process_bpf_event (struct machine *machine,union perf_event *event,struct perf_sample *sample); -int perf_event__synthesize_bpf_events (struct perf_tool *tool, +int perf_event__synthesize_bpf_events (struct perf_session *session,perf_event__handler_t process,struct machine *machine,struct record_opts *opts);
@@ -27,7 +27,7 @@ static inline int machine__process_bpf_event(struct machine *machine __maybe_unureturn 0 ; } -static inline int perf_event__synthesize_bpf_events (struct perf_tool *tool__maybe_unused , +static inline int perf_event__synthesize_bpf_events (struct perf_session *session__maybe_unused ,perf_event__handler_t process__maybe_unused ,struct machine *machine__maybe_unused ,struct record_opts *opts__maybe_unused )
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 31/44 perf bpf: Save bpf_prog_info in a rbtree in perf_env
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
bpf_prog_info contains information necessary to annotate bpf programs.
This patch saves bpf_prog_info for bpf programs loaded in the system.
Some big picture of the next few patches:
To fully annotate BPF programs with source code mapping, 4 different informations are needed:
1) PERF_RECORD_KSYMBOL
2) PERF_RECORD_BPF_EVENT
3) bpf_prog_info
4) btf
Before this set, 1) and 2) in the list are already saved to perf.data file. For BPF programs that are already loaded before perf run, 1) and 2) are synthesized by perf_event__synthesize_bpf_events(). For short living BPF programs, 1) and 2) are generated by kernel.
This set handles 3) and 4) from the list. Again, it is necessary to handle existing BPF program and short living program separately.
This patch handles 3) for exising BPF programs while synthesizing 1) and
2) in perf_event__synthesize_bpf_events(). These data are stored in perf_env. The next patch saves these data from perf_env to perf.data as headers.
Similarly, the two patches after the next saves 4) of existing BPF programs to perf_env and perf.data.
Another patch later will handle 3) and 4) for short living BPF programs by monitoring 1) and 2) in a dedicate thread.
--- tools/perf/perf.c | 1 + tools/perf/util/bpf-event.c | 30 ++++++++++++- tools/perf/util/bpf-event.h | 7 ++- tools/perf/util/env.c | 88 +++++++++++++++++++++++++++++++++++++ tools/perf/util/env.h | 19 ++++++++ tools/perf/util/session.c | 1 + 6 files changed, 144 insertions(+), 2 deletions(-)
tools/perf/perf.c +1 -0
@@ -298,6 +298,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) use_pager =1 ;commit_pager_choice (); +perf_env__init (&perf_env);perf_env__set_cmdline (&perf_env, argc, argv); status = p->fn (argc, argv);perf_config__exit ();
tools/perf/util/bpf-event.c +29 -1
@@ -10,6 +10,7 @@#include "debug.h" #include "symbol.h" #include "machine.h" +#include "env.h" #include "session.h" #define ptr_to_u64 (ptr) ((__u64)(unsigned long)(ptr))
@@ -54,17 +55,28 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,struct bpf_event *bpf_event = &event->bpf_event;struct bpf_prog_info_linear *info_linear;struct perf_tool *tool = session->tool; +struct bpf_prog_info_node *info_node;struct bpf_prog_info *info;struct btf *btf =NULL ;bool has_btf = false; +struct perf_env *env;u32 sub_prog_cnt, i;int err =0 ;u64 arrays; +/* +* for perf-record and perf-report use header.env; +* otherwise, use global perf_env. +*/ + env = session->data ? &session->header.env : &perf_env; + arrays =1UL <<BPF_PROG_INFO_JITED_KSYMS ; arrays |=1UL <<BPF_PROG_INFO_JITED_FUNC_LENS ; arrays |=1UL <<BPF_PROG_INFO_FUNC_INFO ; arrays |=1UL <<BPF_PROG_INFO_PROG_TAGS ; + arrays |=1UL <<BPF_PROG_INFO_JITED_INSNS ; + arrays |=1UL <<BPF_PROG_INFO_LINE_INFO ; + arrays |=1UL <<BPF_PROG_INFO_JITED_LINE_INFO ; info_linear =bpf_program__get_prog_info_linear (fd, arrays);if (IS_ERR_OR_NULL (info_linear)) {
@@ -153,8 +165,8 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, machine, process); } -/* Synthesize PERF_RECORD_BPF_EVENT */ if (!opts->no_bpf_event) { +/* Synthesize PERF_RECORD_BPF_EVENT */ *bpf_event = (struct bpf_event ){ .header = { .type =PERF_RECORD_BPF_EVENT ,
@@ -167,6 +179,22 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,memcpy (bpf_event->tag, info->tag,BPF_TAG_SIZE );memset ((void *)event + event->header.size,0 , machine->id_hdr_size); event->header.size += machine->id_hdr_size; + +/* save bpf_prog_info to env */ + info_node =malloc (sizeof (struct bpf_prog_info_node )); +if (!info_node) { + err =-1 ; + goto out; + } + + info_node->info_linear = info_linear; +perf_env__insert_bpf_prog_info (env, info_node); + info_linear =NULL ; + +/* +* process after saving bpf_prog_info to env, so that +* required information is ready for look up +*/ err =perf_tool__process_synth_event (tool, event, machine, process); }
tools/perf/util/bpf-event.h +6 -1
@@ -3,14 +3,19 @@#define __PERF_BPF_EVENT_H#include <linux/compiler.h> +#include <linux/rbtree.h> #include "event.h" struct machine ;union perf_event ;struct perf_sample ; -struct perf_tool ;struct record_opts ; +struct bpf_prog_info_node { +struct bpf_prog_info_linear *info_linear; +struct rb_node rb_node; +}; +#ifdef HAVE_LIBBPF_SUPPORT int machine__process_bpf_event (struct machine *machine,union perf_event *event,struct perf_sample *sample);
tools/perf/util/env.c +88 -0
109 lines not on this page · raw message
tools/perf/util/env.h +19 -0
@@ -3,7 +3,9 @@#define __PERF_ENV_H#include <linux/types.h> +#include <linux/rbtree.h> #include "cpumap.h" +#include "rwsem.h" struct cpu_topology_map {int socket_id;
@@ -64,8 +66,20 @@ struct perf_env {struct memory_node *memory_nodes;unsigned long long memory_bsize;u64 clockid_res_ns; + +/* +* bpf_info_lock protects bpf rbtrees. This is needed because the +* trees are accessed by different threads in perf-top +*/ +struct { +struct rw_semaphore lock; +struct rb_root infos; +u32 infos_cnt; + } bpf_progs; }; +struct bpf_prog_info_node ; +extern struct perf_env perf_env;void perf_env__exit (struct perf_env *env);
@@ -80,4 +94,9 @@ const char *perf_env__arch(struct perf_env *env);const char *perf_env__raw_arch (struct perf_env *env);int perf_env__nr_cpus_avail (struct perf_env *env); +void perf_env__init (struct perf_env *env); +void perf_env__insert_bpf_prog_info (struct perf_env *env, +struct bpf_prog_info_node *info_node); +struct bpf_prog_info_node *perf_env__find_bpf_prog_info (struct perf_env *env, +__u32 prog_id);#endif /* __PERF_ENV_H */
tools/perf/util/session.c +1 -0
@@ -132,6 +132,7 @@ struct perf_session *perf_session__new(struct perf_data *data,ordered_events__init (&session->ordered_events, ordered_events__deliver_event,NULL ); +perf_env__init (&session->header.env);if (data) {if (perf_data__open (data)) goto out_delete;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 32/44 perf bpf: Save bpf_prog_info information as headers to perf.data
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
This patch enables perf-record to save bpf_prog_info information as headers to perf.data. A new header type HEADER_BPF_PROG_INFO is introduced for this data.
Committer testing:
As root, being on the kernel sources top level directory, run:
# perf trace -e tools/perf/examples/bpf/augmented_raw_syscalls.c -e *msg
Just to compile and load a BPF program that attaches to the raw_syscalls:sys_{enter,exit} tracepoints to trace the syscalls ending in "msg" (recvmsg, sendmsg, recvmmsg, sendmmsg, etc).
Then do a systemwide perf record session for a few seconds:
# perf record -a sleep 2s
Then look at:
# perf report --header-only | grep -i bpf # bpf_prog_info of id 13 # bpf_prog_info of id 14 # bpf_prog_info of id 15 # bpf_prog_info of id 16 # bpf_prog_info of id 17 # bpf_prog_info of id 18 # bpf_prog_info of id 21 # bpf_prog_info of id 22 # bpf_prog_info of id 208 # bpf_prog_info of id 209 #
We need to show more info about these programs, like bpftool does for the ones running on the system, i.e. 'perf record/perf report' become a way of saving the BPF state in a machine to then analyse on another, together with all the other information that is already saved in the perf.data header:
# perf report --header-only
# ========
# captured on : Tue Mar 12 11:42:13 2019
# header version : 1
# data offset : 296
# data size : 16294184
# feat offset : 16294480
# hostname : quaco
# os release : 5.0.0+
# perf version : 5.0.gd783c8
# arch : x86_64
# nrcpus online : 8
# nrcpus avail : 8
# cpudesc : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
# cpuid : GenuineIntel,6,142,10
# total memory : 24555720 kB
# cmdline : /home/acme/bin/perf (deleted) record -a
# event : name = cycles:ppp, , id = { 3190123, 3190124, 3190125, 3190126, 3190127, 3190128, 3190129, 3190130 }, size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CPU|PERIOD, read_format = ID, disabled = 1, inherit = 1, mmap = 1, comm = 1, freq = 1, task = 1, precise_ip = 3, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1
# CPU_TOPOLOGY info available, use -I to display
# NUMA_TOPOLOGY info available, use -I to display
# pmu mappings: intel_pt = 8, software = 1, power = 11, uprobe = 7, uncore_imc = 12, cpu = 4, cstate_core = 18, uncore_cbox_2 = 15, breakpoint = 5, uncore_cbox_0 = 13, tracepoint = 2, cstate_pkg = 19, uncore_arb = 17, kprobe = 6, i915 = 10, msr = 9, uncore_cbox_3 = 16, uncore_cbox_1 = 14
# CACHE info available, use -I to display
# time of first sample : 116392.441701
# time of last sample : 116400.932584
# sample duration : 8490.883 ms
# MEM_TOPOLOGY info available, use -I to display
# bpf_prog_info of id 13
# bpf_prog_info of id 14
# bpf_prog_info of id 15
# bpf_prog_info of id 16
# bpf_prog_info of id 17
# bpf_prog_info of id 18
# bpf_prog_info of id 21
# bpf_prog_info of id 22
# bpf_prog_info of id 208
# bpf_prog_info of id 209
# missing features: TRACING_DATA BRANCH_STACK GROUP_DESC AUXTRACE STAT CLOCKID DIR_FORMAT
# ========
#Committer notes:
We can't use the libbpf unconditionally, as the build may have been with NO_LIBBPF, when we end up with linking errors, so provide dummy {process,write}_bpf_prog_info() wrapped by HAVE_LIBBPF_SUPPORT for that case.
Printing are not affected by this, so can continue as is.
--- tools/perf/util/header.c | 153 ++++++++++++++++++++++++++++++++++++++- tools/perf/util/header.h | 1 + 2 files changed, 153 insertions(+), 1 deletion(-)
tools/perf/util/header.c +152 -1
@@ -18,6 +18,7 @@#include <sys/utsname.h> #include <linux/time64.h> #include <dirent.h> +#include <bpf/libbpf.h> #include "evlist.h" #include "evsel.h"
@@ -40,6 +41,7 @@#include "time-utils.h" #include "units.h" #include "cputopo.h" +#include "bpf-event.h" #include "sane_ctype.h"
@@ -876,6 +878,56 @@ static int write_dir_format(struct feat_fd *ff,return do_write (ff, &data->dir.version,sizeof (data->dir.version)); } +#ifdef HAVE_LIBBPF_SUPPORT +static int write_bpf_prog_info (struct feat_fd *ff, +struct perf_evlist *evlist__maybe_unused ) +{ +struct perf_env *env = &ff->ph->env; +struct rb_root *root; +struct rb_node *next; +int ret; + +down_read (&env->bpf_progs.lock); + + ret =do_write (ff, &env->bpf_progs.infos_cnt, +sizeof (env->bpf_progs.infos_cnt)); +if (ret <0 ) + goto out; + + root = &env->bpf_progs.infos; + next =rb_first (root); +while (next) { +struct bpf_prog_info_node *node; +size_t len; + + node = rb_entry(next, struct bpf_prog_info_node, rb_node); + next =rb_next (&node->rb_node); + len =sizeof (struct bpf_prog_info_linear ) + + node->info_linear->data_len; + +/* before writing to file, translate address to offset */ +bpf_program__bpil_addr_to_offs (node->info_linear); + ret =do_write (ff, node->info_linear, len); +/* +* translate back to address even when do_write() fails, +* so that this function never changes the data. +*/ +bpf_program__bpil_offs_to_addr (node->info_linear); +if (ret <0 ) + goto out; + } +out: +up_read (&env->bpf_progs.lock); +return ret; +} +#else // HAVE_LIBBPF_SUPPORT +static int write_bpf_prog_info (struct feat_fd *ff__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +return 0 ; +} +#endif // HAVE_LIBBPF_SUPPORT +static int cpu_cache_level__sort (const void *a,const void *b) {struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1367,6 +1419,29 @@ static void print_dir_format(struct feat_fd *ff, FILE *fp)fprintf (fp,"# directory data version : %" PRIu64"\n" , data->dir.version); } +static void print_bpf_prog_info (struct feat_fd *ff,FILE *fp) +{ +struct perf_env *env = &ff->ph->env; +struct rb_root *root; +struct rb_node *next; + +down_read (&env->bpf_progs.lock); + + root = &env->bpf_progs.infos; + next =rb_first (root); + +while (next) { +struct bpf_prog_info_node *node; + + node = rb_entry(next, struct bpf_prog_info_node, rb_node); + next =rb_next (&node->rb_node); +fprintf (fp,"# bpf_prog_info of id %u\n" , + node->info_linear->info.id); + } + +up_read (&env->bpf_progs.lock); +} +static void free_event_desc (struct perf_evsel *events) {struct perf_evsel *evsel;
@@ -2414,6 +2489,81 @@ static int process_dir_format(struct feat_fd *ff,return do_read_u64 (ff, &data->dir.version); } +#ifdef HAVE_LIBBPF_SUPPORT +static int process_bpf_prog_info (struct feat_fd *ff,void *data__maybe_unused ) +{ +struct bpf_prog_info_linear *info_linear; +struct bpf_prog_info_node *info_node; +struct perf_env *env = &ff->ph->env; +u32 count, i; +int err =-1 ; + +if (ff->ph->needs_swap) { +pr_warning ("interpreting bpf_prog_info from systems with endianity is not yet supported\n" ); +return 0 ; + } + +if (do_read_u32 (ff, &count)) +return -1 ; + +down_write (&env->bpf_progs.lock); + +for (i =0 ; i < count; ++i) { +u32 info_len, data_len; + + info_linear =NULL ; + info_node =NULL ; +if (do_read_u32 (ff, &info_len)) + goto out; +if (do_read_u32 (ff, &data_len)) + goto out; + +if (info_len >sizeof (struct bpf_prog_info )) { +pr_warning ("detected invalid bpf_prog_info\n" ); + goto out; + } + + info_linear =malloc (sizeof (struct bpf_prog_info_linear ) + + data_len); +if (!info_linear) + goto out; + info_linear->info_len =sizeof (struct bpf_prog_info ); + info_linear->data_len = data_len; +if (do_read_u64 (ff, (u64 *)(&info_linear->arrays))) + goto out; +if (__do_read (ff, &info_linear->info, info_len)) + goto out; +if (info_len <sizeof (struct bpf_prog_info )) +memset (((void *)(&info_linear->info)) + info_len,0 , +sizeof (struct bpf_prog_info ) - info_len); + +if (__do_read (ff, info_linear->data, data_len)) + goto out; + + info_node =malloc (sizeof (struct bpf_prog_info_node )); +if (!info_node) + goto out; + +/* after reading from file, translate offset to address */ +bpf_program__bpil_offs_to_addr (info_linear); + info_node->info_linear = info_linear; +perf_env__insert_bpf_prog_info (env, info_node); + } + +return 0 ; +out: +free (info_linear); +free (info_node); +up_write (&env->bpf_progs.lock); +return err; +} +#else // HAVE_LIBBPF_SUPPORT +static int process_bpf_prog_info (struct feat_fd *ff__maybe_unused ,void *data__maybe_unused ) +{ +return 0 ; +} +#endif // HAVE_LIBBPF_SUPPORT +struct feature_ops {int (*write)(struct feat_fd *ff,struct perf_evlist *evlist);void (*print)(struct feat_fd *ff,FILE *fp);
@@ -2474,7 +2624,8 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {FEAT_OPR (SAMPLE_TIME , sample_time, false),FEAT_OPR (MEM_TOPOLOGY , mem_topology, true),FEAT_OPR (CLOCKID , clockid, false), -FEAT_OPN (DIR_FORMAT , dir_format, false) +FEAT_OPN (DIR_FORMAT , dir_format, false), +FEAT_OPR (BPF_PROG_INFO , bpf_prog_info, false) }; struct header_print_data {
tools/perf/util/header.h +1 -0
@@ -40,6 +40,7 @@ enum {HEADER_MEM_TOPOLOGY ,HEADER_CLOCKID ,HEADER_DIR_FORMAT , +HEADER_BPF_PROG_INFO ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 33/44 perf bpf: Save BTF in a rbtree in perf_env
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
BTF contains information necessary to annotate BPF programs. This patch saves BTF for BPF programs loaded in the system.
--- tools/perf/util/bpf-event.c | 23 +++++++++++++ tools/perf/util/bpf-event.h | 7 ++++ tools/perf/util/env.c | 67 +++++++++++++++++++++++++++++++++++++ tools/perf/util/env.h | 5 +++ 4 files changed, 102 insertions(+)
tools/perf/util/bpf-event.c +23 -0
@@ -34,6 +34,28 @@ int machine__process_bpf_event(struct machine *machine __maybe_unused,return 0 ; } +static int perf_env__fetch_btf (struct perf_env *env, +u32 btf_id, +struct btf *btf) +{ +struct btf_node *node; +u32 data_size; +const void *data; + + data =btf__get_raw_data (btf, &data_size); + + node =malloc (data_size +sizeof (struct btf_node )); +if (!node) +return -1 ; + + node->id = btf_id; + node->data_size = data_size; +memcpy (node->data, data, data_size); + +perf_env__insert_btf (env, node); +return 0 ; +} +/* * Synthesize PERF_RECORD_KSYMBOL and PERF_RECORD_BPF_EVENT for one bpf * program. One PERF_RECORD_BPF_EVENT is generated for the program. And
@@ -113,6 +135,7 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, goto out; } has_btf = true; +perf_env__fetch_btf (env, info->btf_id, btf); }/* Synthesize PERF_RECORD_KSYMBOL */
tools/perf/util/bpf-event.h +7 -0
@@ -16,6 +16,13 @@ struct bpf_prog_info_node {struct rb_node rb_node; }; +struct btf_node { +struct rb_node rb_node; +u32 id; +u32 data_size; +char data[]; +}; +#ifdef HAVE_LIBBPF_SUPPORT int machine__process_bpf_event (struct machine *machine,union perf_event *event,struct perf_sample *sample);
tools/perf/util/env.c +67 -0
85 lines not on this page · raw message
tools/perf/util/env.h +5 -0
@@ -75,10 +75,13 @@ struct perf_env {struct rw_semaphore lock;struct rb_root infos;u32 infos_cnt; +struct rb_root btfs; +u32 btfs_cnt; } bpf_progs; };struct bpf_prog_info_node ; +struct btf_node ;extern struct perf_env perf_env;
@@ -99,4 +102,6 @@ void perf_env__insert_bpf_prog_info(struct perf_env *env, struct bpf_prog_info_node *info_node);struct bpf_prog_info_node *perf_env__find_bpf_prog_info (struct perf_env *env,__u32 prog_id); +void perf_env__insert_btf (struct perf_env *env,struct btf_node *btf_node); +struct btf_node *perf_env__find_btf (struct perf_env *env,__u32 btf_id);#endif /* __PERF_ENV_H */
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 34/44 perf bpf: Save BTF information as headers to perf.data
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
This patch enables 'perf record' to save BTF information as headers to perf.data.
A new header type HEADER_BPF_BTF is introduced for this data.
Committer testing:
As root, being on the kernel sources top level directory, run:
# perf trace -e tools/perf/examples/bpf/augmented_raw_syscalls.c -e *msg
Just to compile and load a BPF program that attaches to the raw_syscalls:sys_{enter,exit} tracepoints to trace the syscalls ending in "msg" (recvmsg, sendmsg, recvmmsg, sendmmsg, etc).
Make sure you have a recent enough clang, say version 9, to get the BTF ELF sections needed for this testing:
# clang --version | head -1 clang version 9.0.0 (https://git.llvm.org/git/clang.git/ 7906282d3afec5dfdc2b27943fd6c0309086c507) (https://git.llvm.org/git/llvm.git/ a1b5de1ff8ae8bc79dc8e86e1f82565229bd0500) # readelf -SW tools/perf/examples/bpf/augmented_raw_syscalls.o | grep BTF [22] .BTF PROGBITS 0000000000000000 000ede 000b0e 00 0 0 1 [23] .BTF.ext PROGBITS 0000000000000000 0019ec 0002a0 00 0 0 1 [24] .rel.BTF.ext REL 0000000000000000 002fa8 000270 10 30 23 8
Then do a systemwide perf record session for a few seconds:
# perf record -a sleep 2s
Then look at:
# perf report --header-only | grep b[pt]f
# event : name = cycles:ppp, , id = { 1116204, 1116205, 1116206, 1116207, 1116208, 1116209, 1116210, 1116211 }, size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|PERIOD, read_format = ID, disabled = 1, inherit = 1, mmap = 1, comm = 1, freq = 1, enable_on_exec = 1, task = 1, precise_ip = 3, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, ksymbol = 1, bpf_event = 1
# bpf_prog_info of id 13
# bpf_prog_info of id 14
# bpf_prog_info of id 15
# bpf_prog_info of id 16
# bpf_prog_info of id 17
# bpf_prog_info of id 18
# bpf_prog_info of id 21
# bpf_prog_info of id 22
# bpf_prog_info of id 51
# bpf_prog_info of id 52
# btf info of id 8
#We need to show more info about these BPF and BTF entries , but that can be done later.
--- tools/perf/util/header.c | 101 ++++++++++++++++++++++++++++++++++++++- tools/perf/util/header.h | 1 + 2 files changed, 101 insertions(+), 1 deletion(-)
tools/perf/util/header.c +100 -1
@@ -928,6 +928,39 @@ static int write_bpf_prog_info(struct feat_fd *ff __maybe_unused, }#endif // HAVE_LIBBPF_SUPPORT +static int write_bpf_btf (struct feat_fd *ff, +struct perf_evlist *evlist__maybe_unused ) +{ +struct perf_env *env = &ff->ph->env; +struct rb_root *root; +struct rb_node *next; +int ret; + +down_read (&env->bpf_progs.lock); + + ret =do_write (ff, &env->bpf_progs.btfs_cnt, +sizeof (env->bpf_progs.btfs_cnt)); + +if (ret <0 ) + goto out; + + root = &env->bpf_progs.btfs; + next =rb_first (root); +while (next) { +struct btf_node *node; + + node = rb_entry(next, struct btf_node, rb_node); + next =rb_next (&node->rb_node); + ret =do_write (ff, &node->id, +sizeof (u32) *2 + node->data_size); +if (ret <0 ) + goto out; + } +out: +up_read (&env->bpf_progs.lock); +return ret; +} +static int cpu_cache_level__sort (const void *a,const void *b) {struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1442,6 +1475,28 @@ static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp)up_read (&env->bpf_progs.lock); } +static void print_bpf_btf (struct feat_fd *ff,FILE *fp) +{ +struct perf_env *env = &ff->ph->env; +struct rb_root *root; +struct rb_node *next; + +down_read (&env->bpf_progs.lock); + + root = &env->bpf_progs.btfs; + next =rb_first (root); + +while (next) { +struct btf_node *node; + + node = rb_entry(next, struct btf_node, rb_node); + next =rb_next (&node->rb_node); +fprintf (fp,"# btf info of id %u\n" , node->id); + } + +up_read (&env->bpf_progs.lock); +} +static void free_event_desc (struct perf_evsel *events) {struct perf_evsel *evsel;
@@ -2564,6 +2619,49 @@ static int process_bpf_prog_info(struct feat_fd *ff __maybe_unused, void *data _ }#endif // HAVE_LIBBPF_SUPPORT +static int process_bpf_btf (struct feat_fd *ff,void *data__maybe_unused ) +{ +struct perf_env *env = &ff->ph->env; +u32 count, i; + +if (ff->ph->needs_swap) { +pr_warning ("interpreting btf from systems with endianity is not yet supported\n" ); +return 0 ; + } + +if (do_read_u32 (ff, &count)) +return -1 ; + +down_write (&env->bpf_progs.lock); + +for (i =0 ; i < count; ++i) { +struct btf_node *node; +u32 id, data_size; + +if (do_read_u32 (ff, &id)) +return -1 ; +if (do_read_u32 (ff, &data_size)) +return -1 ; + + node =malloc (sizeof (struct btf_node ) + data_size); +if (!node) +return -1 ; + + node->id = id; + node->data_size = data_size; + +if (__do_read (ff, node->data, data_size)) { +free (node); +return -1 ; + } + +perf_env__insert_btf (env, node); + } + +up_write (&env->bpf_progs.lock); +return 0 ; +} +struct feature_ops {int (*write)(struct feat_fd *ff,struct perf_evlist *evlist);void (*print)(struct feat_fd *ff,FILE *fp);
@@ -2625,7 +2723,8 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {FEAT_OPR (MEM_TOPOLOGY , mem_topology, true),FEAT_OPR (CLOCKID , clockid, false),FEAT_OPN (DIR_FORMAT , dir_format, false), -FEAT_OPR (BPF_PROG_INFO , bpf_prog_info, false) +FEAT_OPR (BPF_PROG_INFO , bpf_prog_info, false), + FEAT_OPR(BPF_BTF, bpf_btf, false), }; struct header_print_data {
tools/perf/util/header.h +1 -0
@@ -41,6 +41,7 @@ enum {HEADER_CLOCKID ,HEADER_DIR_FORMAT ,HEADER_BPF_PROG_INFO , +HEADER_BPF_BTF ,HEADER_LAST_FEATURE , HEADER_FEAT_BITS = 256, };
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 35/44 perf top: Add option --no-bpf-event
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
This patch adds option --no-bpf-event to 'perf top', which is the same as the option of 'perf record'.
The following patches will use this option.
Committer testing:
# perf top -vv 2> /tmp/perf_event_attr.out
# cat /tmp/perf_event_attr.out
------------------------------------------------------------
perf_event_attr:
size 112
{ sample_period, sample_freq } 4000
sample_type IP|TID|TIME|CPU|PERIOD
read_format ID
disabled 1
inherit 1
mmap 1
comm 1
freq 1
task 1
precise_ip 3
sample_id_all 1
exclude_guest 1
mmap2 1
comm_exec 1
ksymbol 1
bpf_event 1
------------------------------------------------------------
#After this patch:
# perf top --no-bpf-event -vv 2> /tmp/perf_event_attr.out
# cat /tmp/perf_event_attr.out
------------------------------------------------------------
perf_event_attr:
size 112
{ sample_period, sample_freq } 4000
sample_type IP|TID|TIME|CPU|PERIOD
read_format ID
disabled 1
inherit 1
mmap 1
comm 1
freq 1
task 1
precise_ip 3
sample_id_all 1
exclude_guest 1
mmap2 1
comm_exec 1
ksymbol 1
------------------------------------------------------------
#--- tools/perf/builtin-top.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/builtin-top.c +1 -0
@@ -1469,6 +1469,7 @@ int cmd_top(int argc, const char **argv) "Display raw encoding of assembly instructions (default)"),OPT_BOOLEAN (0 ,"demangle-kernel" , &symbol_conf.demangle_kernel,"Enable kernel symbol demangling" ), +OPT_BOOLEAN (0 ,"no-bpf-event" , &top.record_opts.no_bpf_event,"do not record bpf events" ),OPT_STRING (0 ,"objdump" , &top.annotation_opts.objdump_path,"path" ,"objdump binary to use for disassembly and annotations" ), OPT_STRING('M', "disassembler-style", &top.annotation_opts.disassembler_style, "disassembler style",
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 36/44 perf feature detection: Add -lopcodes to feature-libbfd
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
Both libbfd and libopcodes are distributed with binutil-dev/devel. When libbfd is present, it is OK to assume that libopcodes also present. This has been a safe assumption for bpftool.
This patch adds -lopcodes to perf/Makefile.config. libopcodes will be used in the next commit for BPF annotation.
--- tools/perf/Makefile.config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/Makefile.config +3 -3
@@ -713,7 +713,7 @@ else endif ifeq ($(feature-libbfd), 1) - EXTLIBS += -lbfd + EXTLIBS += -lbfd -lopcodes else # we are on a system that requires -liberty and (maybe) -lz # to link against -lbfd; test each case individually here
@@ -724,10 +724,10 @@ else $(call feature_check,libbfd-liberty-z) ifeq ($(feature-libbfd-liberty), 1) - EXTLIBS += -lbfd -liberty + EXTLIBS += -lbfd -lopcodes -liberty else ifeq ($(feature-libbfd-liberty-z), 1) - EXTLIBS += -lbfd -liberty -lz + EXTLIBS += -lbfd -lopcodes -liberty -lz endif endif endif
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 37/44 perf symbols: Introduce DSO_BINARY_TYPE__BPF_PROG_INFO
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
Introduce a new dso type DSO_BINARY_TYPE__BPF_PROG_INFO for BPF programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso will call into a new function symbol__disassemble_bpf() in an upcoming patch, where annotation line information is filled based bpf_prog_info and btf saved in given perf_env.
Committer notes:
Removed the unnamed union with 'bpf_prog' and 'cache' in 'struct dso', to fix this bug when exiting 'perf top':
# perf top perf: Segmentation fault -------- backtrace -------- perf[0x5a785a] /lib64/libc.so.6(+0x385bf)[0x7fd68443c5bf] perf(rb_first+0x2b)[0x4d6eeb] perf(dso__delete+0xb7)[0x4dffb7] perf[0x4f9e37] perf(perf_session__delete+0x64)[0x504df4] perf(cmd_top+0x1957)[0x454467] perf[0x4aad18] perf(main+0x61c)[0x42ec7c] /lib64/libc.so.6(__libc_start_main+0xf2)[0x7fd684428412] perf(_start+0x2d)[0x42eead] # # addr2line -fe ~/bin/perf 0x4dffb7 dso_cache__free /home/acme/git/perf/tools/perf/util/dso.c:713
That is trying to access the dso->data.cache, and that is not used with BPF programs, so we end up accessing what is in bpf_prog.first_member, b00m.
--- tools/perf/util/dso.c | 1 + tools/perf/util/dso.h | 8 ++++++++ tools/perf/util/symbol.c | 1 + 3 files changed, 10 insertions(+)
tools/perf/util/dso.c +1 -0
@@ -184,6 +184,7 @@ int dso__read_binary_type_filename(const struct dso *dso,case DSO_BINARY_TYPE__KALLSYMS :case DSO_BINARY_TYPE__GUEST_KALLSYMS :case DSO_BINARY_TYPE__JAVA_JIT : +case DSO_BINARY_TYPE__BPF_PROG_INFO :case DSO_BINARY_TYPE__NOT_FOUND : ret =-1 ;break ;
tools/perf/util/dso.h +8 -0
@@ -14,6 +14,7 @@struct machine ;struct map ; +struct perf_env ;enum dso_binary_type {DSO_BINARY_TYPE__KALLSYMS =0 ,
@@ -35,6 +36,7 @@ enum dso_binary_type {DSO_BINARY_TYPE__KCORE ,DSO_BINARY_TYPE__GUEST_KCORE ,DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO , +DSO_BINARY_TYPE__BPF_PROG_INFO , DSO_BINARY_TYPE__NOT_FOUND, };
@@ -189,6 +191,12 @@ struct dso {u64 debug_frame_offset;u64 eh_frame_hdr_offset; } data; +/* bpf prog information */ +struct { +u32 id; +u32 sub_id; +struct perf_env *env; + } bpf_prog;union {/* Tool specific area */ void *priv;
tools/perf/util/symbol.c +1 -0
@@ -1455,6 +1455,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO :return true; +case DSO_BINARY_TYPE__BPF_PROG_INFO :case DSO_BINARY_TYPE__NOT_FOUND :default :return false;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 38/44 perf bpf: Process PERF_BPF_EVENT_PROG_LOAD for annotation
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
This patch adds processing of PERF_BPF_EVENT_PROG_LOAD, which sets proper DSO type/id/etc of memory regions mapped to BPF programs to DSO_BINARY_TYPE__BPF_PROG_INFO.
--- tools/perf/util/bpf-event.c | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
tools/perf/util/bpf-event.c +54 -0
@@ -12,6 +12,7 @@#include "machine.h" #include "env.h" #include "session.h" +#include "map.h" #define ptr_to_u64 (ptr) ((__u64)(unsigned long)(ptr))
@@ -25,12 +26,65 @@ static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len)return ret; } +static int machine__process_bpf_event_load (struct machine *machine, +union perf_event *event, +struct perf_sample *sample__maybe_unused ) +{ +struct bpf_prog_info_linear *info_linear; +struct bpf_prog_info_node *info_node; +struct perf_env *env = machine->env; +int id = event->bpf_event.id; +unsigned int i; + +/* perf-record, no need to handle bpf-event */ +if (env ==NULL ) +return 0 ; + + info_node =perf_env__find_bpf_prog_info (env, id); +if (!info_node) +return 0 ; + info_linear = info_node->info_linear; + +for (i =0 ; i < info_linear->info.nr_jited_ksyms; i++) { +u64 *addrs = (u64 *)(info_linear->info.jited_ksyms); +u64 addr = addrs[i]; +struct map *map; + + map =map_groups__find (&machine->kmaps, addr); + +if (map) { + map->dso->binary_type =DSO_BINARY_TYPE__BPF_PROG_INFO ; + map->dso->bpf_prog.id = id; + map->dso->bpf_prog.sub_id = i; + map->dso->bpf_prog.env = env; + } + } +return 0 ; +} +int machine__process_bpf_event (struct machine *machine__maybe_unused ,union perf_event *event,struct perf_sample *sample__maybe_unused ) {if (dump_trace)perf_event__fprintf_bpf_event (event, stdout); + +switch (event->bpf_event.type) { +case PERF_BPF_EVENT_PROG_LOAD : +return machine__process_bpf_event_load (machine, event, sample); + +case PERF_BPF_EVENT_PROG_UNLOAD : +/* +* Do not free bpf_prog_info and btf of the program here, +* as annotation still need them. They will be freed at +* the end of the session. +*/ +break ; +default : +pr_debug ("unexpected bpf_event type of %d\n" , + event->bpf_event.type); +break ; + }return 0 ; }
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 39/44 perf build: Check what binutils's 'disassembler()' signature to use
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
Commit 003ca0fd2286 ("Refactor disassembler selection") in the binutils repo, which changed the disassembler() function signature, so we must use the feature test introduced in fb982666e380 ("tools/bpftool: fix bpftool build with bintutils >= 2.9") to deal with that.
Committer testing:
After adding the missing function call to test-all.c, and:
FEATURE_CHECK_LDFLAGS-disassembler-four-args = -bfd -lopcodes
And the fallbacks for cases where we need -liberty and sometimes -lz to tools/perf/Makefile.config, we get:
$ make -C tools/perf O=/tmp/build/perf install-bin
make: Entering directory '/home/acme/git/perf/tools/perf'
BUILD: Doing 'make -j8' parallel buildAuto-detecting system features:
... dwarf: [ on ] ... dwarf_getlocations: [ on ] ... glibc: [ on ] ... gtk2: [ on ] ... libaudit: [ on ] ... libbfd: [ on ] ... libelf: [ on ] ... libnuma: [ on ] ... numa_num_possible_cpus: [ on ] ... libperl: [ on ] ... libpython: [ on ] ... libslang: [ on ] ... libcrypto: [ on ] ... libunwind: [ on ] ... libdw-dwarf-unwind: [ on ] ... zlib: [ on ] ... lzma: [ on ] ... get_cpuid: [ on ] ... bpf: [ on ] ... libaio: [ on ] ... disassembler-four-args: [ on ]
CC /tmp/build/perf/jvmti/libjvmti.o
CC /tmp/build/perf/builtin-bench.o
<SNIP>
$
$
The feature detection test-all.bin gets successfully built and linked:
$ ls -la /tmp/build/perf/feature/test-all.bin -rwxrwxr-x. 1 acme acme 2680352 Mar 19 11:07 /tmp/build/perf/feature/test-all.bin $ nm /tmp/build/perf/feature/test-all.bin | grep -w disassembler 0000000000061f90 T disassembler $
Time to move on to the patches that make use of this disassembler() routine in binutils's libopcodes.
--- tools/build/Makefile.feature | 6 ++++-- tools/build/feature/test-all.c | 5 +++++ tools/perf/Makefile.config | 9 +++++++++ 3 files changed, 18 insertions(+), 2 deletions(-)
tools/build/Makefile.feature +4 -2
@@ -66,7 +66,8 @@ FEATURE_TESTS_BASIC := \ sched_getcpu \ sdt \ setns \ - libaio + libaio \ + disassembler-four-args # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list # of all feature tests
@@ -118,7 +119,8 @@ FEATURE_DISPLAY ?= \ lzma \ get_cpuid \ bpf \ - libaio + libaio \ + disassembler-four-args # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. # If in the future we need per-feature checks/flags for features not
tools/build/feature/test-all.c +5 -0
@@ -178,6 +178,10 @@# include "test-reallocarray.c" #undef main +#define main main_test_disassembler_four_args +# include "test-disassembler-four-args.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();
@@ -219,6 +223,7 @@ int main(int argc, char *argv[])main_test_setns ();main_test_libaio ();main_test_reallocarray (); +main_test_disassembler_four_args ();return 0 ; }
tools/perf/Makefile.config +9 -0
@@ -227,6 +227,8 @@ FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS) FEATURE_CHECK_LDFLAGS-libaio = -lrt +FEATURE_CHECK_LDFLAGS-disassembler-four-args = -lbfd -lopcodes + CFLAGS += -fno-omit-frame-pointer CFLAGS += -ggdb3 CFLAGS += -funwind-tables
@@ -725,11 +727,14 @@ else ifeq ($(feature-libbfd-liberty), 1) EXTLIBS += -lbfd -lopcodes -liberty + FEATURE_CHECK_LDFLAGS-disassembler-four-args += -liberty -ldl else ifeq ($(feature-libbfd-liberty-z), 1) EXTLIBS += -lbfd -lopcodes -liberty -lz + FEATURE_CHECK_LDFLAGS-disassembler-four-args += -liberty -lz -ldl endif endif + $(call feature_check,disassembler-four-args) endif ifdef NO_DEMANGLE
@@ -808,6 +813,10 @@ ifdef HAVE_KVM_STAT_SUPPORT CFLAGS += -DHAVE_KVM_STAT_SUPPORT endif +ifeq ($(feature-disassembler-four-args), 1) + CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE +endif + ifeq (${IS_64_BIT}, 1) ifndef NO_PERF_READ_VDSO32 $(call feature_check,compile-32)
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 40/44 perf annotate: Enable annotation of BPF programs
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso calls into a new function symbol__disassemble_bpf(), where annotation line information is filled based on the bpf_prog_info and btf data saved in given perf_env.
symbol__disassemble_bpf() uses binutils's libopcodes to disassemble bpf programs.
Committer testing:
After fixing this:
- u64 *addrs = (u64 *)(info_linear->info.jited_ksyms);
+ u64 *addrs = (u64 *)(uintptr_t)(info_linear->info.jited_ksyms);
Detected when crossbuilding to a 32-bit arch.
And making all this dependent on HAVE_LIBBFD_SUPPORT and HAVE_LIBBPF_SUPPORT:
1) Have a BPF program running, one that has BTF info, etc, I used the tools/perf/examples/bpf/augmented_raw_syscalls.c put in place by 'perf trace'.
# grep -B1 augmented_raw ~/.perfconfig [trace] add_events = /home/acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.c # # perf trace -e *mmsg dnf/6245 sendmmsg(20, 0x7f5485a88030, 2, MSG_NOSIGNAL) = 2 NetworkManager/10055 sendmmsg(22<socket:[1056822]>, 0x7f8126ad1bb0, 2, MSG_NOSIGNAL) = 2
2) Then do a 'perf record' system wide for a while:
# perf record -a ^C[ perf record: Woken up 68 times to write data ] [ perf record: Captured and wrote 19.427 MB perf.data (366891 samples) ] #
3) Check that we captured BPF and BTF info in the perf.data file:
# perf report --header-only | grep 'b[pt]f'
# event : name = cycles:ppp, , id = { 294789, 294790, 294791, 294792, 294793, 294794, 294795, 294796 }, size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CPU|PERIOD, read_format = ID, disabled = 1, inherit = 1, mmap = 1, comm = 1, freq = 1, task = 1, precise_ip = 3, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, ksymbol = 1, bpf_event = 1
# bpf_prog_info of id 13
# bpf_prog_info of id 14
# bpf_prog_info of id 15
# bpf_prog_info of id 16
# bpf_prog_info of id 17
# bpf_prog_info of id 18
# bpf_prog_info of id 21
# bpf_prog_info of id 22
# bpf_prog_info of id 41
# bpf_prog_info of id 42
# btf info of id 2
#4) Check which programs got recorded:
# perf report | grep bpf_prog | head
0.16% exe bpf_prog_819967866022f1e1_sys_enter [k] bpf_prog_819967866022f1e1_sys_enter
0.14% exe bpf_prog_c1bd85c092d6e4aa_sys_exit [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
0.08% fuse-overlayfs bpf_prog_819967866022f1e1_sys_enter [k] bpf_prog_819967866022f1e1_sys_enter
0.07% fuse-overlayfs bpf_prog_c1bd85c092d6e4aa_sys_exit [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
0.01% clang-4.0 bpf_prog_c1bd85c092d6e4aa_sys_exit [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
0.01% clang-4.0 bpf_prog_819967866022f1e1_sys_enter [k] bpf_prog_819967866022f1e1_sys_enter
0.00% clang bpf_prog_c1bd85c092d6e4aa_sys_exit [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
0.00% runc bpf_prog_819967866022f1e1_sys_enter [k] bpf_prog_819967866022f1e1_sys_enter
0.00% clang bpf_prog_819967866022f1e1_sys_enter [k] bpf_prog_819967866022f1e1_sys_enter
0.00% sh bpf_prog_c1bd85c092d6e4aa_sys_exit [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
#This was with the default --sort order for 'perf report', which is:
--sort comm,dso,symbol
If we just look for the symbol, for instance:
# perf report --sort symbol | grep bpf_prog | head
0.26% [k] bpf_prog_819967866022f1e1_sys_enter - -
0.24% [k] bpf_prog_c1bd85c092d6e4aa_sys_exit - -
#or the DSO:
# perf report --sort dso | grep bpf_prog | head
0.26% bpf_prog_819967866022f1e1_sys_enter
0.24% bpf_prog_c1bd85c092d6e4aa_sys_exit
#We'll see the two BPF programs that augmented_raw_syscalls.o puts in place, one attached to the raw_syscalls:sys_enter and another to the raw_syscalls:sys_exit tracepoints, as expected.
Now we can finally do, from the command line, annotation for one of those two symbols, with the original BPF program source coude intermixed with the disassembled JITed code:
# perf annotate --stdio2 bpf_prog_819967866022f1e1_sys_enter
Samples: 950 of event 'cycles:ppp', 4000 Hz, Event count (approx.): 553756947, [percent: local period] bpf_prog_819967866022f1e1_sys_enter() bpf_prog_819967866022f1e1_sys_enter
Percent int sys_enter(struct syscall_enter_args *args)
53.41 push %rbp
0.63 mov %rsp,%rbp
0.31 sub $0x170,%rsp
1.93 sub $0x28,%rbp
7.02 mov %rbx,0x0(%rbp)
3.20 mov %r13,0x8(%rbp)
1.07 mov %r14,0x10(%rbp)
0.61 mov %r15,0x18(%rbp)
0.11 xor %eax,%eax
1.29 mov %rax,0x20(%rbp)
0.11 mov %rdi,%rbx
return bpf_get_current_pid_tgid();
2.02 → callq *ffffffffda6776d9
2.76 mov %eax,-0x148(%rbp)
mov %rbp,%rsi
int sys_enter(struct syscall_enter_args *args)
add $0xfffffffffffffeb8,%rsi
return bpf_map_lookup_elem(pids, &pid) != NULL;
movabs $0xffff975ac2607800,%rdi
1.26 → callq *ffffffffda6789e9
cmp $0x0,%rax
2.43 → je 0
add $0x38,%rax
0.21 xor %r13d,%r13d
if (pid_filter__has(&pids_filtered, getpid()))
0.81 cmp $0x0,%rax
→ jne 0
mov %rbp,%rdi
probe_read(&augmented_args.args, sizeof(augmented_args.args), args);
2.22 add $0xfffffffffffffeb8,%rdi
0.11 mov $0x40,%esi
0.32 mov %rbx,%rdx
2.74 → callq *ffffffffda658409
syscall = bpf_map_lookup_elem(&syscalls, &augmented_args.args.syscall_nr);
0.22 mov %rbp,%rsi
1.69 add $0xfffffffffffffec0,%rsi
syscall = bpf_map_lookup_elem(&syscalls, &augmented_args.args.syscall_nr);
movabs $0xffff975bfcd36000,%rdi
add $0xd0,%rdi
0.21 mov 0x0(%rsi),%eax
0.93 cmp $0x200,%rax
→ jae 0
0.10 shl $0x3,%rax
0.11 add %rdi,%rax
0.11 → jmp 0
xor %eax,%eax
if (syscall == NULL || !syscall->enabled)
1.07 cmp $0x0,%rax
→ je 0
if (syscall == NULL || !syscall->enabled)
6.57 movzbq 0x0(%rax),%rdi
if (syscall == NULL || !syscall->enabled)
cmp $0x0,%rdi
0.95 → je 0
mov $0x40,%r8d
switch (augmented_args.args.syscall_nr) {
mov -0x140(%rbp),%rdi
switch (augmented_args.args.syscall_nr) {
cmp $0x2,%rdi
→ je 0
cmp $0x101,%rdi
→ je 0
cmp $0x15,%rdi
→ jne 0
case SYS_OPEN: filename_arg = (const void *)args->args[0];
mov 0x10(%rbx),%rdx
→ jmp 0
case SYS_OPENAT: filename_arg = (const void *)args->args[1];
mov 0x18(%rbx),%rdx
if (filename_arg != NULL) {
cmp $0x0,%rdx
→ je 0
xor %edi,%edi
augmented_args.filename.reserved = 0;
mov %edi,-0x104(%rbp)
augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
mov %rbp,%rdi
add $0xffffffffffffff00,%rdi
augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
mov $0x100,%esi
→ callq *ffffffffda658499
mov $0x148,%r8d
augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
mov %eax,-0x108(%rbp)
augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
mov %rax,%rdi
shl $0x20,%rdi
shr $0x20,%rdi
if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) {
cmp $0xff,%rdi
→ ja 0
len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size;
add $0x48,%rax
len &= sizeof(augmented_args.filename.value) - 1;
and $0xff,%rax
mov %rax,%r8
mov %rbp,%rcx
return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, len);
add $0xfffffffffffffeb8,%rcx
mov %rbx,%rdi
movabs $0xffff975fbd72d800,%rsi
mov $0xffffffff,%edx
→ callq *ffffffffda658ad9
mov %rax,%r13
}
mov %r13,%rax
0.72 mov 0x0(%rbp),%rbx
mov 0x8(%rbp),%r13
1.16 mov 0x10(%rbp),%r14
0.10 mov 0x18(%rbp),%r15
0.42 add $0x28,%rbp
0.54 leaveq
0.54 ← retq#
Please see 'man perf-config' to see how to control what should be seen, via ~/.perfconfig [annotate] section, for instance, one can suppress the source code and see just the disassembly, etc.
Alternatively, use the TUI bu just using 'perf annotate', press '/bpf_prog' to see the bpf symbols, press enter and do the interactive annotation, which allows for dumping to a file after selecting the the various output tunables, for instance, the above without source code intermixed, plus showing all the instruction offsets:
# perf annotate bpf_prog_819967866022f1e1_sys_enter
Then press: 's' to hide the source code + 'O' twice to show all instruction offsets, then 'P' to print to the bpf_prog_819967866022f1e1_sys_enter.annotation file, which will have:
# cat bpf_prog_819967866022f1e1_sys_enter.annotation bpf_prog_819967866022f1e1_sys_enter() bpf_prog_819967866022f1e1_sys_enter Event: cycles:ppp
53.41 0: push %rbp
0.63 1: mov %rsp,%rbp
0.31 4: sub $0x170,%rsp
1.93 b: sub $0x28,%rbp
7.02 f: mov %rbx,0x0(%rbp)
3.20 13: mov %r13,0x8(%rbp)
1.07 17: mov %r14,0x10(%rbp)
0.61 1b: mov %r15,0x18(%rbp)
0.11 1f: xor %eax,%eax
1.29 21: mov %rax,0x20(%rbp)
0.11 25: mov %rdi,%rbx
2.02 28: → callq *ffffffffda6776d9
2.76 2d: mov %eax,-0x148(%rbp)
33: mov %rbp,%rsi
36: add $0xfffffffffffffeb8,%rsi
3d: movabs $0xffff975ac2607800,%rdi
1.26 47: → callq *ffffffffda6789e9
4c: cmp $0x0,%rax
2.43 50: → je 0
52: add $0x38,%rax
0.21 56: xor %r13d,%r13d
0.81 59: cmp $0x0,%rax
5d: → jne 0
63: mov %rbp,%rdi
2.22 66: add $0xfffffffffffffeb8,%rdi
0.11 6d: mov $0x40,%esi
0.32 72: mov %rbx,%rdx
2.74 75: → callq *ffffffffda658409
0.22 7a: mov %rbp,%rsi
1.69 7d: add $0xfffffffffffffec0,%rsi
84: movabs $0xffff975bfcd36000,%rdi
8e: add $0xd0,%rdi
0.21 95: mov 0x0(%rsi),%eax
0.93 98: cmp $0x200,%rax
9f: → jae 0
0.10 a1: shl $0x3,%rax
0.11 a5: add %rdi,%rax
0.11 a8: → jmp 0
aa: xor %eax,%eax
1.07 ac: cmp $0x0,%rax
b0: → je 0
6.57 b6: movzbq 0x0(%rax),%rdi
bb: cmp $0x0,%rdi
0.95 bf: → je 0
c5: mov $0x40,%r8d
cb: mov -0x140(%rbp),%rdi
d2: cmp $0x2,%rdi
d6: → je 0
d8: cmp $0x101,%rdi
df: → je 0
e1: cmp $0x15,%rdi
e5: → jne 0
e7: mov 0x10(%rbx),%rdx
eb: → jmp 0
ed: mov 0x18(%rbx),%rdx
f1: cmp $0x0,%rdx
f5: → je 0
f7: xor %edi,%edi
f9: mov %edi,-0x104(%rbp)
ff: mov %rbp,%rdi
102: add $0xffffffffffffff00,%rdi
109: mov $0x100,%esi
10e: → callq *ffffffffda658499
113: mov $0x148,%r8d
119: mov %eax,-0x108(%rbp)
11f: mov %rax,%rdi
122: shl $0x20,%rdi
126: shr $0x20,%rdi
12a: cmp $0xff,%rdi
131: → ja 0
133: add $0x48,%rax
137: and $0xff,%rax
13d: mov %rax,%r8
140: mov %rbp,%rcx
143: add $0xfffffffffffffeb8,%rcx
14a: mov %rbx,%rdi
14d: movabs $0xffff975fbd72d800,%rsi
157: mov $0xffffffff,%edx
15c: → callq *ffffffffda658ad9
161: mov %rax,%r13
164: mov %r13,%rax
0.72 167: mov 0x0(%rbp),%rbx
16b: mov 0x8(%rbp),%r13
1.16 16f: mov 0x10(%rbp),%r14
0.10 173: mov 0x18(%rbp),%r15
0.42 177: add $0x28,%rbp
0.54 17b: leaveq
0.54 17c: ← retqAnother cool way to test all this is to symple use 'perf top' look for those symbols, go there and press enter, annotate it live :-)
--- tools/perf/util/annotate.c | 163 +++++++++++++++++++++++++++++++++++- tools/perf/util/annotate.h | 1 + tools/perf/util/bpf-event.c | 2 +- 3 files changed, 164 insertions(+), 2 deletions(-)
tools/perf/util/annotate.c +162 -1
@@ -10,6 +10,10 @@#include <errno.h> #include <inttypes.h> #include <libgen.h> +#include <bpf/bpf.h> +#include <bpf/btf.h> +#include <bpf/libbpf.h> +#include <linux/btf.h> #include "util.h" #include "ui/ui.h" #include "sort.h"
@@ -24,6 +28,7 @@#include "annotate.h" #include "evsel.h" #include "evlist.h" +#include "bpf-event.h" #include "block-range.h" #include "string2.h" #include "arch/common.h"
@@ -31,6 +36,7 @@#include <pthread.h> #include <linux/bitops.h> #include <linux/kernel.h> +#include <bpf/libbpf.h> /* FIXME: For the HE_COLORSET */ #include "ui/browser.h"
@@ -1615,6 +1621,9 @@ int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map * " --vmlinux vmlinux\n", build_id_msg ?: ""); }break ; +case SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF : +scnprintf (buf, buflen,"Please link with binutils's libopcode to enable BPF annotation" ); +break ;default :scnprintf (buf, buflen,"Internal error: Invalid %d error code\n" , errnum);break ;
@@ -1674,6 +1683,156 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t filreturn 0 ; } +#if defined(HAVE_LIBBFD_SUPPORT ) && defined(HAVE_LIBBPF_SUPPORT ) +#define PACKAGE "perf" +#include <bfd.h> +#include <dis-asm.h> + +static int symbol__disassemble_bpf (struct symbol *sym, +struct annotate_args *args) +{ +struct annotation *notes =symbol__annotation (sym); +struct annotation_options *opts = args->options; +struct bpf_prog_info_linear *info_linear; +struct bpf_prog_linfo *prog_linfo =NULL ; +struct bpf_prog_info_node *info_node; +int len = sym->end - sym->start; +disassembler_ftype disassemble; +struct map *map = args->ms.map; +struct disassemble_info info; +struct dso *dso = map->dso; +int pc =0 , count, sub_id; +struct btf *btf =NULL ; +char tpath[PATH_MAX ]; +size_t buf_size; +int nr_skip =0 ; +int ret =-1 ; +char *buf; +bfd *bfdf; +FILE *s; + +if (dso->binary_type !=DSO_BINARY_TYPE__BPF_PROG_INFO ) +return -1 ; + +pr_debug ("%s: handling sym %s addr %lx len %lx\n" , __func__, + sym->name, sym->start, sym->end - sym->start); + +memset (tpath,0 ,sizeof (tpath)); +perf_exe (tpath,sizeof (tpath)); + + bfdf =bfd_openr (tpath,NULL ); +assert (bfdf); +assert (bfd_check_format (bfdf, bfd_object)); + + s =open_memstream (&buf, &buf_size); +if (!s) + goto out; +init_disassemble_info (&info, s, + (fprintf_ftype ) fprintf); + + info.arch =bfd_get_arch (bfdf); + info.mach =bfd_get_mach (bfdf); + + info_node =perf_env__find_bpf_prog_info (dso->bpf_prog.env, + dso->bpf_prog.id); +if (!info_node) + goto out; + info_linear = info_node->info_linear; + sub_id = dso->bpf_prog.sub_id; + + info.buffer = (void *)(info_linear->info.jited_prog_insns); + info.buffer_length = info_linear->info.jited_prog_len; + +if (info_linear->info.nr_line_info) + prog_linfo =bpf_prog_linfo__new (&info_linear->info); + +if (info_linear->info.btf_id) { +struct btf_node *node; + + node =perf_env__find_btf (dso->bpf_prog.env, + info_linear->info.btf_id); +if (node) + btf =btf__new ((__u8 *)(node->data), + node->data_size); + } + +disassemble_init_for_target (&info); + +#ifdef DISASM_FOUR_ARGS_SIGNATURE + disassemble =disassembler (info.arch, +bfd_big_endian (bfdf), + info.mach, + bfdf); +#else + disassemble =disassembler (bfdf); +#endif +assert (disassemble); + +fflush (s); +do { +const struct bpf_line_info *linfo =NULL ; +struct disasm_line *dl; +size_t prev_buf_size; +const char *srcline; +u64 addr; + + addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id]; + count =disassemble (pc, &info); + +if (prog_linfo) + linfo =bpf_prog_linfo__lfind_addr_func (prog_linfo, + addr, sub_id, + nr_skip); + +if (linfo && btf) { + srcline =btf__name_by_offset (btf, linfo->line_off); + nr_skip++; + }else + srcline =NULL ; + +fprintf (s,"\n" ); + prev_buf_size = buf_size; +fflush (s); + +if (!opts->hide_src_code && srcline) { + args->offset =-1 ; + args->line =strdup (srcline); + args->line_nr =0 ; + args->ms.sym = sym; + dl =disasm_line__new (args); +if (dl) { +annotation_line__add (&dl->al, + ¬es->src->source); + } + } + + args->offset = pc; + args->line = buf + prev_buf_size; + args->line_nr =0 ; + args->ms.sym = sym; + dl =disasm_line__new (args); +if (dl) +annotation_line__add (&dl->al, ¬es->src->source); + + pc += count; + }while (count >0 && pc < len); + + ret =0 ; +out: +free (prog_linfo); +free (btf); +fclose (s); +bfd_close (bfdf); +return ret; +} +#else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT) +static int symbol__disassemble_bpf (struct symbol *sym__maybe_unused , +struct annotate_args *args__maybe_unused ) +{ +return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF ; +} +#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT) +static int symbol__disassemble (struct symbol *sym,struct annotate_args *args) {struct annotation_options *opts = args->options;
@@ -1701,7 +1860,9 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)pr_debug ("annotating [%p] %30s : [%p] %30s\n" , dso, dso->long_name, sym, sym->name); -if (dso__is_kcore (dso)) { +if (dso->binary_type ==DSO_BINARY_TYPE__BPF_PROG_INFO ) { +return symbol__disassemble_bpf (sym, args); + }else if (dso__is_kcore (dso)) { kce.kcore_filename = symfs_filename; kce.addr =map__rip_2objdump (map, sym->start); kce.offs = sym->start;
tools/perf/util/annotate.h +1 -0
@@ -369,6 +369,7 @@ enum symbol_disassemble_errno { __SYMBOL_ANNOTATE_ERRNO__START =-10000 ,SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START, +SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF , __SYMBOL_ANNOTATE_ERRNO__END, };
tools/perf/util/bpf-event.c +1 -1
@@ -46,7 +46,7 @@ static int machine__process_bpf_event_load(struct machine *machine, info_linear = info_node->info_linear;for (i =0 ; i < info_linear->info.nr_jited_ksyms; i++) { -u64 *addrs = (u64 *)(info_linear->info.jited_ksyms); +u64 *addrs = (u64 *)(uintptr_t )(info_linear->info.jited_ksyms);u64 addr = addrs[i];struct map *map;
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 41/44 perf evlist: Introduce side band thread
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
This patch introduces side band thread that captures extended information for events like PERF_RECORD_BPF_EVENT.
This new thread uses its own evlist that uses ring buffer with very low watermark for lower latency.
To use side band thread, we need to:
1. add side band event(s) by calling perf_evlist__add_sb_event();
2. calls perf_evlist__start_sb_thread();
3. at the end of perf run, perf_evlist__stop_sb_thread().
In the next patch, we use this thread to handle PERF_RECORD_BPF_EVENT.
Committer notes:
Add fix by Jiri Olsa for when te sb_tread can't get started and then at the end the stop_sb_thread() segfaults when joining the (non-existing) thread.
That can happen when running 'perf top' or 'perf record' as a normal user, for instance.
Further checks need to be done on top of this to more graciously handle these possible failure scenarios.
--- tools/perf/builtin-record.c | 9 +++ tools/perf/builtin-top.c | 9 +++ tools/perf/util/evlist.c | 119 ++++++++++++++++++++++++++++++++++++ tools/perf/util/evlist.h | 12 ++++ tools/perf/util/evsel.h | 6 ++ 5 files changed, 155 insertions(+)
tools/perf/builtin-record.c +9 -0
@@ -1137,6 +1137,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)struct perf_data *data = &rec->data;struct perf_session *session;bool disabled = false, draining = false; +struct perf_evlist *sb_evlist =NULL ;int fd;atexit (record__sig_exit);
@@ -1237,6 +1238,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_child; } +if (perf_evlist__start_sb_thread (sb_evlist, &rec->opts.target)) { +pr_debug ("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n" ); + opts->no_bpf_event = true; + } + err =record__synthesize (rec, false);if (err <0 ) goto out_child;
@@ -1487,6 +1493,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) out_delete_session:perf_session__delete (session); + +if (!opts->no_bpf_event) +perf_evlist__stop_sb_thread (sb_evlist);return status; }
tools/perf/builtin-top.c +9 -0
@@ -1501,6 +1501,7 @@ int cmd_top(int argc, const char **argv) "number of thread to run event synthesize"),OPT_END () }; +struct perf_evlist *sb_evlist =NULL ;const char *const top_usage[] = {"perf top [<options>]" ,NULL
@@ -1636,8 +1637,16 @@ int cmd_top(int argc, const char **argv) goto out_delete_evlist; } +if (perf_evlist__start_sb_thread (sb_evlist, target)) { +pr_debug ("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n" ); + opts->no_bpf_event = true; + } + status =__cmd_top (&top); +if (!opts->no_bpf_event) +perf_evlist__stop_sb_thread (sb_evlist); + out_delete_evlist:perf_evlist__delete (top.evlist);perf_session__delete (top.session);
tools/perf/util/evlist.c +119 -0
128 lines not on this page · raw message
tools/perf/util/evlist.h +12 -0
@@ -54,6 +54,10 @@ struct perf_evlist { struct perf_sample *sample);u64 first_sample_time;u64 last_sample_time; +struct { +pthread_t th; +volatile int done; + } thread; };struct perf_evsel_str_handler {
@@ -87,6 +91,14 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,int perf_evlist__add_dummy (struct perf_evlist *evlist); +int perf_evlist__add_sb_event (struct perf_evlist **evlist, +struct perf_event_attr *attr, +perf_evsel__sb_cb_t cb, +void *data); +int perf_evlist__start_sb_thread (struct perf_evlist *evlist, +struct target *target); +void perf_evlist__stop_sb_thread (struct perf_evlist *evlist); +int perf_evlist__add_newtp (struct perf_evlist *evlist,const char *sys,const char *name,void *handler);
tools/perf/util/evsel.h +6 -0
@@ -73,6 +73,8 @@ struct perf_evsel_config_term {struct perf_stat_evsel ; +typedef int (perf_evsel__sb_cb_t )(union perf_event *event,void *data); +/** struct perf_evsel - event selector * * @evlist - evlist this evsel is in, if it is in one.
@@ -151,6 +153,10 @@ struct perf_evsel {bool collect_stat;bool weak_group;const char *pmu_name; +struct { +perf_evsel__sb_cb_t *cb; +void *data; + } side_band; };union u64_swap {
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 42/44 perf tools: Save bpf_prog_info and BTF of new BPF programs
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
To fully annotate BPF programs with source code mapping, 4 different information are needed:
1) PERF_RECORD_KSYMBOL
2) PERF_RECORD_BPF_EVENT
3) bpf_prog_info
4) btf
This patch handles 3) and 4) for BPF programs loaded after 'perf record|top'.
For timely process of these information, a dedicated event is added to the side band evlist.
When PERF_RECORD_BPF_EVENT is received via the side band event, the polling thread gathers 3) and 4) vis sys_bpf and store them in perf_env.
This information is saved to perf.data at the end of 'perf record'.
Committer testing:
The 'wakeup_watermark' member in 'struct perf_event_attr' is inside a unnamed union, so can't be used in a struct designated initialization with older gccs, get it out of that, isolating as 'attr.wakeup_watermark = 1;' to work with all gcc versions.
We also need to add '--no-bpf-event' to the 'perf record' perf_event_attr tests in 'perf test', as the way that that test goes is to intercept the events being setup and looking if they match the fields described in the control files, since now it finds first the side band event used to catch the PERF_RECORD_BPF_EVENT, they all fail.
With these issues fixed:
Same scenario as for testing BPF programs loaded before 'perf record' or 'perf top' starts, only start the BPF programs after 'perf record|top', so that its information get collected by the sideband threads, the rest works as for the programs loaded before start monitoring.
Add missing 'inline' to the bpf_event__add_sb_event() when HAVE_LIBBPF_SUPPORT is not defined, fixing the build in systems without binutils devel files installed.
--- tools/perf/builtin-record.c | 3 + tools/perf/builtin-top.c | 3 + tools/perf/tests/attr/test-record-C0 | 2 +- tools/perf/tests/attr/test-record-basic | 2 +- tools/perf/tests/attr/test-record-branch-any | 2 +- .../tests/attr/test-record-branch-filter-any | 2 +- .../attr/test-record-branch-filter-any_call | 2 +- .../attr/test-record-branch-filter-any_ret | 2 +- .../tests/attr/test-record-branch-filter-hv | 2 +- .../attr/test-record-branch-filter-ind_call | 2 +- .../tests/attr/test-record-branch-filter-k | 2 +- .../tests/attr/test-record-branch-filter-u | 2 +- tools/perf/tests/attr/test-record-count | 2 +- tools/perf/tests/attr/test-record-data | 2 +- tools/perf/tests/attr/test-record-freq | 2 +- .../perf/tests/attr/test-record-graph-default | 2 +- tools/perf/tests/attr/test-record-graph-dwarf | 2 +- tools/perf/tests/attr/test-record-graph-fp | 2 +- tools/perf/tests/attr/test-record-group | 2 +- .../tests/attr/test-record-group-sampling | 2 +- tools/perf/tests/attr/test-record-group1 | 2 +- .../perf/tests/attr/test-record-no-buffering | 2 +- tools/perf/tests/attr/test-record-no-inherit | 2 +- tools/perf/tests/attr/test-record-no-samples | 2 +- tools/perf/tests/attr/test-record-period | 2 +- tools/perf/tests/attr/test-record-raw | 2 +- tools/perf/util/bpf-event.c | 100 ++++++++++++++++++ tools/perf/util/bpf-event.h | 15 +++ 28 files changed, 145 insertions(+), 24 deletions(-)
tools/perf/builtin-record.c +3 -0
@@ -1238,6 +1238,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_child; } +if (!opts->no_bpf_event) +bpf_event__add_sb_event (&sb_evlist, &session->header.env); +if (perf_evlist__start_sb_thread (sb_evlist, &rec->opts.target)) {pr_debug ("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n" ); opts->no_bpf_event = true;
tools/perf/builtin-top.c +3 -0
@@ -1637,6 +1637,9 @@ int cmd_top(int argc, const char **argv) goto out_delete_evlist; } +if (!top.record_opts.no_bpf_event) +bpf_event__add_sb_event (&sb_evlist, &perf_env); +if (perf_evlist__start_sb_thread (sb_evlist, target)) {pr_debug ("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n" ); opts->no_bpf_event = true;
tools/perf/tests/attr/test-record-C0 +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -C 0 kill >/dev/null 2>&1 +args = --no-bpf-event -C 0 kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-basic +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = kill >/dev/null 2>&1 +args = --no-bpf-event kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-branch-any +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -b kill >/dev/null 2>&1 +args = --no-bpf-event -b kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-branch-filter-any +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -j any kill >/dev/null 2>&1 +args = --no-bpf-event -j any kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-branch-filter-any_call +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -j any_call kill >/dev/null 2>&1 +args = --no-bpf-event -j any_call kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-branch-filter-any_ret +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -j any_ret kill >/dev/null 2>&1 +args = --no-bpf-event -j any_ret kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-branch-filter-hv +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -j hv kill >/dev/null 2>&1 +args = --no-bpf-event -j hv kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-branch-filter-ind_call +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -j ind_call kill >/dev/null 2>&1 +args = --no-bpf-event -j ind_call kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-branch-filter-k +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -j k kill >/dev/null 2>&1 +args = --no-bpf-event -j k kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-branch-filter-u +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -j u kill >/dev/null 2>&1 +args = --no-bpf-event -j u kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-count +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -c 123 kill >/dev/null 2>&1 +args = --no-bpf-event -c 123 kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-data +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -d kill >/dev/null 2>&1 +args = --no-bpf-event -d kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-freq +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -F 100 kill >/dev/null 2>&1 +args = --no-bpf-event -F 100 kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-graph-default +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -g kill >/dev/null 2>&1 +args = --no-bpf-event -g kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-graph-dwarf +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = --call-graph dwarf -- kill >/dev/null 2>&1 +args = --no-bpf-event --call-graph dwarf -- kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-graph-fp +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = --call-graph fp kill >/dev/null 2>&1 +args = --no-bpf-event --call-graph fp kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-group +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = --group -e cycles,instructions kill >/dev/null 2>&1 +args = --no-bpf-event --group -e cycles,instructions kill >/dev/null 2>&1 ret = 1 [event-1:base-record]
tools/perf/tests/attr/test-record-group-sampling +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 +args = --no-bpf-event -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 ret = 1 [event-1:base-record]
tools/perf/tests/attr/test-record-group1 +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -e '{cycles,instructions}' kill >/dev/null 2>&1 +args = --no-bpf-event -e '{cycles,instructions}' kill >/dev/null 2>&1 ret = 1 [event-1:base-record]
tools/perf/tests/attr/test-record-no-buffering +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = --no-buffering kill >/dev/null 2>&1 +args = --no-bpf-event --no-buffering kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-no-inherit +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -i kill >/dev/null 2>&1 +args = --no-bpf-event -i kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-no-samples +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -n kill >/dev/null 2>&1 +args = --no-bpf-event -n kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-period +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -c 100 -P kill >/dev/null 2>&1 +args = --no-bpf-event -c 100 -P kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/tests/attr/test-record-raw +1 -1
@@ -1,6 +1,6 @@ [config] command = record -args = -R kill >/dev/null 2>&1 +args = --no-bpf-event -R kill >/dev/null 2>&1 ret = 1 [event:base-record]
tools/perf/util/bpf-event.c +100 -0
109 lines not on this page · raw message
tools/perf/util/bpf-event.h +15 -0
@@ -4,12 +4,17 @@#include <linux/compiler.h> #include <linux/rbtree.h> +#include <pthread.h> +#include <api/fd/array.h> #include "event.h" struct machine ;union perf_event ; +struct perf_env ;struct perf_sample ;struct record_opts ; +struct evlist ; +struct target ;struct bpf_prog_info_node {struct bpf_prog_info_linear *info_linear;
@@ -31,6 +36,9 @@ int perf_event__synthesize_bpf_events(struct perf_session *session,perf_event__handler_t process, struct machine *machine, struct record_opts *opts); +int bpf_event__add_sb_event (struct perf_evlist **evlist, +struct perf_env *env); +#else static inline int machine__process_bpf_event(struct machine *machine __maybe_unused, union perf_event *event __maybe_unused,
@@ -46,5 +54,12 @@ static inline int perf_event__synthesize_bpf_events(struct perf_session *session {return 0 ; } + +static inline int bpf_event__add_sb_event (struct perf_evlist **evlist__maybe_unused , +struct perf_env *env__maybe_unused ) +{ +return 0 ; +} +#endif // HAVE_LIBBPF_SUPPORT #endif
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 43/44 perf bpf: Extract logic to create program names from perf_event__synthesize_one_bpf_prog()
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
Extract logic to create program names to synthesize_bpf_prog_name(), so that it can be reused in header.c:print_bpf_prog_info().
This commit doesn't change the behavior.
--- tools/perf/util/bpf-event.c | 62 +++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 27 deletions(-)
tools/perf/util/bpf-event.c +35 -27
@@ -111,6 +111,38 @@ static int perf_env__fetch_btf(struct perf_env *env,return 0 ; } +static int synthesize_bpf_prog_name (char *buf,int size, +struct bpf_prog_info *info, +struct btf *btf, +u32 sub_id) +{ +u8 (*prog_tags)[BPF_TAG_SIZE ] = (void *)(uintptr_t )(info->prog_tags); +void *func_infos = (void *)(uintptr_t )(info->func_info); +u32 sub_prog_cnt = info->nr_jited_ksyms; +const struct bpf_func_info *finfo; +const char *short_name =NULL ; +const struct btf_type *t; +int name_len; + + name_len =snprintf (buf, size,"bpf_prog_" ); + name_len +=snprintf_hex (buf + name_len, size - name_len, + prog_tags[sub_id],BPF_TAG_SIZE ); +if (btf) { + finfo = func_infos + sub_id * info->func_info_rec_size; + t =btf__type_by_id (btf, finfo->type_id); + short_name =btf__name_by_offset (btf, t->name_off); + }else if (sub_id ==0 && sub_prog_cnt ==1 ) { +/* no subprog */ +if (info->name[0 ]) + short_name = info->name; + }else + short_name ="F" ; +if (short_name) + name_len +=snprintf (buf + name_len, size - name_len, +"_%s" , short_name); +return name_len; +} +/* * Synthesize PERF_RECORD_KSYMBOL and PERF_RECORD_BPF_EVENT for one bpf * program. One PERF_RECORD_BPF_EVENT is generated for the program. And
@@ -135,7 +167,6 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,struct bpf_prog_info_node *info_node;struct bpf_prog_info *info;struct btf *btf =NULL ; -bool has_btf = false;struct perf_env *env;u32 sub_prog_cnt, i;int err =0 ;
@@ -189,19 +220,13 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, btf =NULL ; goto out; } - has_btf = true;perf_env__fetch_btf (env, info->btf_id, btf); }/* Synthesize PERF_RECORD_KSYMBOL */ for (i =0 ; i < sub_prog_cnt; i++) { -u8 (*prog_tags)[BPF_TAG_SIZE ] = (void *)(uintptr_t )(info->prog_tags); -__u32 *prog_lens = (__u32 *)(uintptr_t )(info->jited_func_lens); +__u32 *prog_lens = (__u32 *)(uintptr_t )(info->jited_func_lens);__u64 *prog_addrs = (__u64 *)(uintptr_t )(info->jited_ksyms); -void *func_infos = (void *)(uintptr_t )(info->func_info); -const struct bpf_func_info *finfo; -const char *short_name =NULL ; -const struct btf_type *t;int name_len; *ksymbol_event = (struct ksymbol_event ){
@@ -214,26 +239,9 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, .ksym_type = PERF_RECORD_KSYMBOL_TYPE_BPF, .flags = 0, }; - name_len =snprintf (ksymbol_event->name,KSYM_NAME_LEN , -"bpf_prog_" ); - name_len +=snprintf_hex (ksymbol_event->name + name_len, -KSYM_NAME_LEN - name_len, - prog_tags[i],BPF_TAG_SIZE ); -if (has_btf) { - finfo = func_infos + i * info->func_info_rec_size; - t =btf__type_by_id (btf, finfo->type_id); - short_name =btf__name_by_offset (btf, t->name_off); - }else if (i ==0 && sub_prog_cnt ==1 ) { -/* no subprog */ -if (info->name[0 ]) - short_name = info->name; - }else - short_name ="F" ; -if (short_name) - name_len +=snprintf (ksymbol_event->name + name_len, -KSYM_NAME_LEN - name_len, -"_%s" , short_name); + name_len =synthesize_bpf_prog_name (ksymbol_event->name, +KSYM_NAME_LEN , info, btf, i); ksymbol_event->header.size +=PERF_ALIGN (name_len +1 ,sizeof (u64));
Signature · 1 line
2.20.1
Arnaldo Carvalho de Melo
maintainerPATCH 44/44 perf bpf: Show more BPF program info in print_bpf_prog_info()
In reply to Arnaldo Carvalho de MeloFrom: Song Liu <[email protected]>
This patch enables showing bpf program name, address, and size in the header.
Before the patch:
perf report --header-only ... # bpf_prog_info of id 9 # bpf_prog_info of id 10 # bpf_prog_info of id 13
After the patch:
# bpf_prog_info 9: bpf_prog_7be49e3934a125ba addr 0xffffffffa0024947 size 229 # bpf_prog_info 10: bpf_prog_2a142ef67aaad174 addr 0xffffffffa007c94d size 229 # bpf_prog_info 13: bpf_prog_47368425825d7384_task__task_newt addr 0xffffffffa0251137 size 369
Committer notes:
Fix the fallback definition when HAVE_LIBBPF_SUPPORT is not defined, i.e. add the missing 'static inline' and add the __maybe_unused to the args. Also add stdio.h since we now use FILE * in bpf-event.h.
--- tools/perf/util/bpf-event.c | 40 +++++++++++++++++++++++++++++++++++++ tools/perf/util/bpf-event.h | 11 +++++++++- tools/perf/util/header.c | 5 +++-- 3 files changed, 53 insertions(+), 3 deletions(-)
tools/perf/util/bpf-event.c +40 -0
@@ -438,3 +438,43 @@ int bpf_event__add_sb_event(struct perf_evlist **evlist,return perf_evlist__add_sb_event (evlist, &attr, bpf_event__sb_cb, env); } + +void bpf_event__print_bpf_prog_info (struct bpf_prog_info *info, +struct perf_env *env, +FILE *fp) +{ +__u32 *prog_lens = (__u32 *)(uintptr_t )(info->jited_func_lens); +__u64 *prog_addrs = (__u64 *)(uintptr_t )(info->jited_ksyms); +char name[KSYM_NAME_LEN ]; +struct btf *btf =NULL ; +u32 sub_prog_cnt, i; + + sub_prog_cnt = info->nr_jited_ksyms; +if (sub_prog_cnt != info->nr_prog_tags || + sub_prog_cnt != info->nr_jited_func_lens) +return ; + +if (info->btf_id) { +struct btf_node *node; + + node =perf_env__find_btf (env, info->btf_id); +if (node) + btf =btf__new ((__u8 *)(node->data), + node->data_size); + } + +if (sub_prog_cnt ==1 ) { +synthesize_bpf_prog_name (name,KSYM_NAME_LEN , info, btf,0 ); +fprintf (fp,"# bpf_prog_info %u: %s addr 0x%llx size %u\n" , + info->id, name, prog_addrs[0 ], prog_lens[0 ]); +return ; + } + +fprintf (fp,"# bpf_prog_info %u:\n" , info->id); +for (i =0 ; i < sub_prog_cnt; i++) { +synthesize_bpf_prog_name (name,KSYM_NAME_LEN , info, btf, i); + +fprintf (fp,"# \tsub_prog %u: %s addr 0x%llx size %u\n" , + i, name, prog_addrs[i], prog_lens[i]); + } +}
tools/perf/util/bpf-event.h +10 -1
@@ -7,6 +7,7 @@#include <pthread.h> #include <api/fd/array.h> #include "event.h" +#include <stdio.h> struct machine ;union perf_event ;
@@ -38,7 +39,9 @@ int perf_event__synthesize_bpf_events(struct perf_session *session, struct record_opts *opts);int bpf_event__add_sb_event (struct perf_evlist **evlist,struct perf_env *env); - +void bpf_event__print_bpf_prog_info (struct bpf_prog_info *info, +struct perf_env *env, +FILE *fp);#else static inline int machine__process_bpf_event(struct machine *machine __maybe_unused, union perf_event *event __maybe_unused,
@@ -61,5 +64,11 @@ static inline int bpf_event__add_sb_event(struct perf_evlist **evlist __maybe_unreturn 0 ; } +static inline void bpf_event__print_bpf_prog_info (struct bpf_prog_info *info__maybe_unused , +struct perf_env *env__maybe_unused , +FILE *fp__maybe_unused ) +{ + +}#endif // HAVE_LIBBPF_SUPPORT #endif
tools/perf/util/header.c +3 -2
@@ -1468,8 +1468,9 @@ static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp) node = rb_entry(next, struct bpf_prog_info_node, rb_node); next =rb_next (&node->rb_node); -fprintf (fp,"# bpf_prog_info of id %u\n" , - node->info_linear->info.id); + +bpf_event__print_bpf_prog_info (&node->info_linear->info, + env, fp); }up_read (&env->bpf_progs.lock);
Signature · 1 line
2.20.1