perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Mostly a 'perf annotate' refactoring to allow reusing the TUI
formatting routines in a --stdio2 mode for 'perf annotate' that at some point should replace --stdio, leaving that old code deprecated for a while, then ditching it.
That will take a while yet because there is some stuff in the
--stdio code that needs to be done in the annotation UI agnostic core to then get used in --tui and --stdio2.
There is also some improvements for issues Linus reported in the
TUI annotation code for ASM functions.
Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit ecd380b8dead1bad67e3af87e2ddfe826c3da79d:
Merge tag 'perf-core-for-mingo-4.17-20180319' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2018-03-19 20:37:48 +0100)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-4.17-20180323
for you to fetch changes up to 980b68ec0694f250e967cb18c5705ef5de10fdd5:
perf annotate: Use absolute addresses to calculate jump target offsets (2018-03-23 16:46:53 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
- Move non-TUI specific annotation routines out of the TUI browser so that it can be used in other UIs, and to demonstrate that introduce a 'perf annotate --stdio2' option that will apply those formatting routines to provide a non-interactive annotation mode (Arnaldo Carvalho de Melo)
- Add 'P' hotkey to the annotation TUI, so dump the current annotated symbol to a file, easing report thru e-mail, by getting rid of the spaces + right hand side scrollbar chars (Arnaldo Carvalho de Melo)
- Support --ignore-vmlinux to 'perf report' and 'perf annotate', that
was already present in 'perf top', to use /proc/{kcore,kallsyms}, allowing to see what is in fact running (patched stuff, alternatives, ftrace, etc), not the initial state of the kernel (vmlinux) (Arnaldo Carvalho de Melo)
- Support 'jump' instructions to a different function, treating them as 'call' instructions (Arnaldo Carvalho de Melo)
- Fix some jump artifacts when using vmlinux + ASM functions, where the ELF symtab for instance, for entry_SYSCALL_64 includes that and what comes after the 'syscall_return_via_sysret' label, but the objdump -dS prints the jump targets + offsets using the syscall_return_via_sysret address, which was confusing 'perf annotate'. See the cset comments for further info (Arnaldo Carvalho de Melo)
- Report error from dwfl_attach_state() in the unwind code (Martin Vuille)
- Reference Py_None before returning it in the python extension (Petr Machata)
----------------------------------------------------------------
Arnaldo Carvalho de Melo (42):
perf annotate: Move annotation_options out of the TUI browser perf annotate: Move cycles/IPC formatting width constants outside TUI perf annotate tui: Use annotate_browser__cycles_width() mroe perf annotate tui: Move have_cycles to struct annotation
perf annotate: Move annotation_line array from TUI to generic code perf annotate: Move compute_ipc() to annotation library
perf annotate: Move nr_events from annotate_browser to annotation struct perf annotate: Stop using a global config struct
perf annotate: Move pcnt_with() to the annotation library
perf annotate tui: Add browser__annotation() helper
perf annotate: Move max_jump_sources to struct annotation
perf annotate: Move jumps_percent_color to ui_browser
perf annotate: Move nr_jumps to struct annotation
perf annotate: Move mark_jump_targets from the TUI to the annotation library perf annotate: Nuke struct browser_line
perf annotate: Move 'start' to struct annotation
perf annotate: Move nr_{asm_}entries to struct annotation
perf annotate: Introduce set_offsets() method out of TUI code perf annotate: Move the column widths from the TUI to generic lib perf annotate: Move update_column_widths() to the generic lib perf annotate: Introduce init_column_widths() method out of TUI code perf annotate: Introduce symbol__annotate2 method
perf annotate: Introduce annotation_line__max_percent()
perf ui browser: Add vprintf() method
perf annotate: Introduce annotation_line__print_start() out of TUI code perf annotate: Finish the generalization of annotate_browser__write() perf annotate: Use a ops table for annotation_line__write() perf annotate: Introduce annotation_line__filter()
perf annotate: Introduce the --stdio2 output mode
perf annotate: Move the default annotate options to the library perf annotate: Use the default annotation options for --stdio2 perf annotate: Add function header to --stdio2
perf annotate: Introduce --ignore-vmlinux command line option perf report: Introduce --ignore-vmlinux command line option perf annotate browser: Add 'P' hotkey to dump annotation to file perf annotate: No need to calculate notes->start twice
perf annotate: Pass function descriptor to its instruction parsing routines perf annotate: Mark jumps to outher functions with the call arrow perf annotate: Add "_local" to jump/offset validation routines perf annotate: Support jumping from one function to another perf annotate: Defer searching for comma in raw line till it is needed perf annotate: Use absolute addresses to calculate jump target offsets
Martin Vuille (1):
perf unwind: Report error from dwfl_attach_state
Petr Machata (1):
perf python: Reference Py_None before returning it
tools/perf/Documentation/perf-annotate.txt | 5 + tools/perf/Documentation/perf-report.txt | 3 + tools/perf/arch/s390/annotate/instructions.c | 5 +- tools/perf/builtin-annotate.c | 27 +- tools/perf/builtin-report.c | 3 + tools/perf/builtin-top.c | 2 + tools/perf/ui/browser.c | 9 +- tools/perf/ui/browser.h | 3 +- tools/perf/ui/browsers/annotate.c | 686 ++++++--------------------- tools/perf/util/annotate.c | 679 +++++++++++++++++++++++++- tools/perf/util/annotate.h | 102 +++- tools/perf/util/python.c | 4 +- tools/perf/util/unwind-libdw.c | 3 +- 13 files changed, 944 insertions(+), 587 deletions(-)
Test results:
The first ones are container (docker) based builds of tools/perf with and without libelf support. Where clang is available, it is also used to build perf with/without libelf.
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.
# 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:edge : Ok gcc (Alpine 6.4.0) 6.4.0 6 amazonlinux:1 : Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11) 7 amazonlinux:2 : Ok gcc (GCC) 7.2.1 20170915 (Red Hat 7.2.1-2) 8 android-ndk:r12b-arm : Ok arm-linux-androideabi-gcc (GCC) 4.9.x 20150123 (prerelease) 9 android-ndk:r15c-arm : Ok arm-linux-androideabi-gcc (GCC) 4.9.x 20150123 (prerelease) 10 centos:5 : Ok gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-55) 11 centos:6 : Ok gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18) 12 centos:7 : Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16) 13 debian:7 : Ok gcc (Debian 4.7.2-5) 4.7.2 14 debian:8 : Ok gcc (Debian 4.9.2-10+deb8u1) 4.9.2 15 debian:9 : Ok gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516 16 debian:experimental : Ok gcc (Debian 7.3.0-12) 7.3.0 17 debian:experimental-x-arm64 : Ok aarch64-linux-gnu-gcc (Debian 7.3.0-12) 7.3.0 18 debian:experimental-x-mips : Ok mips-linux-gnu-gcc (Debian 7.3.0-12) 7.3.0 19 debian:experimental-x-mips64 : Ok mips64-linux-gnuabi64-gcc (Debian 7.3.0-11) 7.3.0 20 debian:experimental-x-mipsel : Ok mipsel-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 21 fedora:20 : Ok gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7) 22 fedora:21 : Ok gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6) 23 fedora:22 : Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) 24 fedora:23 : Ok gcc (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) 25 fedora:24 : Ok gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1) 26 fedora:24-x-ARC-uClibc : Ok arc-linux-gcc (ARCompact ISA Linux uClibc toolchain 2017.09-rc2) 7.1.1 20170710 27 fedora:25 : Ok gcc (GCC) 6.4.1 20170727 (Red Hat 6.4.1-1) 28 fedora:26 : Ok gcc (GCC) 7.3.1 20180130 (Red Hat 7.3.1-2) 29 fedora:27 : Ok gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5) 30 fedora:rawhide : Ok gcc (GCC) 8.0.1 20180222 (Red Hat 8.0.1-0.16) 31 gentoo-stage3-amd64:latest : Ok gcc (Gentoo 6.4.0-r1 p1.3) 6.4.0 32 mageia:5 : Ok gcc (GCC) 4.9.2 33 mageia:6 : Ok gcc (Mageia 5.5.0-1.mga6) 5.5.0 34 opensuse:42.1 : Ok gcc (SUSE Linux) 4.8.5 35 opensuse:42.2 : Ok gcc (SUSE Linux) 4.8.5 36 opensuse:42.3 : Ok gcc (SUSE Linux) 4.8.5 37 opensuse:tumbleweed : Ok gcc (SUSE Linux) 7.3.0 38 oraclelinux:6 : Ok gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18) 39 oraclelinux:7 : Ok gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16.0.3) 40 ubuntu:12.04.5 : Ok gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 41 ubuntu:14.04.4 : Ok gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 42 ubuntu:14.04.4-x-linaro-arm64 : Ok aarch64-linux-gnu-gcc (Linaro GCC 5.4-2017.05) 5.4.1 20170404 43 ubuntu:15.04 : Ok gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2 44 ubuntu:16.04 : Ok gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 45 ubuntu:16.04-x-arm : Ok arm-linux-gnueabihf-gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 46 ubuntu:16.04-x-arm64 : Ok aarch64-linux-gnu-gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 47 ubuntu:16.04-x-powerpc : Ok powerpc-linux-gnu-gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 48 ubuntu:16.04-x-powerpc64 : Ok powerpc64-linux-gnu-gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 48 ubuntu:16.04-x-powerpc64 : Ok powerpc64-linux-gnu-gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 49 ubuntu:16.04-x-powerpc64el : Ok powerpc64le-linux-gnu-gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 50 ubuntu:16.04-x-s390 : Ok s390x-linux-gnu-gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 51 ubuntu:16.10 : Ok gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005 52 ubuntu:17.04 : Ok gcc (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406 53 ubuntu:17.10 : Ok gcc (Ubuntu 7.2.0-8ubuntu3) 7.2.0 54 ubuntu:18.04 : Ok gcc (Ubuntu 7.2.0-16ubuntu1) 7.2.0
# uname -a Linux jouet 4.16.0-rc5-00086-gdf09348f78dc #1 SMP Fri Mar 16 09:46:40 -03 2018 x86_64 x86_64 x86_64 GNU/Linux # 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 : Skip 22: Number of exit events of a simple workload : Ok 23: Software clock events period values : Ok 24: Object code reading : Ok 25: Sample parsing : Ok 26: Use a dummy software event to keep tracking : Ok 27: Parse with no sample_id_all bit set : Ok 28: Filter hist entries : Ok 29: Lookup mmap thread : Ok 30: Share thread mg : Ok 31: Sort output of hist entries : Ok 32: Cumulate child hist entries : Ok 33: Track with sched_switch : Ok 34: Filter fds with revents mask in a fdarray : Ok 35: Add fd to a fdarray, making it autogrow : Ok 36: kmod_path__parse : Ok 37: Thread map : Ok 38: LLVM search and compile : 38.1: Basic BPF llvm compile : Ok 38.2: kbuild searching : Ok 38.3: Compile source for BPF prologue generation : Ok 38.4: Compile source for BPF relocation : Ok 39: Session topology : Ok 40: BPF filter : 40.1: Basic BPF filtering : Ok 40.2: BPF pinning : Ok 40.3: BPF prologue generation : Ok 40.4: BPF relocation checker : Ok 41: Synthesize thread map : Ok 42: Remove thread map : Ok 43: Synthesize cpu map : Ok 44: Synthesize stat config : Ok 45: Synthesize stat : Ok 46: Synthesize stat round : Ok 47: Synthesize attr update : Ok 48: Event times : Ok 49: Read backward ring buffer : Ok 50: Print cpu map : Ok 51: Probe SDT events : Ok 52: is_printable_array : Ok 53: Print bitmap : Ok 54: perf hooks : Ok 55: builtin clang support : Skip (not compiled in) 56: unit_number__scnprintf : Ok 57: mem2node : Ok 58: x86 rdpmc : Ok 59: Convert perf time to TSC : Ok 60: DWARF unwind : Ok 61: x86 instruction decoder - new instructions : Ok 62: Use vfs_getname probe to get syscall args filenames : Ok 63: probe libc's inet_pton & backtrace it with ping : Ok 64: Check open filename arg using perf trace + vfs_getname: Ok 65: probe libc's inet_pton & backtrace it with ping : Ok 66: Add vfs_getname probe to get syscall args filenames : Ok #
$ make -C tools/perf build-test
make: Entering directory '/home/acme/git/perf/tools/perf'
- tarpkg: ./tests/perf-targz-src-pkg .
make_install_prefix_slash_O: make install prefix=/tmp/krava/
make_no_libpython_O: make NO_LIBPYTHON=1
make_no_libelf_O: make NO_LIBELF=1
make_perf_o_O: make perf.o
make_doc_O: make doc
make_no_libunwind_O: make NO_LIBUNWIND=1
make_with_babeltrace_O: make LIBBABELTRACE=1
make_install_bin_O: make install-bin
make_no_libbionic_O: make NO_LIBBIONIC=1
make_debug_O: make DEBUG=1
make_static_O: make LDFLAGS=-static
make_no_slang_O: make NO_SLANG=1
make_no_libbpf_O: make NO_LIBBPF=1
make_no_libdw_dwarf_unwind_O: make NO_LIBDW_DWARF_UNWIND=1
make_no_newt_O: make NO_NEWT=1
make_tags_O: make tags
make_util_map_o_O: make util/map.o
make_no_auxtrace_O: make NO_AUXTRACE=1
make_with_clangllvm_O: make LIBCLANGLLVM=1
make_install_prefix_O: make install prefix=/tmp/krava
make_no_libnuma_O: make NO_LIBNUMA=1
make_no_ui_O: make NO_NEWT=1 NO_SLANG=1 NO_GTK2=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_install_O: make install
make_pure_O: make
make_no_libaudit_O: make NO_LIBAUDIT=1
make_no_scripts_O: make NO_LIBPYTHON=1 NO_LIBPERL=1
make_no_demangle_O: make NO_DEMANGLE=1
make_help_O: make help
make_util_pmu_bison_o_O: make util/pmu-bison.o
make_no_gtk2_O: make NO_GTK2=1
make_no_backtrace_O: make NO_BACKTRACE=1
make_no_libperl_O: make NO_LIBPERL=1
make_clean_all_O: make clean all
OK
make: Leaving directory '/home/acme/git/perf/tools/perf'
$Arnaldo Carvalho de Melo
maintainerPATCH 1/44 perf unwind: Report error from dwfl_attach_state
From: Martin Vuille <[email protected]>
In verbose level 2, errors returned by libdw are reported in most cases, but not when calling dwfl_attach_state.
Since elfutils v 0.160 (2014), dwfl_attach_state sets the error code to report failure cause. On failure, log the reported error.
--- tools/perf/util/unwind-libdw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/unwind-libdw.c +2 -1
@@ -236,7 +236,8 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,if (err) goto out; -if (!dwfl_attach_state (ui->dwfl,EM_NONE , thread->tid, &callbacks, ui)) + err = !dwfl_attach_state (ui->dwfl,EM_NONE , thread->tid, &callbacks, ui); +if (err) goto out; err =dwfl_getthread_frames (ui->dwfl, thread->tid, frame_callback, ui);
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 2/44 perf annotate: Move annotation_options out of the TUI browser
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This will be useful when making parts of the TUI browser generic enough to be used for a new stdio mode, available even when the TUI is not built in, for explicit user decision or when the necessary library devel files, for the slang library currently, are not available in the build system.
--- tools/perf/ui/browsers/annotate.c | 10 +--------- tools/perf/util/annotate.h | 10 ++++++++++ 2 files changed, 11 insertions(+), 9 deletions(-)
tools/perf/ui/browsers/annotate.c +1 -9
@@ -31,15 +31,7 @@ struct browser_line {int jump_sources; }; -static struct annotate_browser_opt { -bool hide_src_code, - use_offset, - jump_arrows, - show_linenr, - show_nr_jumps, - show_nr_samples, - show_total_period; -} annotate_browser__opts = { +static struct annotation_options annotate_browser__opts = { .use_offset = true, .jump_arrows = true, };
tools/perf/util/annotate.h +10 -0
@@ -58,6 +58,16 @@ bool ins__is_lock(const struct ins *ins);int ins__scnprintf (struct ins *ins,char *bf,size_t size,struct ins_operands *ops);bool ins__is_fused (struct arch *arch,const char *ins1,const char *ins2); +struct annotation_options { +bool hide_src_code, + use_offset, + jump_arrows, + show_linenr, + show_nr_jumps, + show_nr_samples, + show_total_period; +}; +struct annotation ;struct sym_hist_entry {
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 3/44 perf annotate: Move cycles/IPC formatting width constants outside TUI
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
These will be used in --stdio2 so lets move it first to reduce noise in the following patches.
--- tools/perf/ui/browsers/annotate.c | 19 ++++++++----------- tools/perf/util/annotate.h | 3 +++ 2 files changed, 11 insertions(+), 11 deletions(-)
tools/perf/ui/browsers/annotate.c +8 -11
@@ -22,9 +22,6 @@ struct disasm_line_samples {struct sym_hist_entry he; }; -#define IPC_WIDTH 6 -#define CYCLES_WIDTH 6 -struct browser_line {u32 idx;int idx_asm;
@@ -107,7 +104,7 @@ static int annotate_browser__pcnt_width(struct annotate_browser *ab)static int annotate_browser__cycles_width (struct annotate_browser *ab) { -return ab->have_cycles ?IPC_WIDTH +CYCLES_WIDTH :0 ; +return ab->have_cycles ?ANNOTATION__IPC_WIDTH +ANNOTATION__CYCLES_WIDTH :0 ; } static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser,
@@ -194,19 +191,19 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int }if (ab->have_cycles) {if (al->ipc) -ui_browser__printf (browser,"%*.2f " ,IPC_WIDTH -1 , al->ipc); +ui_browser__printf (browser,"%*.2f " ,ANNOTATION__IPC_WIDTH -1 , al->ipc);else if (!show_title) -ui_browser__write_nstring (browser," " ,IPC_WIDTH ); +ui_browser__write_nstring (browser," " ,ANNOTATION__IPC_WIDTH );else -ui_browser__printf (browser,"%*s " ,IPC_WIDTH -1 ,"IPC" ); +ui_browser__printf (browser,"%*s " ,ANNOTATION__IPC_WIDTH -1 ,"IPC" );if (al->cycles)ui_browser__printf (browser,"%*" PRIu64" " , -CYCLES_WIDTH -1 , al->cycles); +ANNOTATION__CYCLES_WIDTH -1 , al->cycles);else if (!show_title) -ui_browser__write_nstring (browser," " ,CYCLES_WIDTH ); +ui_browser__write_nstring (browser," " ,ANNOTATION__CYCLES_WIDTH );else -ui_browser__printf (browser,"%*s " ,CYCLES_WIDTH -1 ,"Cycle" ); +ui_browser__printf (browser,"%*s " ,ANNOTATION__CYCLES_WIDTH -1 ,"Cycle" ); }SLsmg_write_char (' ' );
@@ -359,7 +356,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) }if (ab->have_cycles) - width =IPC_WIDTH +CYCLES_WIDTH ; + width =ANNOTATION__IPC_WIDTH +ANNOTATION__CYCLES_WIDTH ;ui_browser__set_color (browser,HE_COLORSET_JUMP_ARROWS ); __ui_browser__line_arrow(browser,
tools/perf/util/annotate.h +3 -0
@@ -58,6 +58,9 @@ bool ins__is_lock(const struct ins *ins);int ins__scnprintf (struct ins *ins,char *bf,size_t size,struct ins_operands *ops);bool ins__is_fused (struct arch *arch,const char *ins1,const char *ins2); +#define ANNOTATION__IPC_WIDTH 6 +#define ANNOTATION__CYCLES_WIDTH 6 +struct annotation_options {bool hide_src_code, use_offset,
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 4/44 perf annotate tui: Use annotate_browser__cycles_width() mroe
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Instead of an open coded equivalent, will reduce a bit noise in the following patches.
--- tools/perf/ui/browsers/annotate.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
tools/perf/ui/browsers/annotate.c +2 -3
@@ -308,7 +308,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)struct map_symbol *ms = ab->b.priv;struct symbol *sym = ms->sym;u8 pcnt_width =annotate_browser__pcnt_width (ab); -int width =0 ; +int width;/* PLT symbols contain external offsets */ if (strstr (sym->name,"@plt" ))
@@ -355,8 +355,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) to = (u64 )btarget->idx; } -if (ab->have_cycles) - width =ANNOTATION__IPC_WIDTH +ANNOTATION__CYCLES_WIDTH ; + width =annotate_browser__cycles_width (ab);ui_browser__set_color (browser,HE_COLORSET_JUMP_ARROWS ); __ui_browser__line_arrow(browser,
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 5/44 perf annotate tui: Move have_cycles to struct annotation
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This is to pave the way to have more functions shared between TUI, stdio and the upcoming stdio2 formatting, that will use the __scnprintf functions used by --tui in a --stdio fashion.
This partially addresses the comments added in cset 30e863bb6f70 ("perf
annotate: Compute IPC and basic block cycles"):
/*
* This should probably be in util/annotate.c to share with the tty
* annotate, but right now we need the per byte offsets arrays,
* which are only here.
*/
The following patches will address the rest.
--- tools/perf/ui/browsers/annotate.c | 20 +++++++++----------- tools/perf/util/annotate.h | 6 ++++++ 2 files changed, 15 insertions(+), 11 deletions(-)
tools/perf/ui/browsers/annotate.c +9 -11
@@ -49,7 +49,6 @@ struct annotate_browser {int max_jump_sources;int nr_jumps;bool searching_backwards; -bool have_cycles;u8 addr_width;u8 jumps_width;u8 target_width;
@@ -102,11 +101,6 @@ static int annotate_browser__pcnt_width(struct annotate_browser *ab)return (annotate_browser__opts.show_total_period ?12 :7 ) * ab->nr_events; } -static int annotate_browser__cycles_width (struct annotate_browser *ab) -{ -return ab->have_cycles ?ANNOTATION__IPC_WIDTH +ANNOTATION__CYCLES_WIDTH :0 ; -} -static void disasm_line__write (struct disasm_line *dl,struct ui_browser *browser,char *bf,size_t size) {
@@ -136,6 +130,9 @@ static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browsestatic void annotate_browser__write (struct ui_browser *browser,void *entry,int row) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); +struct map_symbol *ms = browser->priv; +struct symbol *sym = ms->sym; +struct annotation *notes =symbol__annotation (sym); struct annotation_line *al = list_entry(entry, struct annotation_line, node);struct browser_line *bl =browser_line (al);bool current_entry =ui_browser__is_current_entry (browser, row);
@@ -144,7 +141,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int !browser->navkeypressed)));int width = browser->width, printed;int i, pcnt_width =annotate_browser__pcnt_width (ab), - cycles_width =annotate_browser__cycles_width (ab); + cycles_width =annotation__cycles_width (notes);double percent_max =0.0 ;char bf[256 ];bool show_title = false;
@@ -155,7 +152,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int }if ((row ==0 ) && (al->offset ==-1 || percent_max ==0.0 )) { -if (ab->have_cycles) { +if (notes->have_cycles) {if (al->ipc ==0.0 && al->cycles ==0 ) show_title = true; }else
@@ -189,7 +186,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int annotate_browser__opts.show_nr_samples ? "Samples" : "Percent"); } } -if (ab->have_cycles) { +if (notes->have_cycles) {if (al->ipc)ui_browser__printf (browser,"%*.2f " ,ANNOTATION__IPC_WIDTH -1 , al->ipc);else if (!show_title)
@@ -307,6 +304,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)unsigned int from, to;struct map_symbol *ms = ab->b.priv;struct symbol *sym = ms->sym; +struct annotation *notes =symbol__annotation (sym);u8 pcnt_width =annotate_browser__pcnt_width (ab);int width;
@@ -355,7 +353,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) to = (u64 )btarget->idx; } - width =annotate_browser__cycles_width (ab); + width =annotation__cycles_width (notes);ui_browser__set_color (browser,HE_COLORSET_JUMP_ARROWS ); __ui_browser__line_arrow(browser,
@@ -1033,7 +1031,7 @@ static void annotate__compute_ipc(struct annotate_browser *browser, size_t size, al = browser->offsets[offset];if (al && ch->num_aggr) al->cycles = ch->cycles_aggr / ch->num_aggr; - browser->have_cycles = true; + notes->have_cycles = true; } }pthread_mutex_unlock (¬es->lock);
tools/perf/util/annotate.h +6 -0
@@ -164,9 +164,15 @@ struct annotated_source {struct annotation {pthread_mutex_t lock;u64 max_coverage; +bool have_cycles;struct annotated_source *src; }; +static inline int annotation__cycles_width (struct annotation *notes) +{ +return notes->have_cycles ?ANNOTATION__IPC_WIDTH +ANNOTATION__CYCLES_WIDTH :0 ; +} +static inline struct sym_hist *annotation__histogram (struct annotation *notes,int idx) { return (((void *)¬es->src->histograms) +
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 6/44 perf annotate: Move annotation_line array from TUI to generic code
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This is needed to reduce the differences between the TUI mode and the other annotation UIs, next csets will move that code to the UI-neutral annotation library. Leaving it in place for now to ease review.
--- tools/perf/ui/browsers/annotate.c | 41 ++++++++++++++++++--------------------- tools/perf/util/annotate.h | 1 + 2 files changed, 20 insertions(+), 22 deletions(-)
tools/perf/ui/browsers/annotate.c +19 -22
@@ -40,7 +40,6 @@ struct annotate_browser {struct rb_root entries;struct rb_node *curr_hot;struct annotation_line *selection; -struct annotation_line **offsets;struct arch *arch;int nr_events;u64 start;
@@ -335,9 +334,9 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)* name right after the '<' token and probably treating this like a * 'call' instruction. */ - target = ab->offsets[cursor->ops.target.offset]; + target = notes->offsets[cursor->ops.target.offset];if (target ==NULL ) { -ui_helpline__printf ("WARN: jump target inconsistency, press 'o', ab->offsets[%#x] = NULL\n" , +ui_helpline__printf ("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n" , cursor->ops.target.offset);return ; }
@@ -969,25 +968,25 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, } -static unsigned count_insn (struct annotate_browser *browser,u64 start,u64 end) +static unsigned count_insn (struct annotation *notes,u64 start,u64 end) {unsigned n_insn =0 ;u64 offset;for (offset = start; offset <= end; offset++) { -if (browser->offsets[offset]) +if (notes->offsets[offset]) n_insn++; }return n_insn; } -static void count_and_fill (struct annotate_browser *browser,u64 start,u64 end, +static void count_and_fill (struct annotation *notes,u64 start,u64 end,struct cyc_hist *ch) {unsigned n_insn;u64 offset; - n_insn =count_insn (browser, start, end); + n_insn =count_insn (notes, start, end);if (n_insn && ch->num && ch->cycles) {float ipc = n_insn / ((double )ch->cycles / (double )ch->num);
@@ -996,7 +995,7 @@ static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end,return ;for (offset = start; offset <= end; offset++) { -struct annotation_line *al = browser->offsets[offset]; +struct annotation_line *al = notes->offsets[offset];if (al) al->ipc = ipc;
@@ -1009,11 +1008,9 @@ static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end,* annotate, but right now we need the per byte offsets arrays, * which are only here. */ -static void annotate__compute_ipc (struct annotate_browser *browser,size_t size, -struct symbol *sym) +static void annotate__compute_ipc (struct annotation *notes,size_t size) {u64 offset; -struct annotation *notes =symbol__annotation (sym);if (!notes->src || !notes->src->cycles_hist)return ;
@@ -1027,8 +1024,8 @@ static void annotate__compute_ipc(struct annotate_browser *browser, size_t size,struct annotation_line *al;if (ch->have_start) -count_and_fill (browser, ch->start, offset, ch); - al = browser->offsets[offset]; +count_and_fill (notes, ch->start, offset, ch); + al = notes->offsets[offset];if (al && ch->num_aggr) al->cycles = ch->cycles_aggr / ch->num_aggr; notes->have_cycles = true;
@@ -1043,13 +1040,14 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browseru64 offset;struct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym; +struct annotation *notes =symbol__annotation (sym);/* PLT symbols contain external offsets */ if (strstr (sym->name,"@plt" ))return ;for (offset =0 ; offset < size; ++offset) { -struct annotation_line *al = browser->offsets[offset]; +struct annotation_line *al = notes->offsets[offset];struct disasm_line *dl;struct browser_line *blt;
@@ -1058,7 +1056,7 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browserif (!disasm_line__is_valid_jump (dl, sym))continue ; - al = browser->offsets[dl->ops.target.offset]; + al = notes->offsets[dl->ops.target.offset];/* * FIXME: Oops, no jump target? Buggy disassembler? Or do we
@@ -1089,7 +1087,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, struct hist_browser_timer *hbt) {struct annotation_line *al; -struct annotation *notes; +struct annotation *notes =symbol__annotation (sym);size_t size;struct map_symbol ms = { .map = map,
@@ -1116,8 +1114,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (map->dso->annotate_warned)return -1 ; - browser.offsets =zalloc (size *sizeof (struct annotation_line *)); -if (browser.offsets ==NULL ) { + notes->offsets =zalloc (size *sizeof (struct annotation_line *)); +if (notes->offsets ==NULL ) {ui__error ("Not enough memory!" );return -1 ; }
@@ -1137,7 +1135,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,ui_helpline__push ("Press ESC to exit" ); - notes =symbol__annotation (sym); browser.start =map__rip_2objdump (map, sym->start);list_for_each_entry (al, ¬es->src->source, node) {
@@ -1158,13 +1155,13 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,* E.g. copy_user_generic_unrolled */ if (al->offset < (s64 )size) - browser.offsets[al->offset] = al; + notes->offsets[al->offset] = al; }else bpos->idx_asm =-1 ; }annotate_browser__mark_jump_targets (&browser, size); -annotate__compute_ipc (&browser, size, sym); +annotate__compute_ipc (notes, size); browser.addr_width = browser.target_width = browser.min_addr_width =hex_width (size); browser.max_addr_width =hex_width (sym->end);
@@ -1184,7 +1181,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,annotated_source__purge (notes->src); out_free_offsets: -free (browser.offsets); +zfree (¬es->offsets);return ret; }
tools/perf/util/annotate.h +1 -0
@@ -164,6 +164,7 @@ struct annotated_source {struct annotation {pthread_mutex_t lock;u64 max_coverage; +struct annotation_line **offsets;bool have_cycles;struct annotated_source *src; };
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 7/44 perf annotate: Move compute_ipc() to annotation library
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Out of the TUI code, as it has nothing specific to that UI and should be used in the other output modes as well.
--- tools/perf/ui/browsers/annotate.c | 69 +-------------------------------------- tools/perf/util/annotate.c | 60 ++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 2 ++ 3 files changed, 63 insertions(+), 68 deletions(-)
tools/perf/ui/browsers/annotate.c +1 -68
@@ -967,73 +967,6 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,return map_symbol__tui_annotate (&he->ms, evsel, hbt); } - -static unsigned count_insn (struct annotation *notes,u64 start,u64 end) -{ -unsigned n_insn =0 ; -u64 offset; - -for (offset = start; offset <= end; offset++) { -if (notes->offsets[offset]) - n_insn++; - } -return n_insn; -} - -static void count_and_fill (struct annotation *notes,u64 start,u64 end, -struct cyc_hist *ch) -{ -unsigned n_insn; -u64 offset; - - n_insn =count_insn (notes, start, end); -if (n_insn && ch->num && ch->cycles) { -float ipc = n_insn / ((double )ch->cycles / (double )ch->num); - -/* Hide data when there are too many overlaps. */ -if (ch->reset >=0x7fff || ch->reset >= ch->num /2 ) -return ; - -for (offset = start; offset <= end; offset++) { -struct annotation_line *al = notes->offsets[offset]; - -if (al) - al->ipc = ipc; - } - } -} - -/* -* This should probably be in util/annotate.c to share with the tty -* annotate, but right now we need the per byte offsets arrays, -* which are only here. -*/ -static void annotate__compute_ipc (struct annotation *notes,size_t size) -{ -u64 offset; - -if (!notes->src || !notes->src->cycles_hist) -return ; - -pthread_mutex_lock (¬es->lock); -for (offset =0 ; offset < size; ++offset) { -struct cyc_hist *ch; - - ch = ¬es->src->cycles_hist[offset]; -if (ch && ch->cycles) { -struct annotation_line *al; - -if (ch->have_start) -count_and_fill (notes, ch->start, offset, ch); - al = notes->offsets[offset]; -if (al && ch->num_aggr) - al->cycles = ch->cycles_aggr / ch->num_aggr; - notes->have_cycles = true; - } - } -pthread_mutex_unlock (¬es->lock); -} -static void annotate_browser__mark_jump_targets (struct annotate_browser *browser,size_t size) {
@@ -1161,7 +1094,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, }annotate_browser__mark_jump_targets (&browser, size); -annotate__compute_ipc (notes, size); +annotation__compute_ipc (notes, size); browser.addr_width = browser.target_width = browser.min_addr_width =hex_width (size); browser.max_addr_width =hex_width (sym->end);
tools/perf/util/annotate.c +60 -0
66 lines not on this page · raw message
tools/perf/util/annotate.h +2 -0
@@ -174,6 +174,8 @@ static inline int annotation__cycles_width(struct annotation *notes)return notes->have_cycles ?ANNOTATION__IPC_WIDTH +ANNOTATION__CYCLES_WIDTH :0 ; } +void annotation__compute_ipc (struct annotation *notes,size_t size); +static inline struct sym_hist *annotation__histogram (struct annotation *notes,int idx) { return (((void *)¬es->src->histograms) +
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 8/44 perf annotate: Move nr_events from annotate_browser to annotation struct
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Paving the way to move more stuff out of TUI and into the generic annotation library.
--- tools/perf/ui/browsers/annotate.c | 11 ++++++----- tools/perf/util/annotate.h | 1 + 2 files changed, 7 insertions(+), 5 deletions(-)
tools/perf/ui/browsers/annotate.c +6 -5
@@ -41,7 +41,6 @@ struct annotate_browser {struct rb_node *curr_hot;struct annotation_line *selection;struct arch *arch; -int nr_events;u64 start;int nr_asm_entries;int nr_entries;
@@ -97,7 +96,9 @@ static int annotate_browser__set_jumps_percent_color(struct annotate_browser *brstatic int annotate_browser__pcnt_width (struct annotate_browser *ab) { -return (annotate_browser__opts.show_total_period ?12 :7 ) * ab->nr_events; +struct map_symbol *ms = ab->b.priv; +struct annotation *notes =symbol__annotation (ms->sym); +return (annotate_browser__opts.show_total_period ?12 :7 ) * notes->nr_events; } static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser,
@@ -145,7 +146,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intchar bf[256 ];bool show_title = false; -for (i =0 ; i < ab->nr_events; i++) { +for (i =0 ; i < notes->nr_events; i++) {if (al->samples[i].percent > percent_max) percent_max = al->samples[i].percent; }
@@ -159,7 +160,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int }if (al->offset !=-1 && percent_max !=0.0 ) { -for (i =0 ; i < ab->nr_events; i++) { +for (i =0 ; i < notes->nr_events; i++) {ui_browser__set_percent_color (browser, al->samples[i].percent, current_entry);
@@ -1099,7 +1100,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, browser.addr_width = browser.target_width = browser.min_addr_width =hex_width (size); browser.max_addr_width =hex_width (sym->end); browser.jumps_width =width_jumps (browser.max_jump_sources); - browser.nr_events = nr_pcnt; + notes->nr_events = nr_pcnt; browser.b.nr_entries = browser.nr_entries; browser.b.entries = ¬es->src->source, browser.b.width +=18 ;/* Percentage */
tools/perf/util/annotate.h +1 -0
@@ -165,6 +165,7 @@ struct annotation {pthread_mutex_t lock;u64 max_coverage;struct annotation_line **offsets; +int nr_events;bool have_cycles;struct annotated_source *src; };
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 9/44 perf annotate: Stop using a global config struct
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
For the TUI, that is interactive, its interesting to have a configuration that one can go on changing and then when moving from one symbol annotation to another symbol, the options set while browsing the first symbol to be kept.
But since we're trying to make this code reusable by a --stdio formatter, we better have a pointer in struct annotation and in the TUI case set it to the global, but use something else for other cases, such as --stdio2.
--- tools/perf/ui/browsers/annotate.c | 84 +++++++++++++++++++++++---------------- tools/perf/util/annotate.h | 1 + 2 files changed, 51 insertions(+), 34 deletions(-)
tools/perf/ui/browsers/annotate.c +50 -34
@@ -63,10 +63,12 @@ static inline struct browser_line *browser_line(struct annotation_line *al)return ptr -sizeof (struct browser_line ); } -static bool disasm_line__filter (struct ui_browser *browser__maybe_unused , -void *entry) +static bool disasm_line__filter (struct ui_browser *browser,void *entry) { -if (annotate_browser__opts.hide_src_code) { +struct map_symbol *ms = browser->priv; +struct annotation *notes =symbol__annotation (ms->sym); + +if (notes->options->hide_src_code) { struct annotation_line *al = list_entry(entry, struct annotation_line, node);return al->offset ==-1 ;
@@ -98,12 +100,15 @@ static int annotate_browser__pcnt_width(struct annotate_browser *ab) {struct map_symbol *ms = ab->b.priv;struct annotation *notes =symbol__annotation (ms->sym); -return (annotate_browser__opts.show_total_period ?12 :7 ) * notes->nr_events; +return (notes->options->show_total_period ?12 :7 ) * notes->nr_events; }static void disasm_line__write (struct disasm_line *dl,struct ui_browser *browser,char *bf,size_t size) { +struct map_symbol *ms = browser->priv; +struct annotation *notes =symbol__annotation (ms->sym); +if (dl->ins.ops && dl->ins.ops->scnprintf) {if (ins__is_jump (&dl->ins)) {bool fwd = dl->ops.target.offset > dl->al.offset;
@@ -124,7 +129,7 @@ static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browseui_browser__write_nstring (browser," " ,2 ); } -disasm_line__scnprintf (dl, bf, size, !annotate_browser__opts.use_offset); +disasm_line__scnprintf (dl, bf, size, !notes->options->use_offset); }static void annotate_browser__write (struct ui_browser *browser,void *entry,int row)
@@ -136,7 +141,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int struct annotation_line *al = list_entry(entry, struct annotation_line, node);struct browser_line *bl =browser_line (al);bool current_entry =ui_browser__is_current_entry (browser, row); -bool change_color = (!annotate_browser__opts.hide_src_code && +bool change_color = (!notes->options->hide_src_code && (!current_entry || (browser->use_navkeypressed && !browser->navkeypressed)));int width = browser->width, printed;
@@ -164,10 +169,10 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intui_browser__set_percent_color (browser, al->samples[i].percent, current_entry); -if (annotate_browser__opts.show_total_period) { +if (notes->options->show_total_period) {ui_browser__printf (browser,"%11" PRIu64" " , al->samples[i].he.period); - }else if (annotate_browser__opts.show_nr_samples) { + }else if (notes->options->show_nr_samples) {ui_browser__printf (browser,"%6" PRIu64" " , al->samples[i].he.nr_samples); }else {
@@ -182,8 +187,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intui_browser__write_nstring (browser," " , pcnt_width); else {ui_browser__printf (browser,"%*s" , pcnt_width, - annotate_browser__opts.show_total_period ?"Period" : - annotate_browser__opts.show_nr_samples ?"Samples" :"Percent" ); + notes->options->show_total_period ?"Period" : + notes->options->show_nr_samples ?"Samples" :"Percent" ); } }if (notes->have_cycles) {
@@ -212,7 +217,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (!*al->line)ui_browser__write_nstring (browser," " , width - pcnt_width - cycles_width);else if (al->offset ==-1 ) { -if (al->line_nr && annotate_browser__opts.show_linenr) +if (al->line_nr && notes->options->show_linenr) printed =scnprintf (bf,sizeof (bf),"%-*d " , ab->addr_width +1 , al->line_nr);else
@@ -224,14 +229,14 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intu64 addr = al->offset;int color =-1 ; -if (!annotate_browser__opts.use_offset) +if (!notes->options->use_offset) addr += ab->start; -if (!annotate_browser__opts.use_offset) { +if (!notes->options->use_offset) { printed =scnprintf (bf,sizeof (bf),"%" PRIx64": " , addr); }else {if (bl->jump_sources) { -if (annotate_browser__opts.show_nr_jumps) { +if (notes->options->show_nr_jumps) {int prev; printed = scnprintf(bf, sizeof(bf), "%*d ", ab->jumps_width,
@@ -345,7 +350,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) bcursor =browser_line (&cursor->al); btarget =browser_line (target); -if (annotate_browser__opts.hide_src_code) { +if (notes->options->hide_src_code) { from = bcursor->idx_asm; to = btarget->idx_asm; }else {
@@ -371,10 +376,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)static unsigned int annotate_browser__refresh (struct ui_browser *browser) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); +struct map_symbol *ms = browser->priv; +struct annotation *notes =symbol__annotation (ms->sym);int ret =ui_browser__list_head_refresh (browser);int pcnt_width =annotate_browser__pcnt_width (ab); -if (annotate_browser__opts.jump_arrows) +if (notes->options->jump_arrows)annotate_browser__draw_current_jump (browser);ui_browser__set_color (browser,HE_COLORSET_NORMAL );
@@ -439,6 +446,8 @@ static void annotate_browser__set_top(struct annotate_browser *browser,static void annotate_browser__set_rb_top (struct annotate_browser *browser,struct rb_node *nd) { +struct map_symbol *ms = browser->b.priv; +struct annotation *notes =symbol__annotation (ms->sym);struct browser_line *bpos;struct annotation_line *pos;u32 idx;
@@ -447,7 +456,7 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser, bpos =browser_line (pos); idx = bpos->idx; -if (annotate_browser__opts.hide_src_code) +if (notes->options->hide_src_code) idx = bpos->idx_asm;annotate_browser__set_top (browser, pos, idx); browser->curr_hot = nd;
@@ -496,6 +505,8 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,static bool annotate_browser__toggle_source (struct annotate_browser *browser) { +struct map_symbol *ms = browser->b.priv; +struct annotation *notes =symbol__annotation (ms->sym);struct annotation_line *al;struct browser_line *bl;off_t offset = browser->b.index - browser->b.top_idx;
@@ -504,12 +515,12 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser) al = list_entry(browser->b.top, struct annotation_line, node); bl =browser_line (al); -if (annotate_browser__opts.hide_src_code) { +if (notes->options->hide_src_code) {if (bl->idx_asm < offset) offset = bl->idx; browser->b.nr_entries = browser->nr_entries; - annotate_browser__opts.hide_src_code = false; + notes->options->hide_src_code = false; browser->b.seek (&browser->b, -offset,SEEK_CUR ); browser->b.top_idx = bl->idx - offset; browser->b.index = bl->idx;
@@ -524,7 +535,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser) offset = bl->idx_asm; browser->b.nr_entries = browser->nr_asm_entries; - annotate_browser__opts.hide_src_code = true; + notes->options->hide_src_code = true; browser->b.seek (&browser->b, -offset,SEEK_CUR ); browser->b.top_idx = bl->idx_asm - offset; browser->b.index = bl->idx_asm;
@@ -750,14 +761,17 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,static void annotate_browser__update_addr_width (struct annotate_browser *browser) { -if (annotate_browser__opts.use_offset) +struct map_symbol *ms = browser->b.priv; +struct annotation *notes =symbol__annotation (ms->sym); + +if (notes->options->use_offset) browser->target_width = browser->min_addr_width;else browser->target_width = browser->max_addr_width; browser->addr_width = browser->target_width; -if (annotate_browser__opts.show_nr_jumps) +if (notes->options->show_nr_jumps) browser->addr_width += browser->jumps_width +1 ; }
@@ -768,6 +782,7 @@ static int annotate_browser__run(struct annotate_browser *browser,struct rb_node *nd =NULL ;struct map_symbol *ms = browser->b.priv;struct symbol *sym = ms->sym; +struct annotation *notes =symbol__annotation (ms->sym);const char *help ="Press 'h' for help on key bindings" ;int delay_secs = hbt ? hbt->refresh :0 ;int key;
@@ -851,8 +866,7 @@ static int annotate_browser__run(struct annotate_browser *browser,continue ; }case 'k' : - annotate_browser__opts.show_linenr = - !annotate_browser__opts.show_linenr; + notes->options->show_linenr = !notes->options->show_linenr;break ;case 'H' : nd = browser->curr_hot;
@@ -862,14 +876,14 @@ static int annotate_browser__run(struct annotate_browser *browser,ui_helpline__puts (help);continue ;case 'o' : - annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; + notes->options->use_offset = !notes->options->use_offset;annotate_browser__update_addr_width (browser);continue ;case 'j' : - annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; + notes->options->jump_arrows = !notes->options->jump_arrows;continue ;case 'J' : - annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; + notes->options->show_nr_jumps = !notes->options->show_nr_jumps;annotate_browser__update_addr_width (browser);continue ;case '/' :
@@ -920,13 +934,13 @@ static int annotate_browser__run(struct annotate_browser *browser,continue ; }case 't' : -if (annotate_browser__opts.show_total_period) { - annotate_browser__opts.show_total_period = false; - annotate_browser__opts.show_nr_samples = true; - }else if (annotate_browser__opts.show_nr_samples) - annotate_browser__opts.show_nr_samples = false; +if (notes->options->show_total_period) { + notes->options->show_total_period = false; + notes->options->show_nr_samples = true; + }else if (notes->options->show_nr_samples) + notes->options->show_nr_samples = false;else - annotate_browser__opts.show_total_period = true; + notes->options->show_total_period = true;annotate_browser__update_addr_width (browser);continue ;case K_LEFT :
@@ -1048,6 +1062,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (map->dso->annotate_warned)return -1 ; + notes->options = &annotate_browser__opts; + notes->offsets =zalloc (size *sizeof (struct annotation_line *));if (notes->offsets ==NULL ) {ui__error ("Not enough memory!" );
@@ -1105,7 +1121,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, browser.b.entries = ¬es->src->source, browser.b.width +=18 ;/* Percentage */ -if (annotate_browser__opts.hide_src_code) +if (notes->options->hide_src_code)annotate_browser__init_asm_mode (&browser);annotate_browser__update_addr_width (&browser);
tools/perf/util/annotate.h +1 -0
@@ -164,6 +164,7 @@ struct annotated_source {struct annotation {pthread_mutex_t lock;u64 max_coverage; +struct annotation_options *options;struct annotation_line **offsets;int nr_events;bool have_cycles;
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 10/44 perf annotate: Move pcnt_with() to the annotation library
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Out of the TUI code, since now all it touches is what is in 'struct annotation'.
--- tools/perf/ui/browsers/annotate.c | 14 +++----------- tools/perf/util/annotate.h | 5 +++++ 2 files changed, 8 insertions(+), 11 deletions(-)
tools/perf/ui/browsers/annotate.c +3 -11
@@ -96,13 +96,6 @@ static int annotate_browser__set_jumps_percent_color(struct annotate_browser *brreturn ui_browser__set_color (&browser->b, color); } -static int annotate_browser__pcnt_width (struct annotate_browser *ab) -{ -struct map_symbol *ms = ab->b.priv; -struct annotation *notes =symbol__annotation (ms->sym); -return (notes->options->show_total_period ?12 :7 ) * notes->nr_events; -} -static void disasm_line__write (struct disasm_line *dl,struct ui_browser *browser,char *bf,size_t size) {
@@ -145,7 +138,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int (!current_entry || (browser->use_navkeypressed && !browser->navkeypressed)));int width = browser->width, printed; -int i, pcnt_width =annotate_browser__pcnt_width (ab), +int i, pcnt_width =annotation__pcnt_width (notes), cycles_width =annotation__cycles_width (notes);double percent_max =0.0 ;char bf[256 ];
@@ -310,7 +303,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)struct map_symbol *ms = ab->b.priv;struct symbol *sym = ms->sym;struct annotation *notes =symbol__annotation (sym); -u8 pcnt_width =annotate_browser__pcnt_width (ab); +u8 pcnt_width =annotation__pcnt_width (notes);int width;/* PLT symbols contain external offsets */
@@ -375,11 +368,10 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)static unsigned int annotate_browser__refresh (struct ui_browser *browser) { - struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);struct map_symbol *ms = browser->priv;struct annotation *notes =symbol__annotation (ms->sym);int ret =ui_browser__list_head_refresh (browser); -int pcnt_width =annotate_browser__pcnt_width (ab); +int pcnt_width =annotation__pcnt_width (notes);if (notes->options->jump_arrows)annotate_browser__draw_current_jump (browser);
tools/perf/util/annotate.h +5 -0
@@ -176,6 +176,11 @@ static inline int annotation__cycles_width(struct annotation *notes)return notes->have_cycles ?ANNOTATION__IPC_WIDTH +ANNOTATION__CYCLES_WIDTH :0 ; } +static inline int annotation__pcnt_width (struct annotation *notes) +{ +return (notes->options->show_total_period ?12 :7 ) * notes->nr_events; +} +void annotation__compute_ipc (struct annotation *notes,size_t size);static inline struct sym_hist *annotation__histogram (struct annotation *notes,int idx)
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 11/44 perf annotate tui: Add browser__annotation() helper
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To reduce the boilerplate to get to the symbol being annotated from the struct browser ->priv area.
--- tools/perf/ui/browsers/annotate.c | 40 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 24 deletions(-)
tools/perf/ui/browsers/annotate.c +16 -24
@@ -55,6 +55,12 @@ struct annotate_browser {char search_bf[128 ]; }; +static inline struct annotation *browser__annotation (struct ui_browser *browser) +{ +struct map_symbol *ms = browser->priv; +return symbol__annotation (ms->sym); +} +static inline struct browser_line *browser_line (struct annotation_line *al) {void *ptr = al;
@@ -65,8 +71,7 @@ static inline struct browser_line *browser_line(struct annotation_line *al)static bool disasm_line__filter (struct ui_browser *browser,void *entry) { -struct map_symbol *ms = browser->priv; -struct annotation *notes =symbol__annotation (ms->sym); +struct annotation *notes =browser__annotation (browser);if (notes->options->hide_src_code) { struct annotation_line *al = list_entry(entry, struct annotation_line, node);
@@ -99,8 +104,7 @@ static int annotate_browser__set_jumps_percent_color(struct annotate_browser *brstatic void disasm_line__write (struct disasm_line *dl,struct ui_browser *browser,char *bf,size_t size) { -struct map_symbol *ms = browser->priv; -struct annotation *notes =symbol__annotation (ms->sym); +struct annotation *notes =browser__annotation (browser);if (dl->ins.ops && dl->ins.ops->scnprintf) {if (ins__is_jump (&dl->ins)) {
@@ -128,9 +132,7 @@ static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browsestatic void annotate_browser__write (struct ui_browser *browser,void *entry,int row) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); -struct map_symbol *ms = browser->priv; -struct symbol *sym = ms->sym; -struct annotation *notes =symbol__annotation (sym); +struct annotation *notes =browser__annotation (browser); struct annotation_line *al = list_entry(entry, struct annotation_line, node);struct browser_line *bl =browser_line (al);bool current_entry =ui_browser__is_current_entry (browser, row);
@@ -368,8 +370,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)static unsigned int annotate_browser__refresh (struct ui_browser *browser) { -struct map_symbol *ms = browser->priv; -struct annotation *notes =symbol__annotation (ms->sym); +struct annotation *notes =browser__annotation (browser);int ret =ui_browser__list_head_refresh (browser);int pcnt_width =annotation__pcnt_width (notes);
@@ -438,8 +439,7 @@ static void annotate_browser__set_top(struct annotate_browser *browser,static void annotate_browser__set_rb_top (struct annotate_browser *browser,struct rb_node *nd) { -struct map_symbol *ms = browser->b.priv; -struct annotation *notes =symbol__annotation (ms->sym); +struct annotation *notes =browser__annotation (&browser->b);struct browser_line *bpos;struct annotation_line *pos;u32 idx;
@@ -497,8 +497,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,static bool annotate_browser__toggle_source (struct annotate_browser *browser) { -struct map_symbol *ms = browser->b.priv; -struct annotation *notes =symbol__annotation (ms->sym); +struct annotation *notes =browser__annotation (&browser->b);struct annotation_line *al;struct browser_line *bl;off_t offset = browser->b.index - browser->b.top_idx;
@@ -588,9 +587,7 @@ staticstruct disasm_line *annotate_browser__find_offset (struct annotate_browser *browser,s64 offset,s64 *idx) { -struct map_symbol *ms = browser->b.priv; -struct symbol *sym = ms->sym; -struct annotation *notes =symbol__annotation (sym); +struct annotation *notes =browser__annotation (&browser->b);struct disasm_line *pos; *idx =0 ;
@@ -629,9 +626,7 @@ staticstruct annotation_line *annotate_browser__find_string (struct annotate_browser *browser,char *s,s64 *idx) { -struct map_symbol *ms = browser->b.priv; -struct symbol *sym = ms->sym; -struct annotation *notes =symbol__annotation (sym); +struct annotation *notes =browser__annotation (&browser->b);struct annotation_line *al = browser->selection; *idx = browser->b.index;
@@ -668,9 +663,7 @@ staticstruct annotation_line *annotate_browser__find_string_reverse (struct annotate_browser *browser,char *s,s64 *idx) { -struct map_symbol *ms = browser->b.priv; -struct symbol *sym = ms->sym; -struct annotation *notes =symbol__annotation (sym); +struct annotation *notes =browser__annotation (&browser->b);struct annotation_line *al = browser->selection; *idx = browser->b.index;
@@ -753,8 +746,7 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,static void annotate_browser__update_addr_width (struct annotate_browser *browser) { -struct map_symbol *ms = browser->b.priv; -struct annotation *notes =symbol__annotation (ms->sym); +struct annotation *notes =browser__annotation (&browser->b);if (notes->options->use_offset) browser->target_width = browser->min_addr_width;
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 12/44 perf annotate: Move max_jump_sources to struct annotation
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This is not useful only for the TUI, we'll want to somehow mark the --stdio2 lines with the most jump sources too.
And moving this will allow us to change some function signatures from annotate_browser to ui_browser, reducing boilerplate.
--- tools/perf/ui/browsers/annotate.c | 11 ++++++----- tools/perf/util/annotate.h | 1 + 2 files changed, 7 insertions(+), 5 deletions(-)
tools/perf/ui/browsers/annotate.c +6 -5
@@ -44,7 +44,6 @@ struct annotate_browser {u64 start;int nr_asm_entries;int nr_entries; -int max_jump_sources;int nr_jumps;bool searching_backwards;u8 addr_width;
@@ -85,9 +84,11 @@ static bool disasm_line__filter(struct ui_browser *browser, void *entry)static int annotate_browser__jumps_percent_color (struct annotate_browser *browser,int nr,bool current) { +struct annotation *notes =browser__annotation (&browser->b); +if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed))return HE_COLORSET_SELECTED ; -if (nr == browser->max_jump_sources) +if (nr == notes->max_jump_sources)return HE_COLORSET_TOP ;if (nr >1 )return HE_COLORSET_MEDIUM ;
@@ -998,8 +999,8 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browsercontinue ; blt =browser_line (al); -if (++blt->jump_sources > browser->max_jump_sources) - browser->max_jump_sources = blt->jump_sources; +if (++blt->jump_sources > notes->max_jump_sources) + notes->max_jump_sources = blt->jump_sources; ++browser->nr_jumps; }
@@ -1099,7 +1100,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, browser.addr_width = browser.target_width = browser.min_addr_width =hex_width (size); browser.max_addr_width =hex_width (sym->end); - browser.jumps_width =width_jumps (browser.max_jump_sources); + browser.jumps_width =width_jumps (notes->max_jump_sources); notes->nr_events = nr_pcnt; browser.b.nr_entries = browser.nr_entries; browser.b.entries = ¬es->src->source,
tools/perf/util/annotate.h +1 -0
@@ -167,6 +167,7 @@ struct annotation {struct annotation_options *options;struct annotation_line **offsets;int nr_events; +int max_jump_sources;bool have_cycles;struct annotated_source *src; };
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 13/44 perf annotate: Move jumps_percent_color to ui_browser
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Since all it needs is in ui_browser and annotation structs members.
--- tools/perf/ui/browsers/annotate.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
tools/perf/ui/browsers/annotate.c +8 -10
@@ -81,12 +81,11 @@ static bool disasm_line__filter(struct ui_browser *browser, void *entry)return false; } -static int annotate_browser__jumps_percent_color (struct annotate_browser *browser, -int nr,bool current) +static int ui_browser__jumps_percent_color (struct ui_browser *browser,int nr,bool current) { -struct annotation *notes =browser__annotation (&browser->b); +struct annotation *notes =browser__annotation (browser); -if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) +if (current && (!browser->use_navkeypressed || browser->navkeypressed))return HE_COLORSET_SELECTED ;if (nr == notes->max_jump_sources)return HE_COLORSET_TOP ;
@@ -95,11 +94,10 @@ static int annotate_browser__jumps_percent_color(struct annotate_browser *browsereturn HE_COLORSET_NORMAL ; } -static int annotate_browser__set_jumps_percent_color (struct annotate_browser *browser, -int nr,bool current) +static int ui_browser__set_jumps_percent_color (struct ui_browser *browser,int nr,bool current) { -int color =annotate_browser__jumps_percent_color (browser, nr, current); -return ui_browser__set_color (&browser->b, color); +int color =ui_browser__jumps_percent_color (browser, nr, current); +return ui_browser__set_color (browser, color); } static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser,
@@ -237,8 +235,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int printed =scnprintf (bf,sizeof (bf),"%*d " , ab->jumps_width, bl->jump_sources); - prev =annotate_browser__set_jumps_percent_color (ab, bl->jump_sources, - current_entry); + prev =ui_browser__set_jumps_percent_color (browser, bl->jump_sources, + current_entry);ui_browser__write_nstring (browser, bf, printed);ui_browser__set_color (browser, prev); }
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 14/44 perf annotate: Move nr_jumps to struct annotation
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This is another information that will be useful for the --stdio2 mode, to provide symbol statistics, so move it from the TUI and change the mark_jump_targets() method to struct annotation.
--- tools/perf/ui/browsers/annotate.c | 13 ++++--------- tools/perf/util/annotate.h | 1 + 2 files changed, 5 insertions(+), 9 deletions(-)
tools/perf/ui/browsers/annotate.c +4 -9
@@ -44,7 +44,6 @@ struct annotate_browser {u64 start;int nr_asm_entries;int nr_entries; -int nr_jumps;bool searching_backwards;u8 addr_width;u8 jumps_width;
@@ -965,13 +964,9 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,return map_symbol__tui_annotate (&he->ms, evsel, hbt); } -static void annotate_browser__mark_jump_targets (struct annotate_browser *browser, -size_t size) +static void annotation__mark_jump_targets (struct annotation *notes,struct symbol *sym) { -u64 offset; -struct map_symbol *ms = browser->b.priv; -struct symbol *sym = ms->sym; -struct annotation *notes =symbol__annotation (sym); +u64 offset, size =symbol__size (sym);/* PLT symbols contain external offsets */ if (strstr (sym->name,"@plt" ))
@@ -1000,7 +995,7 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browserif (++blt->jump_sources > notes->max_jump_sources) notes->max_jump_sources = blt->jump_sources; - ++browser->nr_jumps; + ++notes->nr_jumps; } }
@@ -1093,7 +1088,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, bpos->idx_asm =-1 ; } -annotate_browser__mark_jump_targets (&browser, size); +annotation__mark_jump_targets (notes, sym);annotation__compute_ipc (notes, size); browser.addr_width = browser.target_width = browser.min_addr_width =hex_width (size);
tools/perf/util/annotate.h +1 -0
@@ -167,6 +167,7 @@ struct annotation {struct annotation_options *options;struct annotation_line **offsets;int nr_events; +int nr_jumps;int max_jump_sources;bool have_cycles;struct annotated_source *src;
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 15/44 perf annotate: Move mark_jump_targets from the TUI to the annotation library
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This also is not TUI specific, should be used in the upcoming --stdio2 mode.
--- tools/perf/ui/browsers/annotate.c | 54 +++------------------------------------ tools/perf/util/annotate.c | 44 +++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 4 +++ 3 files changed, 51 insertions(+), 51 deletions(-)
tools/perf/ui/browsers/annotate.c +3 -51
@@ -25,7 +25,6 @@ struct disasm_line_samples {struct browser_line {u32 idx;int idx_asm; -int jump_sources; };static struct annotation_options annotate_browser__opts = {
@@ -132,7 +131,6 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);struct annotation *notes =browser__annotation (browser); struct annotation_line *al = list_entry(entry, struct annotation_line, node); -struct browser_line *bl =browser_line (al);bool current_entry =ui_browser__is_current_entry (browser, row); bool change_color = (!notes->options->hide_src_code && (!current_entry || (browser->use_navkeypressed &&
@@ -228,13 +226,13 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (!notes->options->use_offset) { printed =scnprintf (bf,sizeof (bf),"%" PRIx64": " , addr); }else { -if (bl->jump_sources) { +if (al->jump_sources) {if (notes->options->show_nr_jumps) {int prev; printed =scnprintf (bf,sizeof (bf),"%*d " , ab->jumps_width, - bl->jump_sources); - prev =ui_browser__set_jumps_percent_color (browser, bl->jump_sources, + al->jump_sources); + prev =ui_browser__set_jumps_percent_color (browser, al->jump_sources, current_entry);ui_browser__write_nstring (browser, bf, printed);ui_browser__set_color (browser, prev);
@@ -263,17 +261,6 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int ab->selection = al; } -static bool disasm_line__is_valid_jump (struct disasm_line *dl,struct symbol *sym) -{ -if (!dl || !dl->ins.ops || !ins__is_jump (&dl->ins) - || !disasm_line__has_offset (dl) - || dl->ops.target.offset <0 - || dl->ops.target.offset >= (s64 )symbol__size (sym)) -return false; - -return true; -} -static bool is_fused (struct annotate_browser *ab,struct disasm_line *cursor) {struct disasm_line *pos =list_prev_entry (cursor, al.node);
@@ -964,41 +951,6 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,return map_symbol__tui_annotate (&he->ms, evsel, hbt); } -static void annotation__mark_jump_targets (struct annotation *notes,struct symbol *sym) -{ -u64 offset, size =symbol__size (sym); - -/* PLT symbols contain external offsets */ -if (strstr (sym->name,"@plt" )) -return ; - -for (offset =0 ; offset < size; ++offset) { -struct annotation_line *al = notes->offsets[offset]; -struct disasm_line *dl; -struct browser_line *blt; - - dl =disasm_line (al); - -if (!disasm_line__is_valid_jump (dl, sym)) -continue ; - - al = notes->offsets[dl->ops.target.offset]; - -/* -* FIXME: Oops, no jump target? Buggy disassembler? Or do we -* have to adjust to the previous offset? -*/ -if (al ==NULL ) -continue ; - - blt =browser_line (al); -if (++blt->jump_sources > notes->max_jump_sources) - notes->max_jump_sources = blt->jump_sources; - - ++notes->nr_jumps; - } -} -static inline int width_jumps (int n) {if (n >=100 )
tools/perf/util/annotate.c +44 -0
50 lines not on this page · raw message
tools/perf/util/annotate.h +4 -0
@@ -90,6 +90,7 @@ struct annotation_line {s64 offset;char *line;int line_nr; +int jump_sources;float ipc;u64 cycles;size_t privsize;
@@ -116,6 +117,8 @@ static inline bool disasm_line__has_offset(const struct disasm_line *dl)return dl->ops.target.offset_avail; } +bool disasm_line__is_valid_jump (struct disasm_line *dl,struct symbol *sym); +void disasm_line__free (struct disasm_line *dl);struct annotation_line *annotation_line__next (struct annotation_line *pos,struct list_head *head);
@@ -184,6 +187,7 @@ static inline int annotation__pcnt_width(struct annotation *notes) }void annotation__compute_ipc (struct annotation *notes,size_t size); +void annotation__mark_jump_targets (struct annotation *notes,struct symbol *sym);static inline struct sym_hist *annotation__histogram (struct annotation *notes,int idx) {
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 16/44 perf annotate: Nuke struct browser_line
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
The information in there are all related to things already moved to struct annotation, so move those members to struct annotation_line.
--- tools/perf/ui/browsers/annotate.c | 66 ++++++++++++--------------------------- tools/perf/util/annotate.h | 2 ++ 2 files changed, 22 insertions(+), 46 deletions(-)
tools/perf/ui/browsers/annotate.c +20 -46
@@ -22,11 +22,6 @@ struct disasm_line_samples {struct sym_hist_entry he; }; -struct browser_line { -u32 idx; -int idx_asm; -}; -static struct annotation_options annotate_browser__opts = { .use_offset = true, .jump_arrows = true,
@@ -58,14 +53,6 @@ static inline struct annotation *browser__annotation(struct ui_browser *browser)return symbol__annotation (ms->sym); } -static inline struct browser_line *browser_line (struct annotation_line *al) -{ -void *ptr = al; - - ptr = container_of(al, struct disasm_line, al); -return ptr -sizeof (struct browser_line ); -} -static bool disasm_line__filter (struct ui_browser *browser,void *entry) {struct annotation *notes =browser__annotation (browser);
@@ -285,7 +272,6 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);struct disasm_line *cursor =disasm_line (ab->selection);struct annotation_line *target; -struct browser_line *btarget, *bcursor;unsigned int from, to;struct map_symbol *ms = ab->b.priv;struct symbol *sym = ms->sym;
@@ -327,15 +313,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)return ; } - bcursor =browser_line (&cursor->al); - btarget =browser_line (target); -if (notes->options->hide_src_code) { - from = bcursor->idx_asm; - to = btarget->idx_asm; + from = cursor->al.idx_asm; + to = target->idx_asm; }else { - from = (u64 )bcursor->idx; - to = (u64 )btarget->idx; + from = (u64 )cursor->al.idx; + to = (u64 )target->idx; } width =annotation__cycles_width (notes);
@@ -425,16 +408,11 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser, struct rb_node *nd) {struct annotation *notes =browser__annotation (&browser->b); -struct browser_line *bpos; -struct annotation_line *pos; -u32 idx; - - pos = rb_entry(nd, struct annotation_line, rb_node); - bpos =browser_line (pos); + struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node); +u32 idx = pos->idx; - idx = bpos->idx;if (notes->options->hide_src_code) - idx = bpos->idx_asm; + idx = pos->idx_asm;annotate_browser__set_top (browser, pos, idx); browser->curr_hot = nd; }
@@ -484,37 +462,35 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser) {struct annotation *notes =browser__annotation (&browser->b);struct annotation_line *al; -struct browser_line *bl;off_t offset = browser->b.index - browser->b.top_idx; browser->b.seek (&browser->b, offset,SEEK_CUR ); al = list_entry(browser->b.top, struct annotation_line, node); - bl =browser_line (al);if (notes->options->hide_src_code) { -if (bl->idx_asm < offset) - offset = bl->idx; +if (al->idx_asm < offset) + offset = al->idx; browser->b.nr_entries = browser->nr_entries; notes->options->hide_src_code = false; browser->b.seek (&browser->b, -offset,SEEK_CUR ); - browser->b.top_idx = bl->idx - offset; - browser->b.index = bl->idx; + browser->b.top_idx = al->idx - offset; + browser->b.index = al->idx; }else { -if (bl->idx_asm <0 ) { +if (al->idx_asm <0 ) {ui_helpline__puts ("Only available for assembly lines." ); browser->b.seek (&browser->b, -offset,SEEK_CUR );return false; } -if (bl->idx_asm < offset) - offset = bl->idx_asm; +if (al->idx_asm < offset) + offset = al->idx_asm; browser->b.nr_entries = browser->nr_asm_entries; notes->options->hide_src_code = true; browser->b.seek (&browser->b, -offset,SEEK_CUR ); - browser->b.top_idx = bl->idx_asm - offset; - browser->b.index = bl->idx_asm; + browser->b.top_idx = al->idx_asm - offset; + browser->b.index = al->idx_asm; }return true;
@@ -1003,7 +979,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (perf_evsel__is_group_event (evsel)) nr_pcnt = evsel->nr_members; - err =symbol__annotate (sym, map, evsel,sizeof (struct browser_line ), &browser.arch); + err =symbol__annotate (sym, map, evsel,0 , &browser.arch);if (err) {char msg[BUFSIZ ];symbol__strerror_disassemble (sym, map, err, msg,sizeof (msg));
@@ -1018,15 +994,13 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, browser.start =map__rip_2objdump (map, sym->start);list_for_each_entry (al, ¬es->src->source, node) { -struct browser_line *bpos;size_t line_len =strlen (al->line);if (browser.b.width < line_len) browser.b.width = line_len; - bpos =browser_line (al); - bpos->idx = browser.nr_entries++; + al->idx = browser.nr_entries++;if (al->offset !=-1 ) { - bpos->idx_asm = browser.nr_asm_entries++; + al->idx_asm = browser.nr_asm_entries++;/* * FIXME: short term bandaid to cope with assembly * routines that comes with labels in the same column
@@ -1037,7 +1011,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (al->offset < (s64 )size) notes->offsets[al->offset] = al; }else - bpos->idx_asm =-1 ; + al->idx_asm =-1 ; }annotation__mark_jump_targets (notes, sym);
tools/perf/util/annotate.h +2 -0
@@ -95,6 +95,8 @@ struct annotation_line {u64 cycles;size_t privsize;char *path; +u32 idx; +int idx_asm;int samples_nr;struct annotation_data samples[0 ]; };
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 17/44 perf annotate: Move 'start' to struct annotation
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Another field that is not TUI specific.
--- tools/perf/ui/browsers/annotate.c | 5 ++--- tools/perf/util/annotate.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-)
tools/perf/ui/browsers/annotate.c +2 -3
@@ -35,7 +35,6 @@ struct annotate_browser {struct rb_node *curr_hot;struct annotation_line *selection;struct arch *arch; -u64 start;int nr_asm_entries;int nr_entries;bool searching_backwards;
@@ -208,7 +207,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intint color =-1 ;if (!notes->options->use_offset) - addr += ab->start; + addr += notes->start;if (!notes->options->use_offset) { printed =scnprintf (bf,sizeof (bf),"%" PRIx64": " , addr);
@@ -991,7 +990,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,ui_helpline__push ("Press ESC to exit" ); - browser.start =map__rip_2objdump (map, sym->start); + notes->start =map__rip_2objdump (map, sym->start);list_for_each_entry (al, ¬es->src->source, node) {size_t line_len =strlen (al->line);
tools/perf/util/annotate.h +1 -0
@@ -169,6 +169,7 @@ struct annotated_source {struct annotation {pthread_mutex_t lock;u64 max_coverage; +u64 start;struct annotation_options *options;struct annotation_line **offsets;int nr_events;
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 18/44 perf annotate: Move nr_{asm_}entries to struct annotation
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
More non-TUI stuff.
--- tools/perf/ui/browsers/annotate.c | 23 +++++++++++------------ tools/perf/util/annotate.h | 2 ++ 2 files changed, 13 insertions(+), 12 deletions(-)
tools/perf/ui/browsers/annotate.c +11 -12
@@ -35,8 +35,6 @@ struct annotate_browser {struct rb_node *curr_hot;struct annotation_line *selection;struct arch *arch; -int nr_asm_entries; -int nr_entries;bool searching_backwards;u8 addr_width;u8 jumps_width;
@@ -470,7 +468,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)if (al->idx_asm < offset) offset = al->idx; - browser->b.nr_entries = browser->nr_entries; + browser->b.nr_entries = notes->nr_entries; notes->options->hide_src_code = false; browser->b.seek (&browser->b, -offset,SEEK_CUR ); browser->b.top_idx = al->idx - offset;
@@ -485,7 +483,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)if (al->idx_asm < offset) offset = al->idx_asm; - browser->b.nr_entries = browser->nr_asm_entries; + browser->b.nr_entries = notes->nr_asm_entries; notes->options->hide_src_code = true; browser->b.seek (&browser->b, -offset,SEEK_CUR ); browser->b.top_idx = al->idx_asm - offset;
@@ -495,10 +493,11 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)return true; } -static void annotate_browser__init_asm_mode (struct annotate_browser *browser) +static void ui_browser__init_asm_mode (struct ui_browser *browser) { -ui_browser__reset_index (&browser->b); - browser->b.nr_entries = browser->nr_asm_entries; +struct annotation *notes =browser__annotation (browser); +ui_browser__reset_index (browser); + browser->nr_entries = notes->nr_asm_entries; }#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
@@ -854,7 +853,7 @@ static int annotate_browser__run(struct annotate_browser *browser, browser->b.height, browser->b.index, browser->b.top_idx, - browser->nr_asm_entries); + notes->nr_asm_entries); }continue ;case K_ENTER :
@@ -997,9 +996,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (browser.b.width < line_len) browser.b.width = line_len; - al->idx = browser.nr_entries++; + al->idx = notes->nr_entries++;if (al->offset !=-1 ) { - al->idx_asm = browser.nr_asm_entries++; + al->idx_asm = notes->nr_asm_entries++;/* * FIXME: short term bandaid to cope with assembly * routines that comes with labels in the same column
@@ -1020,12 +1019,12 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, browser.max_addr_width =hex_width (sym->end); browser.jumps_width =width_jumps (notes->max_jump_sources); notes->nr_events = nr_pcnt; - browser.b.nr_entries = browser.nr_entries; + browser.b.nr_entries = notes->nr_entries; browser.b.entries = ¬es->src->source, browser.b.width +=18 ;/* Percentage */ if (notes->options->hide_src_code) -annotate_browser__init_asm_mode (&browser); +ui_browser__init_asm_mode (&browser.b);annotate_browser__update_addr_width (&browser);
tools/perf/util/annotate.h +2 -0
@@ -175,6 +175,8 @@ struct annotation {int nr_events;int nr_jumps;int max_jump_sources; +int nr_entries; +int nr_asm_entries;bool have_cycles;struct annotated_source *src; };
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 19/44 perf annotate: Introduce set_offsets() method out of TUI code
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
More non-strictly TUI code being moved to the UI neutral annotation library, to be used in the upcoming --stdio2 output mode.
--- tools/perf/ui/browsers/annotate.c | 24 ++---------------------- tools/perf/util/annotate.c | 28 ++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 3 +++ 3 files changed, 33 insertions(+), 22 deletions(-)
tools/perf/ui/browsers/annotate.c +2 -22
@@ -938,7 +938,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,struct perf_evsel *evsel, struct hist_browser_timer *hbt) { - struct annotation_line *al; struct annotation *notes = symbol__annotation(sym);size_t size; struct map_symbol ms = {
@@ -991,27 +990,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, notes->start =map__rip_2objdump (map, sym->start); -list_for_each_entry (al, ¬es->src->source, node) { -size_t line_len =strlen (al->line); - -if (browser.b.width < line_len) - browser.b.width = line_len; - al->idx = notes->nr_entries++; -if (al->offset !=-1 ) { - al->idx_asm = notes->nr_asm_entries++; -/* -* FIXME: short term bandaid to cope with assembly -* routines that comes with labels in the same column -* as the address in objdump, sigh. -* -* E.g. copy_user_generic_unrolled -*/ -if (al->offset < (s64 )size) - notes->offsets[al->offset] = al; - }else - al->idx_asm =-1 ; - } - +annotation__set_offsets (notes, size); + browser.b.width = notes->max_line_len;annotation__mark_jump_targets (notes, sym);annotation__compute_ipc (notes, size);
tools/perf/util/annotate.c +28 -0
@@ -2056,6 +2056,34 @@ void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym) } } +void annotation__set_offsets (struct annotation *notes,s64 size) +{ +struct annotation_line *al; + + notes->max_line_len =0 ; + +list_for_each_entry (al, ¬es->src->source, node) { +size_t line_len =strlen (al->line); + +if (notes->max_line_len < line_len) + notes->max_line_len = line_len; + al->idx = notes->nr_entries++; +if (al->offset !=-1 ) { + al->idx_asm = notes->nr_asm_entries++; +/* +* FIXME: short term bandaid to cope with assembly +* routines that comes with labels in the same column +* as the address in objdump, sigh. +* +* E.g. copy_user_generic_unrolled +*/ +if (al->offset < size) + notes->offsets[al->offset] = al; + }else + al->idx_asm =-1 ; + } +} +static void annotation__calc_lines (struct annotation *notes,struct map *map,struct rb_root *root,u64 start) {
tools/perf/util/annotate.h +3 -0
@@ -177,6 +177,7 @@ struct annotation {int max_jump_sources;int nr_entries;int nr_asm_entries; +u16 max_line_len;bool have_cycles;struct annotated_source *src; };
@@ -191,6 +192,8 @@ static inline int annotation__pcnt_width(struct annotation *notes)return (notes->options->show_total_period ?12 :7 ) * notes->nr_events; } + +void annotation__set_offsets (struct annotation *notes,s64 size);void annotation__compute_ipc (struct annotation *notes,size_t size);void annotation__mark_jump_targets (struct annotation *notes,struct symbol *sym);
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 20/44 perf annotate: Move the column widths from the TUI to generic lib
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This also will be used in other output formats, such as --stdio2.
--- tools/perf/ui/browsers/annotate.c | 45 +++++++++++++++++---------------------- tools/perf/util/annotate.h | 7 ++++++ 2 files changed, 26 insertions(+), 26 deletions(-)
tools/perf/ui/browsers/annotate.c +19 -26
@@ -36,11 +36,6 @@ struct annotate_browser {struct annotation_line *selection;struct arch *arch;bool searching_backwards; -u8 addr_width; -u8 jumps_width; -u8 target_width; -u8 min_addr_width; -u8 max_addr_width;char search_bf[128 ]; };
@@ -194,10 +189,10 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intelse if (al->offset ==-1 ) {if (al->line_nr && notes->options->show_linenr) printed =scnprintf (bf,sizeof (bf),"%-*d " , - ab->addr_width +1 , al->line_nr); + notes->widths.addr +1 , al->line_nr);else printed =scnprintf (bf,sizeof (bf),"%*s " , - ab->addr_width," " ); + notes->widths.addr," " );ui_browser__write_nstring (browser, bf, printed);ui_browser__write_nstring (browser, al->line, width - printed - pcnt_width - cycles_width +1 ); }else {
@@ -214,7 +209,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intif (notes->options->show_nr_jumps) {int prev; printed =scnprintf (bf,sizeof (bf),"%*d " , - ab->jumps_width, + notes->widths.jumps, al->jump_sources); prev =ui_browser__set_jumps_percent_color (browser, al->jump_sources, current_entry);
@@ -223,10 +218,10 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int } printed =scnprintf (bf,sizeof (bf),"%*" PRIx64": " , - ab->target_width, addr); + notes->widths.target, addr); }else { printed =scnprintf (bf,sizeof (bf),"%*s " , - ab->addr_width," " ); + notes->widths.addr," " ); } }
@@ -322,12 +317,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)ui_browser__set_color (browser,HE_COLORSET_JUMP_ARROWS );__ui_browser__line_arrow (browser, - pcnt_width +2 + ab->addr_width + width, + pcnt_width +2 + notes->widths.addr + width, from, to);if (is_fused (ab, cursor)) {ui_browser__mark_fused (browser, - pcnt_width +3 + ab->addr_width + width, + pcnt_width +3 + notes->widths.addr + width, from -1 , to > from ? true : false); }
@@ -703,19 +698,17 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,return __annotate_browser__search_reverse (browser); } -static void annotate_browser__update_addr_width (struct annotate_browser *browser) +static void annotation__update_column_widths (struct annotation *notes) { -struct annotation *notes =browser__annotation (&browser->b); -if (notes->options->use_offset) - browser->target_width = browser->min_addr_width; + notes->widths.target = notes->widths.min_addr;else - browser->target_width = browser->max_addr_width; + notes->widths.target = notes->widths.max_addr; - browser->addr_width = browser->target_width; + notes->widths.addr = notes->widths.target;if (notes->options->show_nr_jumps) - browser->addr_width += browser->jumps_width +1 ; + notes->widths.addr += notes->widths.jumps +1 ; } static int annotate_browser__run(struct annotate_browser *browser,
@@ -820,14 +813,14 @@ static int annotate_browser__run(struct annotate_browser *browser,continue ;case 'o' : notes->options->use_offset = !notes->options->use_offset; -annotate_browser__update_addr_width (browser); +annotation__update_column_widths (notes);continue ;case 'j' : notes->options->jump_arrows = !notes->options->jump_arrows;continue ;case 'J' : notes->options->show_nr_jumps = !notes->options->show_nr_jumps; -annotate_browser__update_addr_width (browser); +annotation__update_column_widths (notes);continue ;case '/' :if (annotate_browser__search (browser, delay_secs)) {
@@ -884,7 +877,7 @@ static int annotate_browser__run(struct annotate_browser *browser, notes->options->show_nr_samples = false; else notes->options->show_total_period = true; -annotate_browser__update_addr_width (browser); +annotation__update_column_widths (notes);continue ;case K_LEFT :case K_ESC :
@@ -995,9 +988,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,annotation__mark_jump_targets (notes, sym);annotation__compute_ipc (notes, size); - browser.addr_width = browser.target_width = browser.min_addr_width =hex_width (size); - browser.max_addr_width =hex_width (sym->end); - browser.jumps_width =width_jumps (notes->max_jump_sources); + notes->widths.addr = notes->widths.target = notes->widths.min_addr =hex_width (size); + notes->widths.max_addr =hex_width (sym->end); + notes->widths.jumps =width_jumps (notes->max_jump_sources); notes->nr_events = nr_pcnt; browser.b.nr_entries = notes->nr_entries; browser.b.entries = ¬es->src->source,
@@ -1006,7 +999,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (notes->options->hide_src_code)ui_browser__init_asm_mode (&browser.b); -annotate_browser__update_addr_width (&browser); +annotation__update_column_widths (notes); ret =annotate_browser__run (&browser, evsel, hbt);
tools/perf/util/annotate.h +7 -0
@@ -178,6 +178,13 @@ struct annotation {int nr_entries;int nr_asm_entries;u16 max_line_len; +struct { +u8 addr; +u8 jumps; +u8 target; +u8 min_addr; +u8 max_addr; + } widths;bool have_cycles;struct annotated_source *src; };
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 21/44 perf annotate: Move update_column_widths() to the generic lib
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Previous patch left it where it was to ease review, move it to its right place.
--- tools/perf/ui/browsers/annotate.c | 13 ------------- tools/perf/util/annotate.c | 13 +++++++++++++ tools/perf/util/annotate.h | 1 + 3 files changed, 14 insertions(+), 13 deletions(-)
tools/perf/ui/browsers/annotate.c +0 -13
@@ -698,19 +698,6 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,return __annotate_browser__search_reverse (browser); } -static void annotation__update_column_widths (struct annotation *notes) -{ -if (notes->options->use_offset) - notes->widths.target = notes->widths.min_addr; -else - notes->widths.target = notes->widths.max_addr; - - notes->widths.addr = notes->widths.target; - -if (notes->options->show_nr_jumps) - notes->widths.addr += notes->widths.jumps +1 ; -} -static int annotate_browser__run (struct annotate_browser *browser,struct perf_evsel *evsel,struct hist_browser_timer *hbt)
tools/perf/util/annotate.c +13 -0
@@ -2084,6 +2084,19 @@ void annotation__set_offsets(struct annotation *notes, s64 size) } } +void annotation__update_column_widths (struct annotation *notes) +{ +if (notes->options->use_offset) + notes->widths.target = notes->widths.min_addr; +else + notes->widths.target = notes->widths.max_addr; + + notes->widths.addr = notes->widths.target; + +if (notes->options->show_nr_jumps) + notes->widths.addr += notes->widths.jumps +1 ; +} +static void annotation__calc_lines (struct annotation *notes,struct map *map,struct rb_root *root,u64 start) {
tools/perf/util/annotate.h +1 -0
@@ -203,6 +203,7 @@ static inline int annotation__pcnt_width(struct annotation *notes)void annotation__set_offsets (struct annotation *notes,s64 size);void annotation__compute_ipc (struct annotation *notes,size_t size);void annotation__mark_jump_targets (struct annotation *notes,struct symbol *sym); +void annotation__update_column_widths (struct annotation *notes);static inline struct sym_hist *annotation__histogram (struct annotation *notes,int idx) {
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 22/44 perf annotate: Introduce init_column_widths() method out of TUI code
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
More non-TUI stuff goes to the UI-agnostic library
--- tools/perf/ui/browsers/annotate.c | 14 +------------- tools/perf/util/annotate.c | 17 +++++++++++++++++ tools/perf/util/annotate.h | 1 + 3 files changed, 19 insertions(+), 13 deletions(-)
tools/perf/ui/browsers/annotate.c +1 -13
@@ -905,15 +905,6 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,return map_symbol__tui_annotate (&he->ms, evsel, hbt); } -static inline int width_jumps (int n) -{ -if (n >=100 ) -return 5 ; -if (n /10 ) -return 2 ; -return 1 ; -} -int symbol__tui_annotate (struct symbol *sym,struct map *map,struct perf_evsel *evsel,struct hist_browser_timer *hbt)
@@ -974,10 +965,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, browser.b.width = notes->max_line_len;annotation__mark_jump_targets (notes, sym);annotation__compute_ipc (notes, size); - - notes->widths.addr = notes->widths.target = notes->widths.min_addr =hex_width (size); - notes->widths.max_addr =hex_width (sym->end); - notes->widths.jumps =width_jumps (notes->max_jump_sources); +annotation__init_column_widths (notes, sym); notes->nr_events = nr_pcnt; browser.b.nr_entries = notes->nr_entries; browser.b.entries = ¬es->src->source,
tools/perf/util/annotate.c +17 -0
@@ -2084,6 +2084,23 @@ void annotation__set_offsets(struct annotation *notes, s64 size) } } +static inline int width_jumps (int n) +{ +if (n >=100 ) +return 5 ; +if (n /10 ) +return 2 ; +return 1 ; +} + +void annotation__init_column_widths (struct annotation *notes,struct symbol *sym) +{ + notes->widths.addr = notes->widths.target = + notes->widths.min_addr =hex_width (symbol__size (sym)); + notes->widths.max_addr =hex_width (sym->end); + notes->widths.jumps =width_jumps (notes->max_jump_sources); +} +void annotation__update_column_widths (struct annotation *notes) {if (notes->options->use_offset)
tools/perf/util/annotate.h +1 -0
@@ -204,6 +204,7 @@ void annotation__set_offsets(struct annotation *notes, s64 size);void annotation__compute_ipc (struct annotation *notes,size_t size);void annotation__mark_jump_targets (struct annotation *notes,struct symbol *sym);void annotation__update_column_widths (struct annotation *notes); +void annotation__init_column_widths (struct annotation *notes,struct symbol *sym);static inline struct sym_hist *annotation__histogram (struct annotation *notes,int idx) {
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 23/44 perf annotate: Introduce symbol__annotate2 method
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
That does all the extended boilerplate the TUI browser did, leaving the symbol__annotate() function to be used by the old --stdio output mode.
Now the upcoming --stdio2 output mode should just use this one to set things up.
--- tools/perf/ui/browsers/annotate.c | 28 +--------------------------- tools/perf/util/annotate.c | 39 +++++++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 4 ++++ 3 files changed, 44 insertions(+), 27 deletions(-)
tools/perf/ui/browsers/annotate.c +1 -27
@@ -910,7 +910,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, struct hist_browser_timer *hbt) {struct annotation *notes =symbol__annotation (sym); -size_t size;struct map_symbol ms = { .map = map, .sym = sym,
@@ -926,28 +925,14 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, }, };int ret =-1 , err; -int nr_pcnt =1 ;if (sym ==NULL )return -1 ; - size =symbol__size (sym); -if (map->dso->annotate_warned)return -1 ; - notes->options = &annotate_browser__opts; - - notes->offsets =zalloc (size *sizeof (struct annotation_line *)); -if (notes->offsets ==NULL ) { -ui__error ("Not enough memory!" ); -return -1 ; - } - -if (perf_evsel__is_group_event (evsel)) - nr_pcnt = evsel->nr_members; - - err =symbol__annotate (sym, map, evsel,0 , &browser.arch); + err =symbol__annotate2 (sym, map, evsel, &annotate_browser__opts, &browser.arch);if (err) {char msg[BUFSIZ ];symbol__strerror_disassemble (sym, map, err, msg,sizeof (msg));
@@ -955,18 +940,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, goto out_free_offsets; } -symbol__calc_percent (sym, evsel); -ui_helpline__push ("Press ESC to exit" ); - notes->start =map__rip_2objdump (map, sym->start); - -annotation__set_offsets (notes, size); browser.b.width = notes->max_line_len; -annotation__mark_jump_targets (notes, sym); -annotation__compute_ipc (notes, size); -annotation__init_column_widths (notes, sym); - notes->nr_events = nr_pcnt; browser.b.nr_entries = notes->nr_entries; browser.b.entries = ¬es->src->source, browser.b.width +=18 ;/* Percentage */
@@ -974,8 +950,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,if (notes->options->hide_src_code)ui_browser__init_asm_mode (&browser.b); -annotation__update_column_widths (notes); - ret =annotate_browser__run (&browser, evsel, hbt);annotated_source__purge (notes->src);
tools/perf/util/annotate.c +39 -0
@@ -2183,3 +2183,42 @@ bool ui__has_annotation(void) {return use_browser ==1 && perf_hpp_list.sym; } + +int symbol__annotate2 (struct symbol *sym,struct map *map,struct perf_evsel *evsel, +struct annotation_options *options,struct arch **parch) +{ +struct annotation *notes =symbol__annotation (sym); +size_t size =symbol__size (sym); +int nr_pcnt =1 , err; + + notes->offsets =zalloc (size *sizeof (struct annotation_line *)); +if (notes->offsets ==NULL ) +return -1 ; + +if (perf_evsel__is_group_event (evsel)) + nr_pcnt = evsel->nr_members; + + err =symbol__annotate (sym, map, evsel,0 , parch); +if (err) + goto out_free_offsets; + + notes->options = options; + +symbol__calc_percent (sym, evsel); + + notes->start =map__rip_2objdump (map, sym->start); + +annotation__set_offsets (notes, size); +annotation__mark_jump_targets (notes, sym); +annotation__compute_ipc (notes, size); +annotation__init_column_widths (notes, sym); + notes->nr_events = nr_pcnt; + +annotation__update_column_widths (notes); + +return 0 ; + +out_free_offsets: +zfree (¬es->offsets); +return -1 ; +}
tools/perf/util/annotate.h +4 -0
@@ -233,6 +233,10 @@ void symbol__annotate_zero_histograms(struct symbol *sym);int symbol__annotate (struct symbol *sym,struct map *map,struct perf_evsel *evsel,size_t privsize,struct arch **parch); +int symbol__annotate2 (struct symbol *sym,struct map *map, +struct perf_evsel *evsel, +struct annotation_options *options, +struct arch **parch);enum symbol_disassemble_errno {SYMBOL_ANNOTATE_ERRNO__SUCCESS =0 ,
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 24/44 perf annotate: Introduce annotation_line__max_percent()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Out of the annotate_browser__write() routine, to be used in the --stdio2 mode.
--- tools/perf/ui/browsers/annotate.c | 7 +------ tools/perf/util/annotate.c | 14 ++++++++++++++ tools/perf/util/annotate.h | 3 +++ 3 files changed, 18 insertions(+), 6 deletions(-)
tools/perf/ui/browsers/annotate.c +1 -6
@@ -117,15 +117,10 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intint width = browser->width, printed;int i, pcnt_width =annotation__pcnt_width (notes), cycles_width =annotation__cycles_width (notes); -double percent_max =0.0 ; +double percent_max =annotation_line__max_percent (al, notes);char bf[256 ];bool show_title = false; -for (i =0 ; i < notes->nr_events; i++) { -if (al->samples[i].percent > percent_max) - percent_max = al->samples[i].percent; - } -if ((row ==0 ) && (al->offset ==-1 || percent_max ==0.0 )) {if (notes->have_cycles) {if (al->ipc ==0.0 && al->cycles ==0 )
tools/perf/util/annotate.c +14 -0
@@ -2184,6 +2184,20 @@ bool ui__has_annotation(void)return use_browser ==1 && perf_hpp_list.sym; } + +double annotation_line__max_percent (struct annotation_line *al,struct annotation *notes) +{ +double percent_max =0.0 ; +int i; + +for (i =0 ; i < notes->nr_events; i++) { +if (al->samples[i].percent > percent_max) + percent_max = al->samples[i].percent; + } + +return percent_max; +} +int symbol__annotate2 (struct symbol *sym,struct map *map,struct perf_evsel *evsel,struct annotation_options *options,struct arch **parch) {
tools/perf/util/annotate.h +3 -0
@@ -124,6 +124,9 @@ bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym);void disasm_line__free (struct disasm_line *dl);struct annotation_line *annotation_line__next (struct annotation_line *pos,struct list_head *head); + +double annotation_line__max_percent (struct annotation_line *al,struct annotation *notes); +int disasm_line__scnprintf (struct disasm_line *dl,char *bf,size_t size,bool raw);size_t disasm__fprintf (struct list_head *head,FILE *fp);void symbol__calc_percent (struct symbol *sym,struct perf_evsel *evsel);
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 25/44 perf ui browser: Add vprintf() method
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We'll need it for some callbacks for the upcoming annotation__line_print() routines.
--- tools/perf/ui/browser.c | 7 ++++++- tools/perf/ui/browser.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-)
tools/perf/ui/browser.c +6 -1
@@ -56,12 +56,17 @@ void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, constslsmg_write_nstring (msg, width); } +void ui_browser__vprintf (struct ui_browser *browser__maybe_unused ,const char *fmt,va_list args) +{ +slsmg_vprintf (fmt, args); +} +void ui_browser__printf (struct ui_browser *browser__maybe_unused ,const char *fmt, ...) {va_list args;va_start (args, fmt); -slsmg_vprintf (fmt, args); +ui_browser__vprintf (browser, fmt, args);va_end (args); }
tools/perf/ui/browser.h +2 -0
@@ -3,6 +3,7 @@#define _PERF_UI_BROWSER_H_ 1#include <linux/types.h> +#include <stdarg.h> #define HE_COLORSET_TOP 50#define HE_COLORSET_MEDIUM 51
@@ -40,6 +41,7 @@ void ui_browser__reset_index(struct ui_browser *browser);void ui_browser__gotorc (struct ui_browser *browser,int y,int x);void ui_browser__write_nstring (struct ui_browser *browser,const char *msg,unsigned int width); +void ui_browser__vprintf (struct ui_browser *browser,const char *fmt,va_list args);void ui_browser__printf (struct ui_browser *browser,const char *fmt, ...);void ui_browser__write_graph (struct ui_browser *browser,int graph); void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 26/44 perf annotate: Introduce annotation_line__print_start() out of TUI code
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
For the --tui and --stdio2 cases using callbacks for print() and set_percent_color() end up being the easiest path, real GUI remains as an exercise.
--- tools/perf/ui/browsers/annotate.c | 82 ++++++++++----------------------------- tools/perf/util/annotate.c | 75 +++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 5 +++ 3 files changed, 101 insertions(+), 61 deletions(-)
tools/perf/ui/browsers/annotate.c +21 -61
@@ -105,6 +105,20 @@ static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browsedisasm_line__scnprintf (dl, bf, size, !notes->options->use_offset); } +static void annotate_browser__set_percent_color (void *browser,double percent,bool current) +{ +ui_browser__set_percent_color (browser, percent, current); +} + +static void annotate_browser__printf (void *browser,const char *fmt, ...) +{ +va_list args; + +va_start (args, fmt); +ui_browser__vprintf (browser, fmt, args); +va_end (args); +} +static void annotate_browser__write (struct ui_browser *browser,void *entry,int row) { struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
@@ -115,65 +129,13 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int (!current_entry || (browser->use_navkeypressed && !browser->navkeypressed)));int width = browser->width, printed; -int i, pcnt_width =annotation__pcnt_width (notes), - cycles_width =annotation__cycles_width (notes); -double percent_max =annotation_line__max_percent (al, notes); +int pcnt_width =annotation__pcnt_width (notes), + cycles_width =annotation__cycles_width (notes);char bf[256 ]; -bool show_title = false; - -if ((row ==0 ) && (al->offset ==-1 || percent_max ==0.0 )) { -if (notes->have_cycles) { -if (al->ipc ==0.0 && al->cycles ==0 ) - show_title = true; - }else - show_title = true; - } - -if (al->offset !=-1 && percent_max !=0.0 ) { -for (i =0 ; i < notes->nr_events; i++) { -ui_browser__set_percent_color (browser, - al->samples[i].percent, - current_entry); -if (notes->options->show_total_period) { -ui_browser__printf (browser,"%11" PRIu64" " , - al->samples[i].he.period); - }else if (notes->options->show_nr_samples) { -ui_browser__printf (browser,"%6" PRIu64" " , - al->samples[i].he.nr_samples); - }else { -ui_browser__printf (browser,"%6.2f " , - al->samples[i].percent); - } - } - }else { -ui_browser__set_percent_color (browser,0 , current_entry); - -if (!show_title) -ui_browser__write_nstring (browser," " , pcnt_width); -else { -ui_browser__printf (browser,"%*s" , pcnt_width, - notes->options->show_total_period ?"Period" : - notes->options->show_nr_samples ?"Samples" :"Percent" ); - } - } -if (notes->have_cycles) { -if (al->ipc) -ui_browser__printf (browser,"%*.2f " ,ANNOTATION__IPC_WIDTH -1 , al->ipc); -else if (!show_title) -ui_browser__write_nstring (browser," " ,ANNOTATION__IPC_WIDTH ); -else -ui_browser__printf (browser,"%*s " ,ANNOTATION__IPC_WIDTH -1 ,"IPC" ); - -if (al->cycles) -ui_browser__printf (browser,"%*" PRIu64" " , -ANNOTATION__CYCLES_WIDTH -1 , al->cycles); -else if (!show_title) -ui_browser__write_nstring (browser," " ,ANNOTATION__CYCLES_WIDTH ); -else -ui_browser__printf (browser,"%*s " ,ANNOTATION__CYCLES_WIDTH -1 ,"Cycle" ); - } -SLsmg_write_char (' ' ); +annotation_line__print_start (al, notes, row ==0 , current_entry, browser, + annotate_browser__set_percent_color, + annotate_browser__printf);/* The scroll bar isn't being used */ if (!browser->navkeypressed)
@@ -183,11 +145,9 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intui_browser__write_nstring (browser," " , width - pcnt_width - cycles_width); else if (al->offset == -1) {if (al->line_nr && notes->options->show_linenr) - printed =scnprintf (bf,sizeof (bf),"%-*d " , - notes->widths.addr +1 , al->line_nr); + printed =scnprintf (bf,sizeof (bf),"%-*d " , notes->widths.addr +1 , al->line_nr);else - printed =scnprintf (bf,sizeof (bf),"%*s " , - notes->widths.addr," " ); + printed =scnprintf (bf,sizeof (bf),"%*s " , notes->widths.addr," " );ui_browser__write_nstring (browser, bf, printed);ui_browser__write_nstring (browser, al->line, width - printed - pcnt_width - cycles_width +1 ); } else {
tools/perf/util/annotate.c +75 -0
81 lines not on this page · raw message
tools/perf/util/annotate.h +5 -0
@@ -126,6 +126,11 @@ struct annotation_line * annotation_line__next(struct annotation_line *pos, struct list_head *head);double annotation_line__max_percent (struct annotation_line *al,struct annotation *notes); +void annotation_line__print_start (struct annotation_line *al,struct annotation *notes, +bool first_line,bool current_entry, +void *obj, +void (*obj__set_percent_color)(void *obj,double percent,bool current), +void (*obj__printf)(void *obj,const char *fmt, ...));int disasm_line__scnprintf (struct disasm_line *dl,char *bf,size_t size,bool raw);size_t disasm__fprintf (struct list_head *head,FILE *fp);
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 27/44 perf annotate: Finish the generalization of annotate_browser__write()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We pass some more callbacks and all of annotate_browser__write() seems to be free of TUI code (except for some arrow constants, will fix).
--- tools/perf/ui/browsers/annotate.c | 97 +++++--------------------------- tools/perf/util/annotate.c | 113 +++++++++++++++++++++++++++++++++++--- tools/perf/util/annotate.h | 13 +++-- 3 files changed, 127 insertions(+), 96 deletions(-)
tools/perf/ui/browsers/annotate.c +15 -82
@@ -71,38 +71,20 @@ static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, breturn HE_COLORSET_NORMAL ; } -static int ui_browser__set_jumps_percent_color (struct ui_browser *browser,int nr,bool current) +static int ui_browser__set_jumps_percent_color (void *browser,int nr,bool current) {int color =ui_browser__jumps_percent_color (browser, nr, current);return ui_browser__set_color (browser, color); } -static void disasm_line__write (struct disasm_line *dl,struct ui_browser *browser, -char *bf,size_t size) +static int annotate_browser__set_color (void *browser,int color) { -struct annotation *notes =browser__annotation (browser); - -if (dl->ins.ops && dl->ins.ops->scnprintf) { -if (ins__is_jump (&dl->ins)) { -bool fwd = dl->ops.target.offset > dl->al.offset; - -ui_browser__write_graph (browser, fwd ?SLSMG_DARROW_CHAR : -SLSMG_UARROW_CHAR ); -SLsmg_write_char (' ' ); - }else if (ins__is_call (&dl->ins)) { -ui_browser__write_graph (browser,SLSMG_RARROW_CHAR ); -SLsmg_write_char (' ' ); - }else if (ins__is_ret (&dl->ins)) { -ui_browser__write_graph (browser,SLSMG_LARROW_CHAR ); -SLsmg_write_char (' ' ); - }else { -ui_browser__write_nstring (browser," " ,2 ); - } - }else { -ui_browser__write_nstring (browser," " ,2 ); - } +return ui_browser__set_color (browser, color); +} -disasm_line__scnprintf (dl, bf, size, !notes->options->use_offset); +static void annotate_browser__write_graph (void *browser,int graph) +{ +ui_browser__write_graph (browser, graph); }static void annotate_browser__set_percent_color (void *browser,double percent,bool current)
@@ -128,68 +110,19 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, intbool change_color = (!notes->options->hide_src_code && (!current_entry || (browser->use_navkeypressed && !browser->navkeypressed))); -int width = browser->width, printed; -int pcnt_width =annotation__pcnt_width (notes), - cycles_width =annotation__cycles_width (notes); -char bf[256 ]; - -annotation_line__print_start (al, notes, row ==0 , current_entry, browser, - annotate_browser__set_percent_color, - annotate_browser__printf); +int width = browser->width;/* The scroll bar isn't being used */ if (!browser->navkeypressed) width +=1 ; -if (!*al->line) -ui_browser__write_nstring (browser," " , width - pcnt_width - cycles_width); -else if (al->offset ==-1 ) { -if (al->line_nr && notes->options->show_linenr) - printed =scnprintf (bf,sizeof (bf),"%-*d " , notes->widths.addr +1 , al->line_nr); -else - printed =scnprintf (bf,sizeof (bf),"%*s " , notes->widths.addr," " ); -ui_browser__write_nstring (browser, bf, printed); -ui_browser__write_nstring (browser, al->line, width - printed - pcnt_width - cycles_width +1 ); - }else { -u64 addr = al->offset; -int color =-1 ; - -if (!notes->options->use_offset) - addr += notes->start; - -if (!notes->options->use_offset) { - printed =scnprintf (bf,sizeof (bf),"%" PRIx64": " , addr); - }else { -if (al->jump_sources) { -if (notes->options->show_nr_jumps) { -int prev; - printed =scnprintf (bf,sizeof (bf),"%*d " , - notes->widths.jumps, - al->jump_sources); - prev =ui_browser__set_jumps_percent_color (browser, al->jump_sources, - current_entry); -ui_browser__write_nstring (browser, bf, printed); -ui_browser__set_color (browser, prev); - } - - printed =scnprintf (bf,sizeof (bf),"%*" PRIx64": " , - notes->widths.target, addr); - }else { - printed =scnprintf (bf,sizeof (bf),"%*s " , - notes->widths.addr," " ); - } - } - -if (change_color) - color =ui_browser__set_color (browser,HE_COLORSET_ADDR ); -ui_browser__write_nstring (browser, bf, printed); -if (change_color) -ui_browser__set_color (browser, color); - -disasm_line__write (disasm_line (al), browser, bf,sizeof (bf)); - -ui_browser__write_nstring (browser, bf, width - pcnt_width - cycles_width -3 - printed); - } +annotation_line__write (al, notes, row ==0 , current_entry, change_color, + width, browser, + annotate_browser__set_color, + annotate_browser__set_percent_color, + ui_browser__set_jumps_percent_color, + annotate_browser__printf, + annotate_browser__write_graph);if (current_entry) ab->selection = al;
tools/perf/util/annotate.c +104 -9
144 lines not on this page · raw message
tools/perf/util/annotate.h +8 -5
@@ -126,11 +126,14 @@ struct annotation_line * annotation_line__next(struct annotation_line *pos, struct list_head *head);double annotation_line__max_percent (struct annotation_line *al,struct annotation *notes); -void annotation_line__print_start (struct annotation_line *al,struct annotation *notes, -bool first_line,bool current_entry, -void *obj, -void (*obj__set_percent_color)(void *obj,double percent,bool current), -void (*obj__printf)(void *obj,const char *fmt, ...)); +void annotation_line__write (struct annotation_line *al,struct annotation *notes, +bool first_line,bool current_entry,bool change_color,int width, +void *obj, +int (*obj__set_color)(void *obj,int color), +void (*obj__set_percent_color)(void *obj,double percent,bool current), +int (*obj__set_jumps_percent_color)(void *obj,int nr,bool current), +void (*obj__printf)(void *obj,const char *fmt, ...), +void (*obj__write_graph)(void *obj,int graph));int disasm_line__scnprintf (struct disasm_line *dl,char *bf,size_t size,bool raw);size_t disasm__fprintf (struct list_head *head,FILE *fp);
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 28/44 perf annotate: Use a ops table for annotation_line__write()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To simplify the passing of arguments, the --stdio2 code will have to set all the fields with operations printing to stdout.
--- tools/perf/ui/browsers/annotate.c | 32 +++++++++++++++------------- tools/perf/util/annotate.c | 44 ++++++++++++++++++++------------------- tools/perf/util/annotate.h | 19 ++++++++++------- 3 files changed, 53 insertions(+), 42 deletions(-)
tools/perf/ui/browsers/annotate.c +18 -14
@@ -106,25 +106,29 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);struct annotation *notes =browser__annotation (browser); struct annotation_line *al = list_entry(entry, struct annotation_line, node); -bool current_entry =ui_browser__is_current_entry (browser, row); -bool change_color = (!notes->options->hide_src_code && - (!current_entry || (browser->use_navkeypressed && - !browser->navkeypressed))); -int width = browser->width; +struct annotation_write_ops ops = { + .first_line = row ==0 , + .current_entry =ui_browser__is_current_entry (browser, row), + .change_color = (!notes->options->hide_src_code && + (!ops.current_entry || + (browser->use_navkeypressed && + !browser->navkeypressed))), + .width = browser->width, + .obj = browser, + .set_color = annotate_browser__set_color, + .set_percent_color = annotate_browser__set_percent_color, + .set_jumps_percent_color = ui_browser__set_jumps_percent_color, + .printf = annotate_browser__printf, + .write_graph = annotate_browser__write_graph, + };/* The scroll bar isn't being used */ if (!browser->navkeypressed) - width +=1 ; + ops.width +=1 ; -annotation_line__write (al, notes, row ==0 , current_entry, change_color, - width, browser, - annotate_browser__set_color, - annotate_browser__set_percent_color, - ui_browser__set_jumps_percent_color, - annotate_browser__printf, - annotate_browser__write_graph); +annotation_line__write (al, notes, &ops); -if (current_entry) +if (ops.current_entry) ab->selection = al; }
tools/perf/util/annotate.c +23 -21
74 lines not on this page · raw message
tools/perf/util/annotate.h +12 -7
@@ -125,15 +125,20 @@ void disasm_line__free(struct disasm_line *dl);struct annotation_line *annotation_line__next (struct annotation_line *pos,struct list_head *head); +struct annotation_write_ops { +bool first_line, current_entry, change_color; +int width; +void *obj; +int (*set_color)(void *obj,int color); +void (*set_percent_color)(void *obj,double percent,bool current); +int (*set_jumps_percent_color)(void *obj,int nr,bool current); +void (*printf)(void *obj,const char *fmt, ...); +void (*write_graph)(void *obj,int graph); +}; +double annotation_line__max_percent (struct annotation_line *al,struct annotation *notes);void annotation_line__write (struct annotation_line *al,struct annotation *notes, -bool first_line,bool current_entry,bool change_color,int width, -void *obj, -int (*obj__set_color)(void *obj,int color), -void (*obj__set_percent_color)(void *obj,double percent,bool current), -int (*obj__set_jumps_percent_color)(void *obj,int nr,bool current), -void (*obj__printf)(void *obj,const char *fmt, ...), -void (*obj__write_graph)(void *obj,int graph)); +struct annotation_write_ops *ops);int disasm_line__scnprintf (struct disasm_line *dl,char *bf,size_t size,bool raw);size_t disasm__fprintf (struct list_head *head,FILE *fp);
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 29/44 perf annotate: Introduce annotation_line__filter()
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Out of the TUI logic that allows toggling the presentation of source code lines.
Will be used in the upcoming --stdio2 mode.
--- tools/perf/ui/browsers/annotate.c | 19 +++++++------------ tools/perf/util/annotate.h | 4 ++++ 2 files changed, 11 insertions(+), 12 deletions(-)
tools/perf/ui/browsers/annotate.c +7 -12
@@ -48,14 +48,8 @@ static inline struct annotation *browser__annotation(struct ui_browser *browser)static bool disasm_line__filter (struct ui_browser *browser,void *entry) {struct annotation *notes =browser__annotation (browser); - -if (notes->options->hide_src_code) { - struct annotation_line *al = list_entry(entry, struct annotation_line, node); - -return al->offset ==-1 ; - } - -return false; + struct annotation_line *al = list_entry(entry, struct annotation_line, node); +return annotation_line__filter (al, notes); }static int ui_browser__jumps_percent_color (struct ui_browser *browser,int nr,bool current)
@@ -268,6 +262,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_linestatic void annotate_browser__set_top (struct annotate_browser *browser,struct annotation_line *pos,u32 idx) { +struct annotation *notes =browser__annotation (&browser->b);unsigned back;ui_browser__refresh_dimensions (&browser->b);
@@ -277,7 +272,7 @@ static void annotate_browser__set_top(struct annotate_browser *browser,while (browser->b.top_idx !=0 && back !=0 ) { pos = list_entry(pos->node.prev, struct annotation_line, node); -if (disasm_line__filter (&browser->b, &pos->node)) +if (annotation_line__filter (pos, notes))continue ; --browser->b.top_idx;
@@ -440,7 +435,7 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browslist_for_each_entry (pos, ¬es->src->source, al.node) {if (pos->al.offset == offset)return pos; -if (!disasm_line__filter (&browser->b, &pos->al.node)) +if (!annotation_line__filter (&pos->al, notes)) ++*idx; }
@@ -477,7 +472,7 @@ struct annotation_line *annotate_browser__find_string(struct annotate_browser *b *idx = browser->b.index;list_for_each_entry_continue (al, ¬es->src->source, node) { -if (disasm_line__filter (&browser->b, &al->node)) +if (annotation_line__filter (al, notes))continue ; ++*idx;
@@ -514,7 +509,7 @@ struct annotation_line *annotate_browser__find_string_reverse(struct annotate_br *idx = browser->b.index;list_for_each_entry_continue_reverse (al, ¬es->src->source, node) { -if (disasm_line__filter (&browser->b, &al->node)) +if (annotation_line__filter (al, notes))continue ; --*idx;
tools/perf/util/annotate.h +4 -0
@@ -215,6 +215,10 @@ static inline int annotation__pcnt_width(struct annotation *notes)return (notes->options->show_total_period ?12 :7 ) * notes->nr_events; } +static inline bool annotation_line__filter (struct annotation_line *al,struct annotation *notes) +{ +return notes->options->hide_src_code && al->offset ==-1 ; +}void annotation__set_offsets (struct annotation *notes,s64 size);void annotation__compute_ipc (struct annotation *notes,size_t size);
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 30/44 perf annotate: Introduce the --stdio2 output mode
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This uses the TUI augmented formatting routines, modulo interactivity.
# perf annotate --ignore-vmlinux --stdio2 _raw_spin_lock_irqsave _raw_spin_lock_irqsave() /proc/kcore Event: cycles:ppp
Percent
Disassembly of section load0:
ffffffff9a8734b0 <load0>:
nop
push %rbx
50.00 pushfq
pop %rax
nop
mov %rax,%rbx
cli
nop
xor %eax,%eax
mov $0x1,%edx 50.00 lock cmpxchg %edx,(%rdi)
test %eax,%eax
↓ jne 2b
mov %rbx,%rax
pop %rbx
← retq
2b: mov %eax,%esi
→ callq queued_spin_lock_slowpath
mov %rbx,%rax
pop %rbx
← retq
--- tools/perf/Documentation/perf-annotate.txt | 2 + tools/perf/builtin-annotate.c | 23 +++++--- tools/perf/util/annotate.c | 92 ++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 5 ++ 4 files changed, 115 insertions(+), 7 deletions(-)
tools/perf/Documentation/perf-annotate.txt +2 -0
@@ -69,6 +69,8 @@ OPTIONS --stdio:: Use the stdio interface. +--stdio2:: Use the stdio2 interface, non-interactive, uses the TUI formatting. + --stdio-color=<mode>:: 'always', 'never' or 'auto', allowing configuring color output via the command line, in addition to via "color.ui" .perfconfig.
tools/perf/builtin-annotate.c +16 -7
@@ -40,7 +40,7 @@struct perf_annotate {struct perf_tool tool;struct perf_session *session; -bool use_tui, use_stdio, use_gtk; +bool use_tui, use_stdio, use_stdio2, use_gtk;bool full_paths;bool print_line;bool skip_missing;
@@ -202,6 +202,11 @@ static int process_branch_callback(struct perf_evsel *evsel,return ret; } +static bool has_annotation (struct perf_annotate *ann) +{ +return ui__has_annotation () || ann->use_stdio2; +} + static int perf_evsel__add_sample(struct perf_evsel *evsel, struct perf_sample *sample, struct addr_location *al,
@@ -212,7 +217,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,struct hist_entry *he;int ret; -if ((!ann->has_br_stack || !ui__has_annotation ()) && +if ((!ann->has_br_stack || !has_annotation (ann)) && ann->sym_hist_filter !=NULL && (al->sym ==NULL ||strcmp (ann->sym_hist_filter, al->sym->name) !=0 )) {
@@ -236,7 +241,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,*/ process_branch_stack (sample->branch_stack, al, sample); -if (ann->has_br_stack &&ui__has_annotation ()) +if (ann->has_br_stack &&has_annotation (ann))return process_branch_callback (evsel, sample, al, ann, machine); he =hists__add_entry (hists, al,NULL ,NULL ,NULL , sample, true);
@@ -282,8 +287,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he, struct perf_evsel *evsel, struct perf_annotate *ann) { - return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, - ann->print_line, ann->full_paths, 0, 0); +if (!ann->use_stdio2) +return symbol__tty_annotate (he->ms.sym, he->ms.map, evsel, + ann->print_line, ann->full_paths,0 ,0 ); +return symbol__tty_annotate2 (he->ms.sym, he->ms.map, evsel, + ann->print_line, ann->full_paths); } static void hists__find_annotations(struct hists *hists,
@@ -487,6 +495,7 @@ int cmd_annotate(int argc, const char **argv)OPT_BOOLEAN (0 ,"gtk" , &annotate.use_gtk,"Use the GTK interface" ),OPT_BOOLEAN (0 ,"tui" , &annotate.use_tui,"Use the TUI interface" ),OPT_BOOLEAN (0 ,"stdio" , &annotate.use_stdio,"Use the stdio interface" ), +OPT_BOOLEAN (0 ,"stdio2" , &annotate.use_stdio2,"Use the stdio interface" ),OPT_STRING ('k' ,"vmlinux" , &symbol_conf.vmlinux_name,"file" ,"vmlinux pathname" ), OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
@@ -569,7 +578,7 @@ int cmd_annotate(int argc, const char **argv)if (ret <0 ) goto out_delete; -if (annotate.use_stdio) +if (annotate.use_stdio || annotate.use_stdio2) use_browser =0 ;else if (annotate.use_tui) use_browser =1 ;
@@ -578,7 +587,7 @@ int cmd_annotate(int argc, const char **argv)setup_browser (true); -if (use_browser ==1 && annotate.has_br_stack) { +if ((use_browser ==1 || annotate.use_stdio2) && annotate.has_br_stack) { sort__mode =SORT_MODE__BRANCH ;if (setup_sorting (annotate.session->evlist) <0 )usage_with_options (annotate_usage, options);
tools/perf/util/annotate.c +92 -0
104 lines not on this page · raw message
tools/perf/util/annotate.h +5 -0
@@ -281,6 +281,7 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,int symbol__annotate_printf (struct symbol *sym,struct map *map,struct perf_evsel *evsel,bool full_paths,int min_pcnt,int max_lines,int context); +int symbol__annotate_fprintf2 (struct symbol *sym,FILE *fp);void symbol__annotate_zero_histogram (struct symbol *sym,int evidx);void symbol__annotate_decay_histogram (struct symbol *sym,int evidx);void annotated_source__purge (struct annotated_source *as);
@@ -291,6 +292,10 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, struct perf_evsel *evsel, bool print_lines, bool full_paths, int min_pcnt, int max_lines); +int symbol__tty_annotate2 (struct symbol *sym,struct map *map, +struct perf_evsel *evsel,bool print_lines, +bool full_paths); +#ifdef HAVE_SLANG_SUPPORT int symbol__tui_annotate(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 31/44 perf annotate: Move the default annotate options to the library
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
One more thing that goes from the TUI code to be used more widely, for instance it'll affect the default options used by:
perf annotate --stdio2
--- tools/perf/builtin-annotate.c | 2 ++ tools/perf/builtin-report.c | 1 + tools/perf/builtin-top.c | 2 ++ tools/perf/ui/browser.c | 2 -- tools/perf/ui/browser.h | 1 - tools/perf/ui/browsers/annotate.c | 67 +-------------------------------------- tools/perf/util/annotate.c | 62 ++++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 4 +++ 8 files changed, 72 insertions(+), 69 deletions(-)
tools/perf/builtin-annotate.c +2 -0
@@ -572,6 +572,8 @@ int cmd_annotate(int argc, const char **argv)if (ret <0 ) goto out_delete; +annotation_config__init (); + symbol_conf.try_vmlinux_path = true; ret =symbol__init (&annotate.session->header.env);
tools/perf/builtin-report.c +1 -0
@@ -1340,6 +1340,7 @@ int cmd_report(int argc, const char **argv) symbol_conf.priv_size +=sizeof (u32); symbol_conf.sort_by_name = true; } +annotation_config__init (); }if (symbol__init (&session->header.env) <0 )
tools/perf/builtin-top.c +2 -0
@@ -1493,6 +1493,8 @@ int cmd_top(int argc, const char **argv)if (status <0 ) goto out_delete_evlist; +annotation_config__init (); + symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name ==NULL );if (symbol__init (NULL ) <0 )return -1 ;
tools/perf/ui/browser.c +0 -2
@@ -784,6 +784,4 @@ void ui_browser__init(void)struct ui_browser_colorset *c = &ui_browser__colorsets[i++];sltt_set_color (c->colorset, c->name, c->fg, c->bg); } - -annotate_browser__init (); }
tools/perf/ui/browser.h +0 -1
@@ -79,5 +79,4 @@ void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int whunsigned int ui_browser__list_head_refresh (struct ui_browser *browser);void ui_browser__init (void ); -void annotate_browser__init (void );#endif /* _PERF_UI_BROWSER_H_ */
tools/perf/ui/browsers/annotate.c +1 -66
94 lines not on this page · raw message
tools/perf/util/annotate.c +62 -0
77 lines not on this page · raw message
tools/perf/util/annotate.h +4 -0
@@ -71,6 +71,8 @@ struct annotation_options { show_total_period; }; +extern struct annotation_options annotation__default_options; +struct annotation ;struct sym_hist_entry {
@@ -313,4 +315,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,extern const char *disassembler_style; +void annotation_config__init (void ); +#endif /* __PERF_ANNOTATE_H */
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 32/44 perf annotate: Use the default annotation options for --stdio2
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
With an empty '[annotate]' section in ~/.perfconfig:
# perf record -a --all-kernel -e '{cycles,instructions}:P' sleep 5
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 2.243 MB perf.data (5513 samples) ]
# perf annotate --stdio2 _raw_spin_lock | head -20 Disassembly of section .text:
ffffffff81868790 <_raw_spin_lock>:
_raw_spin_lock():
EXPORT_SYMBOL(_raw_spin_trylock_bh);
#endif
#ifndef CONFIG_INLINE_SPIN_LOCK
void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)
{
→ callq __fentry__
atomic_cmpxchg():
return xadd(&v->counter, -i);
}
static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{
# perf annotate --stdio2 _raw_spin_lock | head -20
→ callq __fentry__
xor %eax,%eax
mov $0x1,%edx
87.50 100.00 lock cmpxchg %edx,(%rdi)
6.25 0.00 test %eax,%eax
↓ jne 16
6.25 0.00 repz retq
16: mov %eax,%esi
↑ jmpq ffffffff810e96b0 <queued_spin_lock_slowpath>
#
# cat ~/.perfconfig
[annotate] hide_src_code = false
show_linenr = true
# perf annotate --stdio2 _raw_spin_lock | head -20
3 Disassembly of section .text:
5 ffffffff81868790 <_raw_spin_lock>:
6 _raw_spin_lock():
143 EXPORT_SYMBOL(_raw_spin_trylock_bh);
144 #endif
146 #ifndef CONFIG_INLINE_SPIN_LOCK
147 void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)
148 {
→ callq __fentry__
150 atomic_cmpxchg():
187 return xadd(&v->counter, -i);
188 }
190 static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
191 {
#
# cat ~/.perfconfig
[annotate] hide_src_code = true
show_total_period = true
# perf annotate --stdio2 _raw_spin_lock | head -20
→ callq __fentry__
xor %eax,%eax
mov $0x1,%edx
1411316 152339 lock cmpxchg %edx,(%rdi)
344694 0 test %eax,%eax
↓ jne 16
80806 0 repz retq
16: mov %eax,%esi
↑ jmpq ffffffff810e96b0 <queued_spin_lock_slowpath>
#--- tools/perf/util/annotate.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
tools/perf/util/annotate.c +1 -3
@@ -2243,9 +2243,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map, {struct dso *dso = map->dso;struct rb_root source_line =RB_ROOT ; -struct annotation_options opts = { - .use_offset = true, - }; +struct annotation_options opts = annotation__default_options;if (symbol__annotate2 (sym, map, evsel, &opts,NULL ) <0 )return -1 ;
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 33/44 perf annotate: Add function header to --stdio2
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
# perf annotate --stdio2 _raw_spin_lock_irqsave
_raw_spin_lock_irqsave() /lib/modules/4.16.0-rc4/build/vmlinux
Event: anon group { cycles, instructions } 0.00 3.17 → callq __fentry__
0.00 7.94 push %rbx
7.69 36.51 → callq __page_file_index
mov %rax,%rbx
7.69 3.17 → callq *ffffffff82225cd0
xor %eax,%eax
mov $0x1,%edx 80.77 49.21 lock cmpxchg %edx,(%rdi)
test %eax,%eax
↓ jne 2b
3.85 0.00 mov %rbx,%rax
pop %rbx
← retq
2b: mov %eax,%esi
→ callq queued_spin_lock_slowpath
mov %rbx,%rax
pop %rbx
← retq
#
--- tools/perf/util/annotate.c | 8 ++++++++ 1 file changed, 8 insertions(+)
tools/perf/util/annotate.c +8 -0
@@ -2244,6 +2244,8 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,struct dso *dso = map->dso;struct rb_root source_line =RB_ROOT ;struct annotation_options opts = annotation__default_options; +const char *ev_name =perf_evsel__name (evsel); +char buf[1024 ];if (symbol__annotate2 (sym, map, evsel, &opts,NULL ) <0 )return -1 ;
@@ -2254,6 +2256,12 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,print_summary (&source_line, dso->long_name); } +if (perf_evsel__is_group_event (evsel)) { +perf_evsel__group_desc (evsel, buf,sizeof (buf)); + ev_name = buf; + } + +fprintf (stdout,"%s() %s\nEvent: %s\n\n" , sym->name, dso->long_name, ev_name);symbol__annotate_fprintf2 (sym, stdout);annotated_source__purge (symbol__annotation (sym)->src);
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 34/44 perf annotate: Introduce --ignore-vmlinux command line option
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This is already present in 'perf top', albeit undocumented (will fix), and is useful to use /proc/kcore instead of vmlinux and then get what is really in place, not what the kernel starts with, before alternatives, ftrace .text patching, etc, see the differences:
# perf annotate --stdio2 _raw_spin_lock_irqsave
_raw_spin_lock_irqsave() /lib/modules/4.16.0-rc4/build/vmlinux
Event: anon group { cycles, instructions } 0.00 3.17 → callq __fentry__
0.00 7.94 push %rbx
7.69 36.51 → callq __page_file_index
mov %rax,%rbx
7.69 3.17 → callq *ffffffff82225cd0
xor %eax,%eax
mov $0x1,%edx 80.77 49.21 lock cmpxchg %edx,(%rdi)
test %eax,%eax
↓ jne 2b
3.85 0.00 mov %rbx,%rax
pop %rbx
← retq
2b: mov %eax,%esi
→ callq queued_spin_lock_slowpath
mov %rbx,%rax
pop %rbx
← retq
[root@jouet ~]# perf annotate --ignore-vmlinux --stdio2 _raw_spin_lock_irqsave _raw_spin_lock_irqsave() /proc/kcore
Event: anon group { cycles, instructions }
0.00 3.17 nop
0.00 7.94 push %rbx
0.00 23.81 pushfq
7.69 12.70 pop %rax
nop
mov %rax,%rbx
7.69 3.17 cli
nop
xor %eax,%eax
mov $0x1,%edx 80.77 49.21 lock cmpxchg %edx,(%rdi)
test %eax,%eax
↓ jne 2b
3.85 0.00 mov %rbx,%rax
pop %rbx
← retq
2b: mov %eax,%esi
→ callq *ffffffff820e96b0
mov %rbx,%rax
pop %rbx
← retq
#
Diff of the output of those commands:
# perf annotate --stdio2 _raw_spin_lock_irqsave > /tmp/vmlinux
# perf annotate --ignore-vmlinux --stdio2 _raw_spin_lock_irqsave > /tmp/kcore
# diff -y /tmp/vmlinux /tmp/kcore
_raw_spin_lock_irqsave() vmlinux | _raw_spin_lock_irqsave() /proc/kcore
Event: anon group { cycles, instructions } Event: anon group { cycles, instructions } 0.00 3.17 → callq __fentry__ | 0.00 3.17 nop
0.00 7.94 push %rbx 0.00 7.94 push %rbx
7.69 36.51 → callq __page_file_index | 0.00 23.81 pushfq
> 7.69 12.70 pop %rax
> nop
mov %rax,%rbx mov %rax,%rbx
7.69 3.17 → callq *ffffffff82225cd0 | 7.69 3.17 cli
> nop
xor %eax,%eax xor %eax,%eax
mov $0x1,%edx mov $0x1,%edx
80.77 49.21 lock cmpxchg %edx,(%rdi) 80.77 49.21 lock cmpxchg %edx,(%rdi)
test %eax,%eax test %eax,%eax
↓ jne 2b ↓ jne 2b
3.85 0.00 mov %rbx,%rax 3.85 0.00 mov %rbx,%rax
pop %rbx pop %rbx
← retq ← retq
2b: mov %eax,%esi 2b: mov %eax,%esi
→ callq queued_spin_lock_slowpath| → callq *ffffffff820e96b0
mov %rbx,%rax mov %rbx,%rax
pop %rbx pop %rbx
← retq ← retq#
This should be further streamlined by doing both annotations and allowing the TUI to toggle initial/current, and show the patched instructions in a slightly different color.
--- tools/perf/Documentation/perf-annotate.txt | 3 +++ tools/perf/builtin-annotate.c | 2 ++ 2 files changed, 5 insertions(+)
tools/perf/Documentation/perf-annotate.txt +3 -0
@@ -55,6 +55,9 @@ OPTIONS --vmlinux=<file>:: vmlinux pathname. +--ignore-vmlinux:: + Ignore vmlinux files. + -m:: --modules:: Load module symbols. WARNING: use only with -k and LIVE kernel.
tools/perf/builtin-annotate.c +2 -0
@@ -496,6 +496,8 @@ int cmd_annotate(int argc, const char **argv)OPT_BOOLEAN (0 ,"tui" , &annotate.use_tui,"Use the TUI interface" ),OPT_BOOLEAN (0 ,"stdio" , &annotate.use_stdio,"Use the stdio interface" ),OPT_BOOLEAN (0 ,"stdio2" , &annotate.use_stdio2,"Use the stdio interface" ), +OPT_BOOLEAN (0 ,"ignore-vmlinux" , &symbol_conf.ignore_vmlinux, +"don't load vmlinux even if found" ),OPT_STRING ('k' ,"vmlinux" , &symbol_conf.vmlinux_name,"file" ,"vmlinux pathname" ), OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 35/44 perf report: Introduce --ignore-vmlinux command line option
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We've had this in 'perf top' for quite a while, useful if one wishes to force using /proc/kcore to do annotation using the patched kernel instead of the ELF image it started from, aka vmlinux.
--- tools/perf/Documentation/perf-report.txt | 3 +++ tools/perf/builtin-report.c | 2 ++ 2 files changed, 5 insertions(+)
tools/perf/Documentation/perf-report.txt +3 -0
@@ -296,6 +296,9 @@ OPTIONS --vmlinux=<file>:: vmlinux pathname +--ignore-vmlinux:: + Ignore vmlinux files. + --kallsyms=<file>:: kallsyms pathname
tools/perf/builtin-report.c +2 -0
@@ -1018,6 +1018,8 @@ int cmd_report(int argc, const char **argv)OPT_BOOLEAN (0 ,"mmaps" , &report.mmaps_mode,"Display recorded tasks memory maps" ),OPT_STRING ('k' ,"vmlinux" , &symbol_conf.vmlinux_name,"file" ,"vmlinux pathname" ), +OPT_BOOLEAN (0 ,"ignore-vmlinux" , &symbol_conf.ignore_vmlinux, +"don't load vmlinux even if found" ),OPT_STRING (0 ,"kallsyms" , &symbol_conf.kallsyms_name,"file" ,"kallsyms pathname" ), OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 36/44 perf annotate browser: Add 'P' hotkey to dump annotation to file
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Just like we have in the histograms browser used as the main screen for 'perf top --tui' and 'perf report --tui', to print the current annotation to a file with a named composed by the symbol name and the ".annotation" suffix.
Here is one example of pressing 'A' on 'perf top' to live annotate a kernel function and then press 'P' to dump that annotation, the resulting file:
# cat _raw_spin_lock_irqsave.annotation _raw_spin_lock_irqsave() /proc/kcore Event: cycles:ppp
7.14 nop
21.43 push %rbx
7.14 pushfq
pop %rax
nop
mov %rax,%rbx
cli
nop
xor %eax,%eax
mov $0x1,%edx 64.29 lock cmpxchg %edx,(%rdi)
test %eax,%eax
↓ jne 2b
mov %rbx,%rax
pop %rbx
← retq
2b: mov %eax,%esi
→ callq queued_spin_lock_slowpath
mov %rbx,%rax
pop %rbx
← retq
#
--- tools/perf/ui/browsers/annotate.c | 4 ++++ tools/perf/util/annotate.c | 31 +++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 2 ++ 3 files changed, 37 insertions(+)
tools/perf/ui/browsers/annotate.c +4 -0
@@ -661,6 +661,7 @@ static int annotate_browser__run(struct annotate_browser *browser,"t Circulate percent, total period, samples view\n" "/ Search string\n" "k Toggle line numbers\n" +"P Print to [symbol_name].annotation file.\n" "r Run available scripts\n" "? Search string backwards\n");continue ;
@@ -737,6 +738,9 @@ static int annotate_browser__run(struct annotate_browser *browser, }continue ; } +case 'P' : +map_symbol__annotation_dump (ms, evsel); +continue ;case 't' :if (notes->options->show_total_period) { notes->options->show_total_period = false;
tools/perf/util/annotate.c +31 -0
@@ -2037,6 +2037,37 @@ int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)return 0 ; } +int map_symbol__annotation_dump (struct map_symbol *ms,struct perf_evsel *evsel) +{ +const char *ev_name =perf_evsel__name (evsel); +char buf[1024 ]; +char *filename; +int err =-1 ; +FILE *fp; + +if (asprintf (&filename,"%s.annotation" , ms->sym->name) <0 ) +return -1 ; + + fp =fopen (filename,"w" ); +if (fp ==NULL ) + goto out_free_filename; + +if (perf_evsel__is_group_event (evsel)) { +perf_evsel__group_desc (evsel, buf,sizeof (buf)); + ev_name = buf; + } + +fprintf (fp,"%s() %s\nEvent: %s\n\n" , + ms->sym->name, ms->map->dso->long_name, ev_name); +symbol__annotate_fprintf2 (ms->sym, fp); + +fclose (fp); + err =0 ; +out_free_filename: +free (filename); +return err; +} +void symbol__annotate_zero_histogram (struct symbol *sym,int evidx) {struct annotation *notes =symbol__annotation (sym);
tools/perf/util/annotate.h +2 -0
@@ -288,6 +288,8 @@ void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);void symbol__annotate_decay_histogram (struct symbol *sym,int evidx);void annotated_source__purge (struct annotated_source *as); +int map_symbol__annotation_dump (struct map_symbol *ms,struct perf_evsel *evsel); +bool ui__has_annotation (void ); int symbol__tty_annotate(struct symbol *sym, struct map *map,
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 37/44 perf annotate: No need to calculate notes->start twice
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Since we already set notes->start to map__rip_2objdump(map, sym->start) in symbol__annotate2(), no need to calculate that address again in symbol__calc_lines(), just use notes->start.
--- tools/perf/util/annotate.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
tools/perf/util/annotate.c +4 -5
@@ -2230,7 +2230,7 @@ void annotation__update_column_widths(struct annotation *notes) }static void annotation__calc_lines (struct annotation *notes,struct map *map, -struct rb_root *root,u64 start) +struct rb_root *root) {struct annotation_line *al;struct rb_root tmp_root =RB_ROOT ;
@@ -2251,8 +2251,8 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,if (percent_max <=0.5 )continue ; - al->path =get_srcline (map->dso, start + al->offset,NULL , - false, true, start + al->offset); + al->path =get_srcline (map->dso, notes->start + al->offset,NULL , + false, true, notes->start + al->offset);insert_source_line (&tmp_root, al); }
@@ -2263,9 +2263,8 @@ static void symbol__calc_lines(struct symbol *sym, struct map *map, struct rb_root *root) {struct annotation *notes =symbol__annotation (sym); -u64 start =map__rip_2objdump (map, sym->start); -annotation__calc_lines (notes, map, root, start); +annotation__calc_lines (notes, map, root); } int symbol__tty_annotate2(struct symbol *sym, struct map *map,
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 38/44 perf annotate: Pass function descriptor to its instruction parsing routines
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We need that to figure out if jumps have targets in a different function.
E.g. _cpp_lex_token(), in /usr/libexec/gcc/x86_64-redhat-linux/5.3.1/cc1 has a line like this:
jne c469be <cpp_named_operator2name@@Base+0xa72>
--- tools/perf/arch/s390/annotate/instructions.c | 5 +++-- tools/perf/util/annotate.c | 30 ++++++++++++++++------------ tools/perf/util/annotate.h | 2 +- 3 files changed, 21 insertions(+), 16 deletions(-)
tools/perf/arch/s390/annotate/instructions.c +3 -2
@@ -2,9 +2,10 @@#include <linux/compiler.h> static int s390_call__parse (struct arch *arch,struct ins_operands *ops, -struct map *map) +struct map_symbol *ms) {char *endptr, *tok, *name; +struct map *map = ms->map;struct addr_map_symbol target = { .map = map, };
@@ -54,7 +55,7 @@ static struct ins_ops s390_call_ops = {static int s390_mov__parse (struct arch *arch__maybe_unused ,struct ins_operands *ops, -struct map *map__maybe_unused ) +struct map_symbol *ms__maybe_unused ) {char *s =strchr (ops->raw,',' ), *target, *endptr;
tools/perf/util/annotate.c +17 -13
@@ -202,9 +202,10 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)return arch->ins_is_fused (arch, ins1, ins2); } -static int call__parse (struct arch *arch,struct ins_operands *ops,struct map *map) +static int call__parse (struct arch *arch,struct ins_operands *ops,struct map_symbol *ms) {char *endptr, *tok, *name; +struct map *map = ms->map;struct addr_map_symbol target = { .map = map, };
@@ -272,7 +273,7 @@ bool ins__is_call(const struct ins *ins)return ins->ops == &call_ops || ins->ops == &s390_call_ops; } -static int jump__parse (struct arch *arch__maybe_unused ,struct ins_operands *ops,struct map *map__maybe_unused ) +static int jump__parse (struct arch *arch__maybe_unused ,struct ins_operands *ops,struct map_symbol *ms__maybe_unused ) {const char *s =strchr (ops->raw,'+' );const char *c =strchr (ops->raw,',' );
@@ -365,7 +366,7 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)return 0 ; } -static int lock__parse (struct arch *arch,struct ins_operands *ops,struct map *map) +static int lock__parse (struct arch *arch,struct ins_operands *ops,struct map_symbol *ms) { ops->locked.ops =zalloc (sizeof (*ops->locked.ops));if (ops->locked.ops ==NULL )
@@ -380,7 +381,7 @@ static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map * goto out_free_ops;if (ops->locked.ins.ops->parse && - ops->locked.ins.ops->parse (arch, ops->locked.ops, map) <0 ) + ops->locked.ins.ops->parse (arch, ops->locked.ops, ms) <0 ) goto out_free_ops;return 0 ;
@@ -423,7 +424,7 @@ static struct ins_ops lock_ops = { .scnprintf = lock__scnprintf, }; -static int mov__parse (struct arch *arch,struct ins_operands *ops,struct map *map__maybe_unused ) +static int mov__parse (struct arch *arch,struct ins_operands *ops,struct map_symbol *ms__maybe_unused ) {char *s =strchr (ops->raw,',' ), *target, *comment, prev;
@@ -484,7 +485,7 @@ static struct ins_ops mov_ops = { .scnprintf = mov__scnprintf, }; -static int dec__parse (struct arch *arch__maybe_unused ,struct ins_operands *ops,struct map *map__maybe_unused ) +static int dec__parse (struct arch *arch__maybe_unused ,struct ins_operands *ops,struct map_symbol *ms__maybe_unused ) {char *target, *comment, *s, prev;
@@ -923,14 +924,14 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sampreturn symbol__inc_addr_samples (he->ms.sym, he->ms.map, evidx, ip, sample); } -static void disasm_line__init_ins (struct disasm_line *dl,struct arch *arch,struct map *map) +static void disasm_line__init_ins (struct disasm_line *dl,struct arch *arch,struct map_symbol *ms) { dl->ins.ops =ins__find (arch, dl->ins.name);if (!dl->ins.ops)return ; -if (dl->ins.ops->parse && dl->ins.ops->parse (arch, &dl->ops, map) <0 ) +if (dl->ins.ops->parse && dl->ins.ops->parse (arch, &dl->ops, ms) <0 ) dl->ins.ops =NULL ; }
@@ -967,7 +968,7 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)struct annotate_args {size_t privsize;struct arch *arch; -struct map *map; +struct map_symbol ms;struct perf_evsel *evsel;s64 offset;char *line;
@@ -1049,7 +1050,7 @@ static struct disasm_line *disasm_line__new(struct annotate_args *args)if (disasm_line__parse (dl->al.line, &dl->ins.name, &dl->ops.raw) <0 ) goto out_free_line; -disasm_line__init_ins (dl, args->arch, args->map); +disasm_line__init_ins (dl, args->arch, &args->ms); } }
@@ -1307,7 +1308,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,struct annotate_args *args, int *line_nr) { - struct map *map = args->map; + struct map *map = args->ms.map;struct annotation *notes =symbol__annotation (sym);struct disasm_line *dl;char *line =NULL , *parsed_line, *tmp, *tmp2;
@@ -1354,6 +1355,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file, args->offset = offset; args->line = parsed_line; args->line_nr = *line_nr; + args->ms.sym = sym; dl =disasm_line__new (args);free (line);
@@ -1506,7 +1508,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t filstatic int symbol__disassemble (struct symbol *sym,struct annotate_args *args) { -struct map *map = args->map; +struct map *map = args->ms.map;struct dso *dso = map->dso;char *command;FILE *file;
@@ -1705,7 +1707,6 @@ int symbol__annotate(struct symbol *sym, struct map *map, {struct annotate_args args = { .privsize = privsize, - .map = map, .evsel = evsel, };struct perf_env *env =perf_evsel__env (evsel);
@@ -1731,6 +1732,9 @@ int symbol__annotate(struct symbol *sym, struct map *map, } } + args.ms.map = map; + args.ms.sym = sym; +return symbol__disassemble (sym, &args); }
tools/perf/util/annotate.h +1 -1
@@ -46,7 +46,7 @@ struct arch;struct ins_ops {void (*free)(struct ins_operands *ops); -int (*parse)(struct arch *arch,struct ins_operands *ops,struct map *map); +int (*parse)(struct arch *arch,struct ins_operands *ops,struct map_symbol *ms);int (*scnprintf)(struct ins *ins,char *bf,size_t size,struct ins_operands *ops); };
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 39/44 perf annotate: Mark jumps to outher functions with the call arrow
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Things like this in _cpp_lex_token (gcc's cc1 program):
cpp_named_operator2name@@Base+0xa72
Point to a place that is after the cpp_named_operator2name boundaries, i.e. in the ELF symbol table for cc1 cpp_named_operator2name is marked as being 32-bytes long, but it in fact is much larger than that, so we seem to need a symbols__find() routine that looks for >= current->start and < next_symbol->start, possibly just for C++ objects?
For now lets just make some progress by marking jumps to outside the current function as call like.
Actual navigation will come next, with further understanding of how the symbol searching and disassembly should be done.
--- tools/perf/util/annotate.c | 55 +++++++++++++++++++++++++++++++++++++++++++--- tools/perf/util/annotate.h | 1 + 2 files changed, 53 insertions(+), 3 deletions(-)
tools/perf/util/annotate.c +52 -3
@@ -273,11 +273,27 @@ bool ins__is_call(const struct ins *ins)return ins->ops == &call_ops || ins->ops == &s390_call_ops; } -static int jump__parse (struct arch *arch__maybe_unused ,struct ins_operands *ops,struct map_symbol *ms__maybe_unused ) +static int jump__parse (struct arch *arch__maybe_unused ,struct ins_operands *ops,struct map_symbol *ms) { +struct map *map = ms->map; +struct symbol *sym = ms->sym; +struct addr_map_symbol target = { + .map = map, + };const char *s =strchr (ops->raw,'+' );const char *c =strchr (ops->raw,',' ); - +u64 start, end; +/* +* Examples of lines to parse for the _cpp_lex_token@@Base +* function: +* +* 1159e6c: jne 115aa32 <_cpp_lex_token@@Base+0xf92> +* 1159e8b: jne c469be <cpp_named_operator2name@@Base+0xa72> +* +* The first is a jump to an offset inside the same function, +* the second is to another function, i.e. that 0xa72 is an +* offset in the cpp_named_operator2name@@base function. +*/ /* * skip over possible up to 2 operands to get to address, e.g.: * tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
@@ -293,6 +309,35 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op ops->target.addr =strtoull (ops->raw,NULL ,16 ); } + target.addr =map__objdump_2mem (map, ops->target.addr); + start = map->unmap_ip (map, sym->start), + end = map->unmap_ip (map, sym->end); + + ops->target.outside = target.addr < start || target.addr > end; + +/* +* FIXME: things like this in _cpp_lex_token (gcc's cc1 program): + +cpp_named_operator2name@@Base+0xa72 + +* Point to a place that is after the cpp_named_operator2name +* boundaries, i.e. in the ELF symbol table for cc1 +* cpp_named_operator2name is marked as being 32-bytes long, but it in +* fact is much larger than that, so we seem to need a symbols__find() +* routine that looks for >= current->start and < next_symbol->start, +* possibly just for C++ objects? +* +* For now lets just make some progress by marking jumps to outside the +* current function as call like. +* +* Actual navigation will come next, with further understanding of how +* the symbol searching and disassembly should be done. + +if (map_groups__find_ams(&target) == 0 && +map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr) +ops->target.sym = target.sym; +*/ +if (s++ !=NULL ) { ops->target.offset =strtoull (s,NULL ,16 ); ops->target.offset_avail = true;
@@ -2355,11 +2400,15 @@ static void disasm_line__write(struct disasm_line *dl, struct annotation *notes, {if (dl->ins.ops && dl->ins.ops->scnprintf) {if (ins__is_jump (&dl->ins)) { -bool fwd = dl->ops.target.offset > dl->al.offset; +bool fwd; +if (dl->ops.target.outside) + goto call_like; + fwd = dl->ops.target.offset > dl->al.offset;obj__write_graph (obj, fwd ?DARROW_CHAR :UARROW_CHAR );obj__printf (obj," " ); }else if (ins__is_call (&dl->ins)) { +call_like:obj__write_graph (obj,RARROW_CHAR );obj__printf (obj," " ); }else if (ins__is_ret (&dl->ins)) {
tools/perf/util/annotate.h +1 -0
@@ -28,6 +28,7 @@ struct ins_operands {u64 addr;s64 offset;bool offset_avail; +bool outside; } target; union { struct {
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 40/44 perf python: Reference Py_None before returning it
In reply to Arnaldo Carvalho de MeloFrom: Petr Machata <[email protected]>
Python None objects are handled just like all the other objects with respect to their reference counting. Before returning Py_None, its reference count thus needs to be bumped.
--- tools/perf/util/python.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/python.c +3 -1
@@ -1004,8 +1004,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,return PyErr_NoMemory (); evsel =perf_evlist__event2evsel (evlist, event); -if (!evsel) +if (!evsel) { +Py_INCREF (Py_None);return Py_None; + } pevent->evsel = evsel;
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 41/44 perf annotate: Add "_local" to jump/offset validation routines
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Because they all really check if we can access data structures/visual constructs where a "jump" instruction targets code in the same function, i.e. things like:
__pthread_mutex_lock /usr/lib64/libpthread-2.26.so
1.95 │ mov __pthread_force_elision,%ecx
│ ┌──test %ecx,%ecx
0.07 │ ├──je 60
│ │ test $0x300,%esi
│ │↓ jne 60
│ │ or $0x100,%esi
│ │ mov %esi,0x10(%rdi)
│ 42:│ mov %esi,%edx
│ │ lea 0x16(%r8),%rsi
│ │ mov %r8,%rdi
│ │ and $0x80,%edx
│ │ add $0x8,%rsp
│ │→ jmpq __lll_lock_elision
│ │ nop
0.29 │ 60:└─→and $0x80,%esi
0.07 │ mov $0x1,%edi
0.29 │ xor %eax,%eax
2.53 │ lock cmpxchg %edi,(%r8)And not things like that "jmpq __lll_lock_elision", that instead should behave like a "call" instruction and "jump" to the disassembly of "___lll_lock_elision".
--- tools/perf/ui/browsers/annotate.c | 2 +- tools/perf/util/annotate.c | 9 ++++----- tools/perf/util/annotate.h | 14 +++++++++++--- 3 files changed, 16 insertions(+), 9 deletions(-)
tools/perf/ui/browsers/annotate.c +1 -1
@@ -155,7 +155,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)if (strstr (sym->name,"@plt" ))return ; -if (!disasm_line__is_valid_jump (cursor, sym)) +if (!disasm_line__is_valid_local_jump (cursor, sym))return ;/*
tools/perf/util/annotate.c +4 -5
@@ -1409,7 +1409,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,if (dl ==NULL )return -1 ; -if (!disasm_line__has_offset (dl)) { +if (!disasm_line__has_local_offset (dl)) { dl->ops.target.offset = dl->ops.target.addr -map__rip_2objdump (map, sym->start); dl->ops.target.offset_avail = true;
@@ -2176,11 +2176,10 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)return printed; } - -bool disasm_line__is_valid_jump (struct disasm_line *dl,struct symbol *sym) +bool disasm_line__is_valid_local_jump (struct disasm_line *dl,struct symbol *sym) {if (!dl || !dl->ins.ops || !ins__is_jump (&dl->ins) || - !disasm_line__has_offset (dl) || dl->ops.target.offset <0 || + !disasm_line__has_local_offset (dl) || dl->ops.target.offset <0 || dl->ops.target.offset >= (s64 )symbol__size (sym))return false;
@@ -2201,7 +2200,7 @@ void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym) dl =disasm_line (al); -if (!disasm_line__is_valid_jump (dl, sym)) +if (!disasm_line__is_valid_local_jump (dl, sym))continue ; al = notes->offsets[dl->ops.target.offset];
tools/perf/util/annotate.h +11 -3
@@ -117,12 +117,20 @@ static inline struct disasm_line *disasm_line(struct annotation_line *al) return al ? container_of(al, struct disasm_line, al) : NULL; } -static inline bool disasm_line__has_offset (const struct disasm_line *dl) +/* +* Is this offset in the same function as the line it is used? +* asm functions jump to other functions, for instance. +*/ +static inline bool disasm_line__has_local_offset (const struct disasm_line *dl) { -return dl->ops.target.offset_avail; +return dl->ops.target.offset_avail && !dl->ops.target.outside; } -bool disasm_line__is_valid_jump (struct disasm_line *dl,struct symbol *sym); +/* +* Can we draw an arrow from the jump to its target, for instance? I.e. +* is the jump and its target in the same function? +*/ +bool disasm_line__is_valid_local_jump (struct disasm_line *dl,struct symbol *sym);void disasm_line__free (struct disasm_line *dl); struct annotation_line *
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 42/44 perf annotate: Support jumping from one function to another
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
For instance:
entry_SYSCALL_64 /lib/modules/4.16.0-rc5-00086-gdf09348f78dc/build/vmlinux
5.50 │ → callq do_syscall_64
14.56 │ mov 0x58(%rsp),%rcx
7.44 │ mov 0x80(%rsp),%r11
0.32 │ cmp %rcx,%r11
│ → jne swapgs_restore_regs_and_return_to_usermode
0.32 │ shl $0x10,%rcx
0.32 │ sar $0x10,%rcx
3.24 │ cmp %rcx,%r11
│ → jne swapgs_restore_regs_and_return_to_usermode
2.27 │ cmpq $0x33,0x88(%rsp)
1.29 │ → jne swapgs_restore_regs_and_return_to_usermode
│ mov 0x30(%rsp),%r11
8.74 │ cmp %r11,0x90(%rsp)
│ → jne swapgs_restore_regs_and_return_to_usermode
0.32 │ test $0x10100,%r11
│ → jne swapgs_restore_regs_and_return_to_usermode
0.32 │ cmpq $0x2b,0xa0(%rsp)
0.65 │ → jne swapgs_restore_regs_and_return_to_usermodeIt'll behave just like a "call" instruction, i.e. press enter or right arrow over one such line and the browser will navigate to the annotated disassembly of that function, which when exited, via left arrow or esc, will come back to the calling function.
Now to support jump to an offset on a different function...
--- tools/perf/ui/browsers/annotate.c | 23 ++++++++++++++++++----- tools/perf/util/annotate.c | 6 ++++-- 2 files changed, 22 insertions(+), 7 deletions(-)
tools/perf/ui/browsers/annotate.c +18 -5
@@ -384,6 +384,15 @@ static int sym_title(struct symbol *sym, struct map *map, char *title,return snprintf (title, sz,"%s %s" , sym->name, map->dso->long_name); } +/* +* This can be called from external jumps, i.e. jumps from one functon +* to another, like from the kernel's entry_SYSCALL_64 function to the +* swapgs_restore_regs_and_return_to_usermode() function. +* +* So all we check here is that dl->ops.target.sym is set, if it is, just +* go to that function and when exiting from its disassembly, come back +* to the calling function. +*/ static bool annotate_browser__callq (struct annotate_browser *browser,struct perf_evsel *evsel,struct hist_browser_timer *hbt)
@@ -393,9 +402,6 @@ static bool annotate_browser__callq(struct annotate_browser *browser,struct annotation *notes;char title[SYM_TITLE_MAX_SIZE ]; -if (!ins__is_call (&dl->ins)) -return false; -if (!dl->ops.target.sym) {ui_helpline__puts ("The called function was not found." );return true;
@@ -436,7 +442,9 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browsreturn NULL ; } -static bool annotate_browser__jump (struct annotate_browser *browser) +static bool annotate_browser__jump (struct annotate_browser *browser, +struct perf_evsel *evsel, +struct hist_browser_timer *hbt) {struct disasm_line *dl =disasm_line (browser->selection);u64 offset;
@@ -445,6 +453,11 @@ static bool annotate_browser__jump(struct annotate_browser *browser)if (!ins__is_jump (&dl->ins))return false; +if (dl->ops.target.outside) { +annotate_browser__callq (browser, evsel, hbt); +return true; + } + offset = dl->ops.target.offset; dl =annotate_browser__find_offset (browser, offset, &idx);if (dl ==NULL ) {
@@ -731,7 +744,7 @@ static int annotate_browser__run(struct annotate_browser *browser, goto show_sup_ins; else if (ins__is_ret(&dl->ins)) goto out; - else if (!(annotate_browser__jump(browser) || + else if (!(annotate_browser__jump(browser, evsel, hbt) || annotate_browser__callq(browser, evsel, hbt))) { show_sup_ins:ui_helpline__puts ("Actions are only available for function call/return & jump/branch instructions." );
tools/perf/util/annotate.c +4 -2
@@ -332,11 +332,10 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op* * Actual navigation will come next, with further understanding of how * the symbol searching and disassembly should be done. - +*/ if (map_groups__find_ams (&target) ==0 &&map__rip_2objdump (target.map, map->map_ip (target.map, target.addr)) == ops->target.addr) ops->target.sym = target.sym; -*/ if (s++ !=NULL ) { ops->target.offset =strtoull (s,NULL ,16 );
@@ -356,6 +355,9 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size,if (!ops->target.addr || ops->target.offset <0 )return ins__raw_scnprintf (ins, bf, size, ops); +if (ops->target.outside && ops->target.sym !=NULL ) +return scnprintf (bf, size,"%-6s %s" , ins->name, ops->target.sym->name); +if (c !=NULL ) {const char *c2 =strchr (c +1 ,',' );
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 43/44 perf annotate: Defer searching for comma in raw line till it is needed
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
That strchr() in jump__scnprintf() needs to be nuked somehow, as it, IIRC is already done in jump__parse() and if needed at scnprintf() time, should be stashed in the struct filled in parse() time.
For now jus defer it to just before where it is used.
--- tools/perf/util/annotate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/annotate.c +2 -1
@@ -350,7 +350,7 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *opstatic int jump__scnprintf (struct ins *ins,char *bf,size_t size,struct ins_operands *ops) { -const char *c =strchr (ops->raw,',' ); +const char *c;if (!ops->target.addr || ops->target.offset <0 )return ins__raw_scnprintf (ins, bf, size, ops);
@@ -358,6 +358,7 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size,if (ops->target.outside && ops->target.sym !=NULL )return scnprintf (bf, size,"%-6s %s" , ins->name, ops->target.sym->name); + c =strchr (ops->raw,',' );if (c !=NULL ) {const char *c2 =strchr (c +1 ,',' );
Signature · 1 line
2.14.3
Arnaldo Carvalho de Melo
maintainerPATCH 44/44 perf annotate: Use absolute addresses to calculate jump target offsets
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
These types of jumps were confusing the annotate browser:
entry_SYSCALL_64 /lib/modules/4.16.0-rc5-00086-gdf09348f78dc/build/vmlinux
entry_SYSCALL_64 /lib/modules/4.16.0-rc5-00086-gdf09348f78dc/build/vmlinux
Percent│ffffffff81a00020: swapgs
<SNIP>
│ffffffff81a00128: ↓ jae ffffffff81a00139 <syscall_return_via_sysret+0x53>
<SNIP>
│ffffffff81a00155: → jmpq *0x825d2d(%rip) # ffffffff82225e88 <pv_cpu_ops+0xe8>I.e. the syscall_return_via_sysret function is actually "inside" the entry_SYSCALL_64 function, and the offsets in jumps like these (+0x53) are relative to syscall_return_via_sysret, not to syscall_return_via_sysret.
Or this may be some artifact in how the assembler marks the start and end of a function and how this ends up in the ELF symtab for vmlinux, i.e. syscall_return_via_sysret() isn't "inside" entry_SYSCALL_64, but just right after it.
From readelf -sw vmlinux:
80267: ffffffff81a00020 315 NOTYPE GLOBAL DEFAULT 1 entry_SYSCALL_64 316: ffffffff81a000e6 0 NOTYPE LOCAL DEFAULT 1 syscall_return_via_sysret
0xffffffff81a00020 + 315 > 0xffffffff81a000e6
So instead of looking for offsets after that last '+' sign, calculate offsets for jump target addresses that are inside the function being disassembled from the absolute address, 0xffffffff81a00139 in this case, subtracting from it the objdump address for the start of the function being disassembled, entry_SYSCALL_64() in this case.
So, before this patch:
entry_SYSCALL_64 /lib/modules/4.16.0-rc5-00086-gdf09348f78dc/build/vmlinux
Percent│ pop %r10
│ pop %r9
│ pop %r8
│ pop %rax
│ pop %rsi
│ pop %rdx
│ pop %rsi
│ mov %rsp,%rdi
│ mov %gs:0x5004,%rsp
│ pushq 0x28(%rdi)
│ pushq (%rdi)
│ push %rax
│ ↑ jmp 6c
│ mov %cr3,%rdi
│ ↑ jmp 62
│ mov %rdi,%rax
│ and $0x7ff,%rdi
│ bt %rdi,%gs:0x2219a
│ ↑ jae 53
│ btr %rdi,%gs:0x2219a
│ mov %rax,%rdi
│ ↑ jmp 5bAfter:
entry_SYSCALL_64 /lib/modules/4.16.0-rc5-00086-gdf09348f78dc/build/vmlinux
0.65 │ → jne swapgs_restore_regs_and_return_to_usermode
│ pop %r10
│ pop %r9
│ pop %r8
│ pop %rax
│ pop %rsi
│ pop %rdx
│ pop %rsi
│ mov %rsp,%rdi
│ mov %gs:0x5004,%rsp
│ pushq 0x28(%rdi)
│ pushq (%rdi)
│ push %rax
│ ↓ jmp 132
│ mov %cr3,%rdi
│ ┌──jmp 128
│ │ mov %rdi,%rax
│ │ and $0x7ff,%rdi
│ │ bt %rdi,%gs:0x2219a
│ │↓ jae 119
│ │ btr %rdi,%gs:0x2219a
│ │ mov %rax,%rdi
│ │↓ jmp 121
│119:│ mov %rax,%rdi
│ │ bts $0x3f,%rdi
│121:│ or $0x800,%rdi
│128:└─→or $0x1000,%rdi
│ mov %rdi,%cr3
│132: pop %rax
│ pop %rdi
│ pop %rsp
│ → jmpq *0x825d2d(%rip) # ffffffff82225e88 <pv_cpu_ops+0xe8>With those at least navigating to the right destination, an improvement for these cases seems to be to be to somehow mark those inner functions, which in this case could be:
entry_SYSCALL_64 /lib/modules/4.16.0-rc5-00086-gdf09348f78dc/build/vmlinux
│syscall_return_via_sysret:
│ pop %r15
│ pop %r14
│ pop %r13
│ pop %r12
│ pop %rbp
│ pop %rbx
│ pop %rsi
│ pop %r10
│ pop %r9
│ pop %r8
│ pop %rax
│ pop %rsi
│ pop %rdx
│ pop %rsi
│ mov %rsp,%rdi
│ mov %gs:0x5004,%rsp
│ pushq 0x28(%rdi)
│ pushq (%rdi)
│ push %rax
│ ↓ jmp 132
│ mov %cr3,%rdi
│ ┌──jmp 128
│ │ mov %rdi,%rax
│ │ and $0x7ff,%rdi
│ │ bt %rdi,%gs:0x2219a
│ │↓ jae 119
│ │ btr %rdi,%gs:0x2219a
│ │ mov %rax,%rdi
│ │↓ jmp 121
│119:│ mov %rax,%rdi
│ │ bts $0x3f,%rdi
│121:│ or $0x800,%rdi
│128:└─→or $0x1000,%rdi
│ mov %rdi,%cr3
│132: pop %rax
│ pop %rdi
│ pop %rsp
│ → jmpq *0x825d2d(%rip) # ffffffff82225e88 <pv_cpu_ops+0xe8>This all gets much better viewed if one uses 'perf report --ignore-vmlinux' forcing the usage of /proc/kcore + /proc/kallsyms, when the above actually gets down to:
# perf report --ignore-vmlinux ## do '/64', will show the function names containing '64', ## navigate to /entry_SYSCALL_64_after_hwframe.annotation, ## press 'A' to annotate, then 'P' to print that annotation ## to a file ## From another xterm (or see on screen, this 'P' thing is for ## getting rid of those right side scroll bars/spaces): # cat /entry_SYSCALL_64_after_hwframe.annotation entry_SYSCALL_64_after_hwframe() /proc/kcore Event: cycles:ppp
Percent
Disassembly of section load0:
ffffffff9aa00044 <load0>:
11.97 push %rax
4.85 push %rdi
push %rsi
2.59 push %rdx
2.27 push %rcx
0.32 pushq $0xffffffffffffffda
1.29 push %r8
xor %r8d,%r8d
1.62 push %r9
0.65 xor %r9d,%r9d
1.62 push %r10
xor %r10d,%r10d
5.50 push %r11
xor %r11d,%r11d
3.56 push %rbx
xor %ebx,%ebx
4.21 push %rbp
xor %ebp,%ebp
2.59 push %r12
0.97 xor %r12d,%r12d
3.24 push %r13
xor %r13d,%r13d
2.27 push %r14
xor %r14d,%r14d
4.21 push %r15
xor %r15d,%r15d
0.97 mov %rsp,%rdi
5.50 → callq do_syscall_64
14.56 mov 0x58(%rsp),%rcx
7.44 mov 0x80(%rsp),%r11
0.32 cmp %rcx,%r11
→ jne swapgs_restore_regs_and_return_to_usermode
0.32 shl $0x10,%rcx
0.32 sar $0x10,%rcx
3.24 cmp %rcx,%r11
→ jne swapgs_restore_regs_and_return_to_usermode
2.27 cmpq $0x33,0x88(%rsp)
1.29 → jne swapgs_restore_regs_and_return_to_usermode
mov 0x30(%rsp),%r11
8.74 cmp %r11,0x90(%rsp)
→ jne swapgs_restore_regs_and_return_to_usermode
0.32 test $0x10100,%r11
→ jne swapgs_restore_regs_and_return_to_usermode
0.32 cmpq $0x2b,0xa0(%rsp)
0.65 → jne swapgs_restore_regs_and_return_to_usermodeI.e. using kallsyms makes the function start/end be done differently than using what is in the vmlinux ELF symtab and actually the hits goes to entry_SYSCALL_64_after_hwframe, which is a GLOBAL() after the start of entry_SYSCALL_64:
ENTRY(entry_SYSCALL_64)
UNWIND_HINT_EMPTY
<SNIP>
pushq $__USER_CS /* pt_regs->cs */
pushq %rcx /* pt_regs->ip */
GLOBAL(entry_SYSCALL_64_after_hwframe)
pushq %rax /* pt_regs->orig_ax */
PUSH_AND_CLEAR_REGS rax=$-ENOSYSAnd it goes and ends at:
cmpq $__USER_DS, SS(%rsp) /* SS must match SYSRET */
jne swapgs_restore_regs_and_return_to_usermode
/*
* We win! This label is here just for ease of understanding
* perf profiles. Nothing jumps here.
*/
syscall_return_via_sysret:
/* rcx and r11 are already restored (see code above) */
UNWIND_HINT_EMPTY
POP_REGS pop_rdi=0 skip_r11rcx=1So perhaps some people should really just play with '--ignore-vmlinux' to force /proc/kcore + kallsyms.
One idea is to do both, i.e. have a vmlinux annotation and a kcore+kallsyms one, when possible, and even show the patched location, etc.
--- tools/perf/util/annotate.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
tools/perf/util/annotate.c +2 -3
@@ -280,7 +280,6 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *opstruct addr_map_symbol target = { .map = map, }; -const char *s =strchr (ops->raw,'+' );const char *c =strchr (ops->raw,',' );u64 start, end;/*
@@ -337,8 +336,8 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr) ops->target.sym = target.sym; -if (s++ !=NULL ) { - ops->target.offset =strtoull (s,NULL ,16 ); +if (!ops->target.outside) { + ops->target.offset = target.addr - start; ops->target.offset_avail = true; }else { ops->target.offset_avail = false;
Signature · 1 line
2.14.3
Quoted 116 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Mostly a 'perf annotate' refactoring to allow reusing the TUI
formatting routines in a --stdio2 mode for 'perf annotate' that at some point should replace --stdio, leaving that old code deprecated for a while, then ditching it.That will take a while yet because there is some stuff in the
--stdio code that needs to be done in the annotation UI agnostic core to then get used in --tui and --stdio2.There is also some improvements for issues Linus reported in the
TUI annotation code for ASM functions.Please consider pulling,
- Arnaldo
Test results at the end of this message, as usual.
The following changes since commit
ecd380b8dead1bad67e3af87e2ddfe826c3da79d:Merge tag 'perf-core-for-mingo-4.17-20180319' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxinto perf/core (2018-03-19 20:37:48 +0100)are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingo-4.17-20180323for you to fetch changes up to
980b68ec0694f250e967cb18c5705ef5de10fdd5:perf annotate: Use absolute addresses to calculate jump target offsets (2018-03-23 16:46:53 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:- Move non-TUI specific annotation routines out of the TUI browser so that it can be used in other UIs, and to demonstrate that introduce a 'perf annotate --stdio2' option that will apply those formatting routines to provide a non-interactive annotation mode (Arnaldo Carvalho de Melo)
- Add 'P' hotkey to the annotation TUI, so dump the current annotated symbol to a file, easing report thru e-mail, by getting rid of the spaces + right hand side scrollbar chars (Arnaldo Carvalho de Melo)
- Support --ignore-vmlinux to 'perf report' and 'perf annotate', that
was already present in 'perf top', to use/proc/{kcore,kallsyms}, allowing to see what is in fact running (patched stuff, alternatives, ftrace, etc), not the initial state of the kernel (vmlinux) (Arnaldo Carvalho de Melo)- Support 'jump' instructions to a different function, treating them as 'call' instructions (Arnaldo Carvalho de Melo)
- Fix some jump artifacts when using vmlinux + ASM functions, where the ELF symtab for instance, for
entry_SYSCALL_64includes that and what comes after the 'syscall_return_via_sysret' label, but the objdump -dS prints the jump targets + offsets using thesyscall_return_via_sysretaddress, which was confusing 'perf annotate'. See the cset comments for further info (Arnaldo Carvalho de Melo)- Report error from
dwfl_attach_state()in the unwind code (Martin Vuille)- Reference
Py_Nonebefore returning it in the python extension (Petr Machata)Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Arnaldo Carvalho de Melo (42):
perf annotate: Moveannotation_optionsout of the TUI browser perf annotate: Move cycles/IPC formatting width constants outside TUI perf annotate tui: Useannotate_browser__cycles_width()mroe perf annotate tui: Movehave_cyclesto struct annotation
perf annotate: Moveannotation_linearray from TUI to generic code perf annotate: Movecompute_ipc()to annotation library
perf annotate: Movenr_eventsfromannotate_browserto annotation struct perf annotate: Stop using a global config struct
perf annotate: Movepcnt_with()to the annotation library
perf annotate tui: Addbrowser__annotation()helper
perf annotate: Movemax_jump_sourcesto struct annotation
perf annotate: Movejumps_percent_colortoui_browser
perf annotate: Movenr_jumpsto struct annotation
perf annotate: Movemark_jump_targetsfrom the TUI to the annotation library perf annotate: Nuke structbrowser_line
perf annotate: Move 'start' to struct annotation
perf annotate: Move nr_{asm_}entries to struct annotation
perf annotate: Introduceset_offsets()method out of TUI code perf annotate: Move the column widths from the TUI to generic lib perf annotate: Moveupdate_column_widths()to the generic lib perf annotate: Introduceinit_column_widths()method out of TUI code perf annotate: Introducesymbol__annotate2method
perf annotate: Introduceannotation_line__max_percent()
perf ui browser: Addvprintf()method
perf annotate: Introduceannotation_line__print_start()out of TUI code perf annotate: Finish the generalization ofannotate_browser__write()perf annotate: Use a ops table forannotation_line__write()perf annotate: Introduceannotation_line__filter()
perf annotate: Introduce the --stdio2 output mode
perf annotate: Move the default annotate options to the library perf annotate: Use the default annotation options for --stdio2 perf annotate: Add function header to --stdio2
perf annotate: Introduce --ignore-vmlinux command line option perf report: Introduce --ignore-vmlinux command line option perf annotate browser: Add 'P' hotkey to dump annotation to file perf annotate: No need to calculatenotes->starttwice
perf annotate: Pass function descriptor to its instruction parsing routines perf annotate: Mark jumps to outher functions with the call arrow perf annotate: Add "_local" to jump/offset validation routines perf annotate: Support jumping from one function to another perf annotate: Defer searching for comma in raw line till it is needed perf annotate: Use absolute addresses to calculate jump target offsetsMartin Vuille (1):
perf unwind: Report error fromdwfl_attach_statePetr Machata (1):
perf python: ReferencePy_Nonebefore returning it
Quoted 14 lines
tools/perf/Documentation/perf-annotate.txt | 5 + tools/perf/Documentation/perf-report.txt | 3 + tools/perf/arch/s390/annotate/instructions.c | 5 +- tools/perf/builtin-annotate.c | 27 +- tools/perf/builtin-report.c | 3 + tools/perf/builtin-top.c | 2 + tools/perf/ui/browser.c | 9 +- tools/perf/ui/browser.h | 3 +- tools/perf/ui/browsers/annotate.c | 686 ++++++--------------------- tools/perf/util/annotate.c | 679 +++++++++++++++++++++++++- tools/perf/util/annotate.h | 102 +++- tools/perf/util/python.c | 4 +- tools/perf/util/unwind-libdw.c | 3 +- 13 files changed, 944 insertions(+), 587 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo