Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull more perf updates from Thomas Gleixner:
"A rather large set of perf updates:

Kernel:

- Fix various initialization issues

- Prevent creating [ku]probes for not CAP_SYS_ADMIN users

Tooling:

- Show only failing syscalls with 'perf trace --failure' (Arnaldo
Carvalho de Melo)

e.g: See what 'openat' syscalls are failing:

# perf trace --failure -e openat
762.323 ( 0.007 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video2) = -1 ENOENT No such file or directory
<SNIP N /dev/videoN open attempts... sigh, where is that improvised camera lid?!? >
790.228 ( 0.008 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video63) = -1 ENOENT No such file or directory
^C#

- Show information about the event (freq, nr_samples, total
period/nr_events) in the annotate --tui and --stdio2 'perf
annotate' output, similar to the first line in the 'perf report
--tui', but just for the samples for a the annotated symbol
(Arnaldo Carvalho de Melo)

- Introduce 'perf version --build-options' to show what features were
linked, aliased as well as a shorter 'perf -vv' (Jin Yao)

- Add a "dso_size" sort order (Kim Phillips)

- Remove redundant ')' in the tracepoint output in 'perf trace'
(Changbin Du)

- Synchronize x86's cpufeatures.h, no effect on toolss (Arnaldo
Carvalho de Melo)

- Show group details on the title line in the annotate browser and
'perf annotate --stdio2' output, so that the per-event columns can
have headers (Arnaldo Carvalho de Melo)

- Fixup vertical line separating metrics from instructions and
cleaning unused lines at the bottom, both in the annotate TUI
browser (Arnaldo Carvalho de Melo)

- Remove duplicated 'samples' in lost samples warning in
'perf report' (Arnaldo Carvalho de Melo)

- Synchronize i915_drm.h, silencing the perf build process,
automagically adding support for the new DRM_I915_QUERY ioctl
(Arnaldo Carvalho de Melo)

- Make auxtrace_queues__add_buffer() allocate struct buffer, from a
patchkit already applied (Adrian Hunter)

- Fix the --stdio2/TUI annotate output to include group details, be
it for a recorded '{a,b,f}' explicit event group or when forcing
group display using 'perf report --group' for a set of events not
recorded as a group (Arnaldo Carvalho de Melo)

- Fix display artifacts in the ui browser (base class for the
annotate and main report/top TUI browser) related to the extra
title lines work (Arnaldo Carvalho de Melo)

- perf auxtrace refactorings, leftovers from a previously partially
processed patchset (Adrian Hunter)

- Fix the builtin clang build (Sandipan Das, Arnaldo Carvalho de
Melo)

- Synchronize i915_drm.h, silencing a perf build warning and in the
process automagically adding support for a new ioctl command
(Arnaldo Carvalho de Melo)

- Fix a strncpy issue in uprobe tracing"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (36 commits)
perf/core: Need CAP_SYS_ADMIN to create k/uprobe with perf_event_open()
tracing/uprobe_event: Fix strncpy corner case
perf/core: Fix perf_uprobe_init()
perf/core: Fix perf_kprobe_init()
perf/core: Fix use-after-free in uprobe_perf_close()
perf tests clang: Fix function name for clang IR test
perf clang: Add support for recent clang versions
perf tools: Fix perf builds with clang support
perf tools: No need to include namespaces.h in util.h
perf hists browser: Remove leftover from row returned from refresh
perf hists browser: Show extra_title_lines in the 'D' debug hotkey
perf auxtrace: Make auxtrace_queues__add_buffer() do CPU filtering
tools headers uapi: Synchronize i915_drm.h
perf report: Remove duplicated 'samples' in lost samples warning
perf ui browser: Fixup cleaning unused lines at the bottom
perf annotate browser: Fixup vertical line separating metrics from instructions
perf annotate: Show group details on the title line
perf auxtrace: Make auxtrace_queues__add_buffer() allocate struct buffer
perf/x86/intel: Move regs->flags EXACT bit init
perf trace: Remove redundant ')'
...

+653 -211
+24 -10
arch/x86/events/intel/ds.c
··· 1153 1153 if (pebs == NULL) 1154 1154 return; 1155 1155 1156 - regs->flags &= ~PERF_EFLAGS_EXACT; 1157 1156 sample_type = event->attr.sample_type; 1158 1157 dsrc = sample_type & PERF_SAMPLE_DATA_SRC; 1159 1158 ··· 1196 1197 * and PMI. 1197 1198 */ 1198 1199 *regs = *iregs; 1199 - regs->flags = pebs->flags; 1200 + 1201 + /* 1202 + * Initialize regs_>flags from PEBS, 1203 + * Clear exact bit (which uses x86 EFLAGS Reserved bit 3), 1204 + * i.e., do not rely on it being zero: 1205 + */ 1206 + regs->flags = pebs->flags & ~PERF_EFLAGS_EXACT; 1200 1207 1201 1208 if (sample_type & PERF_SAMPLE_REGS_INTR) { 1202 1209 regs->ax = pebs->ax; ··· 1222 1217 regs->sp = pebs->sp; 1223 1218 } 1224 1219 1225 - /* 1226 - * Preserve PERF_EFLAGS_VM from set_linear_ip(). 1227 - */ 1228 - regs->flags = pebs->flags | (regs->flags & PERF_EFLAGS_VM); 1229 1220 #ifndef CONFIG_X86_32 1230 1221 regs->r8 = pebs->r8; 1231 1222 regs->r9 = pebs->r9; ··· 1235 1234 } 1236 1235 1237 1236 if (event->attr.precise_ip > 1) { 1238 - /* Haswell and later have the eventing IP, so use it: */ 1237 + /* 1238 + * Haswell and later processors have an 'eventing IP' 1239 + * (real IP) which fixes the off-by-1 skid in hardware. 1240 + * Use it when precise_ip >= 2 : 1241 + */ 1239 1242 if (x86_pmu.intel_cap.pebs_format >= 2) { 1240 1243 set_linear_ip(regs, pebs->real_ip); 1241 1244 regs->flags |= PERF_EFLAGS_EXACT; 1242 1245 } else { 1243 - /* Otherwise use PEBS off-by-1 IP: */ 1246 + /* Otherwise, use PEBS off-by-1 IP: */ 1244 1247 set_linear_ip(regs, pebs->ip); 1245 1248 1246 - /* ... and try to fix it up using the LBR entries: */ 1249 + /* 1250 + * With precise_ip >= 2, try to fix up the off-by-1 IP 1251 + * using the LBR. If successful, the fixup function 1252 + * corrects regs->ip and calls set_linear_ip() on regs: 1253 + */ 1247 1254 if (intel_pmu_pebs_fixup_ip(regs)) 1248 1255 regs->flags |= PERF_EFLAGS_EXACT; 1249 1256 } 1250 - } else 1257 + } else { 1258 + /* 1259 + * When precise_ip == 1, return the PEBS off-by-1 IP, 1260 + * no fixup attempted: 1261 + */ 1251 1262 set_linear_ip(regs, pebs->ip); 1263 + } 1252 1264 1253 1265 1254 1266 if ((sample_type & (PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR)) &&
+14
kernel/events/core.c
··· 4447 4447 if (event->ctx) 4448 4448 put_ctx(event->ctx); 4449 4449 4450 + if (event->hw.target) 4451 + put_task_struct(event->hw.target); 4452 + 4450 4453 exclusive_event_destroy(event); 4451 4454 module_put(event->pmu->module); 4452 4455 ··· 8400 8397 8401 8398 if (event->attr.type != perf_kprobe.type) 8402 8399 return -ENOENT; 8400 + 8401 + if (!capable(CAP_SYS_ADMIN)) 8402 + return -EACCES; 8403 + 8403 8404 /* 8404 8405 * no branch sampling for probe events 8405 8406 */ ··· 8441 8434 8442 8435 if (event->attr.type != perf_uprobe.type) 8443 8436 return -ENOENT; 8437 + 8438 + if (!capable(CAP_SYS_ADMIN)) 8439 + return -EACCES; 8440 + 8444 8441 /* 8445 8442 * no branch sampling for probe events 8446 8443 */ ··· 9966 9955 * and we cannot use the ctx information because we need the 9967 9956 * pmu before we get a ctx. 9968 9957 */ 9958 + get_task_struct(task); 9969 9959 event->hw.target = task; 9970 9960 } 9971 9961 ··· 10082 10070 perf_detach_cgroup(event); 10083 10071 if (event->ns) 10084 10072 put_pid_ns(event->ns); 10073 + if (event->hw.target) 10074 + put_task_struct(event->hw.target); 10085 10075 kfree(event); 10086 10076 10087 10077 return ERR_PTR(err);
+4
kernel/trace/trace_event_perf.c
··· 252 252 ret = strncpy_from_user( 253 253 func, u64_to_user_ptr(p_event->attr.kprobe_func), 254 254 KSYM_NAME_LEN); 255 + if (ret == KSYM_NAME_LEN) 256 + ret = -E2BIG; 255 257 if (ret < 0) 256 258 goto out; 257 259 ··· 302 300 return -ENOMEM; 303 301 ret = strncpy_from_user( 304 302 path, u64_to_user_ptr(p_event->attr.uprobe_path), PATH_MAX); 303 + if (ret == PATH_MAX) 304 + return -E2BIG; 305 305 if (ret < 0) 306 306 goto out; 307 307 if (path[0] == '\0') {
+2
kernel/trace/trace_uprobe.c
··· 151 151 return; 152 152 153 153 ret = strncpy_from_user(dst, src, maxlen); 154 + if (ret == maxlen) 155 + dst[--ret] = '\0'; 154 156 155 157 if (ret < 0) { /* Failed to fetch string */ 156 158 ((u8 *)get_rloc_data(dest))[0] = '\0';
+2
tools/arch/x86/include/asm/cpufeatures.h
··· 316 316 #define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */ 317 317 #define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */ 318 318 #define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */ 319 + #define X86_FEATURE_TME (16*32+13) /* Intel Total Memory Encryption */ 319 320 #define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ 320 321 #define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */ 321 322 #define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */ ··· 329 328 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ 330 329 #define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ 331 330 #define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ 331 + #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ 332 332 #define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ 333 333 #define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ 334 334 #define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
+34
tools/include/tools/config.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _TOOLS_CONFIG_H 3 + #define _TOOLS_CONFIG_H 4 + 5 + /* Subset of include/linux/kconfig.h */ 6 + 7 + #define __ARG_PLACEHOLDER_1 0, 8 + #define __take_second_arg(__ignored, val, ...) val 9 + 10 + /* 11 + * Helper macros to use CONFIG_ options in C/CPP expressions. Note that 12 + * these only work with boolean and tristate options. 13 + */ 14 + 15 + /* 16 + * Getting something that works in C and CPP for an arg that may or may 17 + * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1" 18 + * we match on the placeholder define, insert the "0," for arg1 and generate 19 + * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one). 20 + * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when 21 + * the last step cherry picks the 2nd arg, we get a zero. 22 + */ 23 + #define __is_defined(x) ___is_defined(x) 24 + #define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val) 25 + #define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0) 26 + 27 + /* 28 + * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 29 + * otherwise. For boolean options, this is equivalent to 30 + * IS_ENABLED(CONFIG_FOO). 31 + */ 32 + #define IS_BUILTIN(option) __is_defined(option) 33 + 34 + #endif /* _TOOLS_CONFIG_H */
+108 -4
tools/include/uapi/drm/i915_drm.h
··· 318 318 #define DRM_I915_PERF_OPEN 0x36 319 319 #define DRM_I915_PERF_ADD_CONFIG 0x37 320 320 #define DRM_I915_PERF_REMOVE_CONFIG 0x38 321 + #define DRM_I915_QUERY 0x39 321 322 322 323 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) 323 324 #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) ··· 376 375 #define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) 377 376 #define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) 378 377 #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) 378 + #define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) 379 379 380 380 /* Allow drivers to submit batchbuffers directly to hardware, relying 381 381 * on the security mechanisms provided by hardware. ··· 1360 1358 * active on a given plane. 1361 1359 */ 1362 1360 1363 - #define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */ 1361 + #define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set 1362 + * flags==0 to disable colorkeying. 1363 + */ 1364 1364 #define I915_SET_COLORKEY_DESTINATION (1<<1) 1365 1365 #define I915_SET_COLORKEY_SOURCE (1<<2) 1366 1366 struct drm_intel_sprite_colorkey { ··· 1608 1604 __u32 n_flex_regs; 1609 1605 1610 1606 /* 1611 - * These fields are pointers to tuples of u32 values (register 1612 - * address, value). For example the expected length of the buffer 1613 - * pointed by mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). 1607 + * These fields are pointers to tuples of u32 values (register address, 1608 + * value). For example the expected length of the buffer pointed by 1609 + * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). 1614 1610 */ 1615 1611 __u64 mux_regs_ptr; 1616 1612 __u64 boolean_regs_ptr; 1617 1613 __u64 flex_regs_ptr; 1614 + }; 1615 + 1616 + struct drm_i915_query_item { 1617 + __u64 query_id; 1618 + #define DRM_I915_QUERY_TOPOLOGY_INFO 1 1619 + 1620 + /* 1621 + * When set to zero by userspace, this is filled with the size of the 1622 + * data to be written at the data_ptr pointer. The kernel sets this 1623 + * value to a negative value to signal an error on a particular query 1624 + * item. 1625 + */ 1626 + __s32 length; 1627 + 1628 + /* 1629 + * Unused for now. Must be cleared to zero. 1630 + */ 1631 + __u32 flags; 1632 + 1633 + /* 1634 + * Data will be written at the location pointed by data_ptr when the 1635 + * value of length matches the length of the data to be written by the 1636 + * kernel. 1637 + */ 1638 + __u64 data_ptr; 1639 + }; 1640 + 1641 + struct drm_i915_query { 1642 + __u32 num_items; 1643 + 1644 + /* 1645 + * Unused for now. Must be cleared to zero. 1646 + */ 1647 + __u32 flags; 1648 + 1649 + /* 1650 + * This points to an array of num_items drm_i915_query_item structures. 1651 + */ 1652 + __u64 items_ptr; 1653 + }; 1654 + 1655 + /* 1656 + * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO : 1657 + * 1658 + * data: contains the 3 pieces of information : 1659 + * 1660 + * - the slice mask with one bit per slice telling whether a slice is 1661 + * available. The availability of slice X can be queried with the following 1662 + * formula : 1663 + * 1664 + * (data[X / 8] >> (X % 8)) & 1 1665 + * 1666 + * - the subslice mask for each slice with one bit per subslice telling 1667 + * whether a subslice is available. The availability of subslice Y in slice 1668 + * X can be queried with the following formula : 1669 + * 1670 + * (data[subslice_offset + 1671 + * X * subslice_stride + 1672 + * Y / 8] >> (Y % 8)) & 1 1673 + * 1674 + * - the EU mask for each subslice in each slice with one bit per EU telling 1675 + * whether an EU is available. The availability of EU Z in subslice Y in 1676 + * slice X can be queried with the following formula : 1677 + * 1678 + * (data[eu_offset + 1679 + * (X * max_subslices + Y) * eu_stride + 1680 + * Z / 8] >> (Z % 8)) & 1 1681 + */ 1682 + struct drm_i915_query_topology_info { 1683 + /* 1684 + * Unused for now. Must be cleared to zero. 1685 + */ 1686 + __u16 flags; 1687 + 1688 + __u16 max_slices; 1689 + __u16 max_subslices; 1690 + __u16 max_eus_per_subslice; 1691 + 1692 + /* 1693 + * Offset in data[] at which the subslice masks are stored. 1694 + */ 1695 + __u16 subslice_offset; 1696 + 1697 + /* 1698 + * Stride at which each of the subslice masks for each slice are 1699 + * stored. 1700 + */ 1701 + __u16 subslice_stride; 1702 + 1703 + /* 1704 + * Offset in data[] at which the EU masks are stored. 1705 + */ 1706 + __u16 eu_offset; 1707 + 1708 + /* 1709 + * Stride at which each of the EU masks for each subslice are stored. 1710 + */ 1711 + __u16 eu_stride; 1712 + 1713 + __u8 data[]; 1618 1714 }; 1619 1715 1620 1716 #if defined(__cplusplus)
+1
tools/perf/Documentation/perf-report.txt
··· 80 80 - comm: command (name) of the task which can be read via /proc/<pid>/comm 81 81 - pid: command and tid of the task 82 82 - dso: name of library or module executed at the time of sample 83 + - dso_size: size of library or module executed at the time of sample 83 84 - symbol: name of function executed at the time of sample 84 85 - symbol_size: size of function executed at the time of sample 85 86 - parent: name of function matched to the parent regex filter. Unmatched
+3
tools/perf/Documentation/perf-trace.txt
··· 117 117 --sched:: 118 118 Accrue thread runtime and provide a summary at the end of the session. 119 119 120 + --failure:: 121 + Show only syscalls that failed, i.e. that returned < 0. 122 + 120 123 -i:: 121 124 --input:: 122 125 Process events from a given perf data file.
+24
tools/perf/Documentation/perf-version.txt
··· 1 + perf-version(1) 2 + =============== 3 + 4 + NAME 5 + ---- 6 + perf-version - display the version of perf binary 7 + 8 + SYNOPSIS 9 + -------- 10 + 'perf version' [--build-options] 11 + 12 + DESCRIPTION 13 + ----------- 14 + With no options given, the 'perf version' prints the perf version 15 + on the standard output. 16 + 17 + If the option '--build-options' is given, then the status of 18 + compiled-in libraries are printed on the standard output. 19 + 20 + OPTIONS 21 + ------- 22 + --build-options:: 23 + Prints the status of compiled-in libraries on the 24 + standard output.
+7 -1
tools/perf/Makefile.config
··· 346 346 ifneq ($(feature-dwarf_getlocations), 1) 347 347 msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157); 348 348 else 349 - CFLAGS += -DHAVE_DWARF_GETLOCATIONS 349 + CFLAGS += -DHAVE_DWARF_GETLOCATIONS_SUPPORT 350 350 endif # dwarf_getlocations 351 351 endif # Dwarf support 352 352 endif # libelf support 353 353 endif # NO_LIBELF 354 + 355 + ifeq ($(feature-glibc), 1) 356 + CFLAGS += -DHAVE_GLIBC_SUPPORT 357 + endif 354 358 355 359 ifdef NO_DWARF 356 360 NO_LIBDW_DWARF_UNWIND := 1 ··· 639 635 else 640 636 LDFLAGS += $(PERL_EMBED_LDFLAGS) 641 637 EXTLIBS += $(PERL_EMBED_LIBADD) 638 + CFLAGS += -DHAVE_LIBPERL_SUPPORT 642 639 $(call detected,CONFIG_LIBPERL) 643 640 endif 644 641 endif ··· 676 671 LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 677 672 EXTLIBS += $(PYTHON_EMBED_LIBADD) 678 673 LANG_BINDINGS += $(obj-perf)python/perf.so 674 + CFLAGS += -DHAVE_LIBPYTHON_SUPPORT 679 675 $(call detected,CONFIG_LIBPYTHON) 680 676 endif 681 677 endif
+2 -1
tools/perf/Makefile.perf
··· 364 364 365 365 ifeq ($(USE_CLANG), 1) 366 366 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization 367 - LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a)) 367 + CLANGLIBS_NOEXT_LIST = $(foreach l,$(CLANGLIBS_LIST),$(shell $(LLVM_CONFIG) --libdir)/libclang$(l)) 368 + LIBCLANG = $(foreach l,$(CLANGLIBS_NOEXT_LIST),$(wildcard $(l).a $(l).so)) 368 369 LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group 369 370 endif 370 371
+7 -4
tools/perf/builtin-trace.c
··· 112 112 bool multiple_threads; 113 113 bool summary; 114 114 bool summary_only; 115 + bool failure_only; 115 116 bool show_comm; 116 117 bool print_sample; 117 118 bool show_tool_stats; ··· 1566 1565 struct thread_trace *ttrace; 1567 1566 size_t printed; 1568 1567 1569 - if (trace->current == NULL) 1568 + if (trace->failure_only || trace->current == NULL) 1570 1569 return 0; 1571 1570 1572 1571 ttrace = thread__priv(trace->current); ··· 1639 1638 args, trace, thread); 1640 1639 1641 1640 if (sc->is_exit) { 1642 - if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { 1641 + if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) { 1643 1642 trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output); 1644 1643 fprintf(trace->output, "%-70s)\n", ttrace->entry_str); 1645 1644 } ··· 1743 1742 } 1744 1743 } 1745 1744 1746 - if (trace->summary_only) 1745 + if (trace->summary_only || (ret >= 0 && trace->failure_only)) 1747 1746 goto out; 1748 1747 1749 1748 trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output); ··· 1962 1961 trace->output); 1963 1962 } 1964 1963 1965 - fprintf(trace->output, ")\n"); 1964 + fprintf(trace->output, "\n"); 1966 1965 1967 1966 if (callchain_ret > 0) 1968 1967 trace__fprintf_callchain(trace, sample); ··· 3088 3087 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 3089 3088 OPT_BOOLEAN('T', "time", &trace.full_time, 3090 3089 "Show full timestamp, not time relative to first start"), 3090 + OPT_BOOLEAN(0, "failure", &trace.failure_only, 3091 + "Show only syscalls that failed"), 3091 3092 OPT_BOOLEAN('s', "summary", &trace.summary_only, 3092 3093 "Show only syscall summary with statistics"), 3093 3094 OPT_BOOLEAN('S', "with-summary", &trace.summary,
+81 -1
tools/perf/builtin-version.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include "builtin.h" 3 3 #include "perf.h" 4 + #include "color.h" 4 5 #include <linux/compiler.h> 6 + #include <tools/config.h> 5 7 #include <stdio.h> 8 + #include <string.h> 9 + #include <subcmd/parse-options.h> 6 10 7 - int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused) 11 + int version_verbose; 12 + 13 + struct version { 14 + bool build_options; 15 + }; 16 + 17 + static struct version version; 18 + 19 + static struct option version_options[] = { 20 + OPT_BOOLEAN(0, "build-options", &version.build_options, 21 + "display the build options"), 22 + }; 23 + 24 + static const char * const version_usage[] = { 25 + "perf version [<options>]", 26 + NULL 27 + }; 28 + 29 + static void on_off_print(const char *status) 8 30 { 31 + printf("[ "); 32 + 33 + if (!strcmp(status, "OFF")) 34 + color_fprintf(stdout, PERF_COLOR_RED, "%-3s", status); 35 + else 36 + color_fprintf(stdout, PERF_COLOR_GREEN, "%-3s", status); 37 + 38 + printf(" ]"); 39 + } 40 + 41 + static void status_print(const char *name, const char *macro, 42 + const char *status) 43 + { 44 + printf("%22s: ", name); 45 + on_off_print(status); 46 + printf(" # %s\n", macro); 47 + } 48 + 49 + #define STATUS(__d, __m) \ 50 + do { \ 51 + if (IS_BUILTIN(__d)) \ 52 + status_print(#__m, #__d, "on"); \ 53 + else \ 54 + status_print(#__m, #__d, "OFF"); \ 55 + } while (0) 56 + 57 + static void library_status(void) 58 + { 59 + STATUS(HAVE_DWARF_SUPPORT, dwarf); 60 + STATUS(HAVE_DWARF_GETLOCATIONS_SUPPORT, dwarf_getlocations); 61 + STATUS(HAVE_GLIBC_SUPPORT, glibc); 62 + STATUS(HAVE_GTK2_SUPPORT, gtk2); 63 + STATUS(HAVE_LIBAUDIT_SUPPORT, libaudit); 64 + STATUS(HAVE_LIBBFD_SUPPORT, libbfd); 65 + STATUS(HAVE_LIBELF_SUPPORT, libelf); 66 + STATUS(HAVE_LIBNUMA_SUPPORT, libnuma); 67 + STATUS(HAVE_LIBNUMA_SUPPORT, numa_num_possible_cpus); 68 + STATUS(HAVE_LIBPERL_SUPPORT, libperl); 69 + STATUS(HAVE_LIBPYTHON_SUPPORT, libpython); 70 + STATUS(HAVE_SLANG_SUPPORT, libslang); 71 + STATUS(HAVE_LIBCRYPTO_SUPPORT, libcrypto); 72 + STATUS(HAVE_LIBUNWIND_SUPPORT, libunwind); 73 + STATUS(HAVE_DWARF_SUPPORT, libdw-dwarf-unwind); 74 + STATUS(HAVE_ZLIB_SUPPORT, zlib); 75 + STATUS(HAVE_LZMA_SUPPORT, lzma); 76 + STATUS(HAVE_AUXTRACE_SUPPORT, get_cpuid); 77 + STATUS(HAVE_LIBBPF_SUPPORT, bpf); 78 + } 79 + 80 + int cmd_version(int argc, const char **argv) 81 + { 82 + argc = parse_options(argc, argv, version_options, version_usage, 83 + PARSE_OPT_STOP_AT_NON_OPTION); 84 + 9 85 printf("perf version %s\n", perf_version_string); 86 + 87 + if (version.build_options || version_verbose == 1) 88 + library_status(); 89 + 10 90 return 0; 11 91 }
+6
tools/perf/perf.c
··· 190 190 break; 191 191 } 192 192 193 + if (!strcmp(cmd, "-vv")) { 194 + (*argv)[0] = "version"; 195 + version_verbose = 1; 196 + break; 197 + } 198 + 193 199 /* 194 200 * Check remaining flags. 195 201 */
+1
tools/perf/perf.h
··· 84 84 struct option; 85 85 extern const char * const *record_usage; 86 86 extern struct option *record_options; 87 + extern int version_verbose; 87 88 88 89 int record__parse_freq(const struct option *opt, const char *str, int unset); 89 90 #endif
+9 -3
tools/perf/ui/browser.c
··· 45 45 ui_browser__set_color(browser, color); 46 46 } 47 47 48 - void ui_browser__gotorc(struct ui_browser *browser, int y, int x) 48 + void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x) 49 49 { 50 50 SLsmg_gotorc(browser->y + y, browser->x + x); 51 + } 52 + 53 + void ui_browser__gotorc(struct ui_browser *browser, int y, int x) 54 + { 55 + SLsmg_gotorc(browser->y + y + browser->extra_title_lines, browser->x + x); 51 56 } 52 57 53 58 void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg, ··· 196 191 { 197 192 browser->width = SLtt_Screen_Cols - 1; 198 193 browser->height = browser->rows = SLtt_Screen_Rows - 2; 194 + browser->rows -= browser->extra_title_lines; 199 195 browser->y = 1; 200 196 browser->x = 0; 201 197 } ··· 343 337 else 344 338 width += 1; 345 339 346 - SLsmg_fill_region(browser->y + row, browser->x, 347 - browser->height - row, width, ' '); 340 + SLsmg_fill_region(browser->y + row + browser->extra_title_lines, browser->x, 341 + browser->rows - row, width, ' '); 348 342 349 343 return 0; 350 344 }
+2
tools/perf/ui/browser.h
··· 17 17 u64 index, top_idx; 18 18 void *top, *entries; 19 19 u16 y, x, width, height, rows, columns, horiz_scroll; 20 + u8 extra_title_lines; 20 21 int current_color; 21 22 void *priv; 22 23 const char *title; ··· 39 38 void ui_browser__refresh_dimensions(struct ui_browser *browser); 40 39 void ui_browser__reset_index(struct ui_browser *browser); 41 40 41 + void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x); 42 42 void ui_browser__gotorc(struct ui_browser *browser, int y, int x); 43 43 void ui_browser__write_nstring(struct ui_browser *browser, const char *msg, 44 44 unsigned int width);
+28 -5
tools/perf/ui/browsers/annotate.c
··· 218 218 annotate_browser__draw_current_jump(browser); 219 219 220 220 ui_browser__set_color(browser, HE_COLORSET_NORMAL); 221 - __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); 221 + __ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1); 222 222 return ret; 223 223 } 224 224 ··· 592 592 return __annotate_browser__search_reverse(browser); 593 593 } 594 594 595 + static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help) 596 + { 597 + struct map_symbol *ms = browser->priv; 598 + struct symbol *sym = ms->sym; 599 + char symbol_dso[SYM_TITLE_MAX_SIZE]; 600 + 601 + if (ui_browser__show(browser, title, help) < 0) 602 + return -1; 603 + 604 + sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso)); 605 + 606 + ui_browser__gotorc_title(browser, 0, 0); 607 + ui_browser__set_color(browser, HE_COLORSET_ROOT); 608 + ui_browser__write_nstring(browser, symbol_dso, browser->width + 1); 609 + return 0; 610 + } 611 + 595 612 static int annotate_browser__run(struct annotate_browser *browser, 596 613 struct perf_evsel *evsel, 597 614 struct hist_browser_timer *hbt) 598 615 { 599 616 struct rb_node *nd = NULL; 617 + struct hists *hists = evsel__hists(evsel); 600 618 struct map_symbol *ms = browser->b.priv; 601 619 struct symbol *sym = ms->sym; 602 620 struct annotation *notes = symbol__annotation(ms->sym); 603 621 const char *help = "Press 'h' for help on key bindings"; 604 622 int delay_secs = hbt ? hbt->refresh : 0; 623 + char title[256]; 605 624 int key; 606 - char title[SYM_TITLE_MAX_SIZE]; 607 625 608 - sym_title(sym, ms->map, title, sizeof(title)); 609 - if (ui_browser__show(&browser->b, title, help) < 0) 626 + annotation__scnprintf_samples_period(notes, title, sizeof(title), evsel); 627 + 628 + if (annotate_browser__show(&browser->b, title, help) < 0) 610 629 return -1; 611 630 612 631 annotate_browser__calc_percent(browser, evsel); ··· 656 637 if (hbt) 657 638 hbt->timer(hbt->arg); 658 639 659 - if (delay_secs != 0) 640 + if (delay_secs != 0) { 660 641 symbol__annotate_decay_histogram(sym, evsel->idx); 642 + hists__scnprintf_title(hists, title, sizeof(title)); 643 + annotate_browser__show(&browser->b, title, help); 644 + } 661 645 continue; 662 646 case K_TAB: 663 647 if (nd != NULL) { ··· 834 812 .seek = ui_browser__list_head_seek, 835 813 .write = annotate_browser__write, 836 814 .filter = disasm_line__filter, 815 + .extra_title_lines = 1, /* for hists__scnprintf_title() */ 837 816 .priv = &ms, 838 817 .use_navkeypressed = true, 839 818 },
+32 -106
tools/perf/ui/browsers/hists.c
··· 32 32 33 33 extern void hist_browser__init_hpp(void); 34 34 35 - static int perf_evsel_browser_title(struct hist_browser *browser, 36 - char *bf, size_t size); 35 + static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size); 37 36 static void hist_browser__update_nr_entries(struct hist_browser *hb); 38 37 39 38 static struct rb_node *hists__filter_entries(struct rb_node *nd, ··· 61 62 return unfolded_rows; 62 63 } 63 64 65 + static void hist_browser__set_title_space(struct hist_browser *hb) 66 + { 67 + struct ui_browser *browser = &hb->b; 68 + struct hists *hists = hb->hists; 69 + struct perf_hpp_list *hpp_list = hists->hpp_list; 70 + 71 + browser->extra_title_lines = hb->show_headers ? hpp_list->nr_header_lines : 0; 72 + } 73 + 64 74 static u32 hist_browser__nr_entries(struct hist_browser *hb) 65 75 { 66 76 u32 nr_entries; ··· 90 82 struct ui_browser *browser = &hb->b; 91 83 struct hists *hists = hb->hists; 92 84 struct perf_hpp_list *hpp_list = hists->hpp_list; 93 - u16 header_offset, index_row; 85 + u16 index_row; 94 86 95 - header_offset = hb->show_headers ? hpp_list->nr_header_lines : 0; 96 - browser->rows = browser->height - header_offset; 87 + if (!hb->show_headers) { 88 + browser->rows += browser->extra_title_lines; 89 + browser->extra_title_lines = 0; 90 + return; 91 + } 92 + 93 + browser->extra_title_lines = hpp_list->nr_header_lines; 94 + browser->rows -= browser->extra_title_lines; 97 95 /* 98 96 * Verify if we were at the last line and that line isn't 99 97 * visibe because we now show the header line(s). ··· 122 108 * changeset. 123 109 */ 124 110 ui_browser__refresh_dimensions(browser); 125 - hist_browser__update_rows(hb); 126 - } 127 - 128 - static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) 129 - { 130 - struct hists *hists = browser->hists; 131 - struct perf_hpp_list *hpp_list = hists->hpp_list; 132 - u16 header_offset; 133 - 134 - header_offset = browser->show_headers ? hpp_list->nr_header_lines : 0; 135 - ui_browser__gotorc(&browser->b, row + header_offset, column); 136 111 } 137 112 138 113 static void hist_browser__reset(struct hist_browser *browser) ··· 659 656 struct hist_entry *h = rb_entry(browser->b.top, 660 657 struct hist_entry, rb_node); 661 658 ui_helpline__pop(); 662 - ui_helpline__fpush("%d: nr_ent=(%d,%d), rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", 659 + ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", 663 660 seq++, browser->b.nr_entries, 664 661 browser->hists->nr_entries, 662 + browser->b.extra_title_lines, 665 663 browser->b.rows, 666 664 browser->b.index, 667 665 browser->b.top_idx, ··· 737 733 } 738 734 739 735 ui_browser__set_color(&browser->b, color); 740 - hist_browser__gotorc(browser, row, 0); 736 + ui_browser__gotorc(&browser->b, row, 0); 741 737 ui_browser__write_nstring(&browser->b, " ", offset); 742 738 ui_browser__printf(&browser->b, "%c", folded_sign); 743 739 ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' '); ··· 1253 1249 }; 1254 1250 int column = 0; 1255 1251 1256 - hist_browser__gotorc(browser, row, 0); 1252 + ui_browser__gotorc(&browser->b, row, 0); 1257 1253 1258 1254 hists__for_each_format(browser->hists, fmt) { 1259 1255 char s[2048]; ··· 1362 1358 goto show_callchain; 1363 1359 } 1364 1360 1365 - hist_browser__gotorc(browser, row, 0); 1361 + ui_browser__gotorc(&browser->b, row, 0); 1366 1362 1367 1363 if (current_entry && browser->b.navkeypressed) 1368 1364 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); ··· 1511 1507 browser->selection = NULL; 1512 1508 } 1513 1509 1514 - hist_browser__gotorc(browser, row, 0); 1510 + ui_browser__gotorc(&browser->b, row, 0); 1515 1511 1516 1512 if (current_entry && browser->b.navkeypressed) 1517 1513 ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); ··· 1717 1713 hists_browser__scnprintf_headers(browser, headers, 1718 1714 sizeof(headers), line); 1719 1715 1720 - ui_browser__gotorc(&browser->b, line, 0); 1716 + ui_browser__gotorc_title(&browser->b, line, 0); 1721 1717 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); 1722 1718 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); 1723 1719 } ··· 1744 1740 static unsigned int hist_browser__refresh(struct ui_browser *browser) 1745 1741 { 1746 1742 unsigned row = 0; 1747 - u16 header_offset = 0; 1748 1743 struct rb_node *nd; 1749 1744 struct hist_browser *hb = container_of(browser, struct hist_browser, b); 1750 - struct hists *hists = hb->hists; 1751 1745 1752 - if (hb->show_headers) { 1753 - struct perf_hpp_list *hpp_list = hists->hpp_list; 1754 - 1746 + if (hb->show_headers) 1755 1747 hist_browser__show_headers(hb); 1756 - header_offset = hpp_list->nr_header_lines; 1757 - } 1758 1748 1759 1749 ui_browser__hists_init_top(browser); 1760 1750 hb->he_selection = NULL; ··· 1786 1788 break; 1787 1789 } 1788 1790 1789 - return row + header_offset; 1791 + return row; 1790 1792 } 1791 1793 1792 1794 static struct rb_node *hists__filter_entries(struct rb_node *nd, ··· 2141 2143 browser->b.seek = ui_browser__hists_seek; 2142 2144 browser->b.use_navkeypressed = true; 2143 2145 browser->show_headers = symbol_conf.show_hist_headers; 2146 + hist_browser__set_title_space(browser); 2144 2147 2145 2148 if (symbol_conf.report_hierarchy) { 2146 2149 struct perf_hpp_list_node *fmt_node; ··· 2182 2183 if (browser) { 2183 2184 browser->hbt = hbt; 2184 2185 browser->env = env; 2185 - browser->title = perf_evsel_browser_title; 2186 + browser->title = hists_browser__scnprintf_title; 2186 2187 } 2187 2188 return browser; 2188 2189 } ··· 2208 2209 return timer == NULL; 2209 2210 } 2210 2211 2211 - static int perf_evsel_browser_title(struct hist_browser *browser, 2212 - char *bf, size_t size) 2212 + static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size) 2213 2213 { 2214 2214 struct hist_browser_timer *hbt = browser->hbt; 2215 - struct hists *hists = browser->hists; 2216 - char unit; 2217 - int printed; 2218 - const struct dso *dso = hists->dso_filter; 2219 - const struct thread *thread = hists->thread_filter; 2220 - int socket_id = hists->socket_filter; 2221 - unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 2222 - u64 nr_events = hists->stats.total_period; 2223 - struct perf_evsel *evsel = hists_to_evsel(hists); 2224 - const char *ev_name = perf_evsel__name(evsel); 2225 - char buf[512], sample_freq_str[64] = ""; 2226 - size_t buflen = sizeof(buf); 2227 - char ref[30] = " show reference callgraph, "; 2228 - bool enable_ref = false; 2215 + int printed = __hists__scnprintf_title(browser->hists, bf, size, !is_report_browser(hbt)); 2229 2216 2230 - if (symbol_conf.filter_relative) { 2231 - nr_samples = hists->stats.nr_non_filtered_samples; 2232 - nr_events = hists->stats.total_non_filtered_period; 2233 - } 2234 - 2235 - if (perf_evsel__is_group_event(evsel)) { 2236 - struct perf_evsel *pos; 2237 - 2238 - perf_evsel__group_desc(evsel, buf, buflen); 2239 - ev_name = buf; 2240 - 2241 - for_each_group_member(pos, evsel) { 2242 - struct hists *pos_hists = evsel__hists(pos); 2243 - 2244 - if (symbol_conf.filter_relative) { 2245 - nr_samples += pos_hists->stats.nr_non_filtered_samples; 2246 - nr_events += pos_hists->stats.total_non_filtered_period; 2247 - } else { 2248 - nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; 2249 - nr_events += pos_hists->stats.total_period; 2250 - } 2251 - } 2252 - } 2253 - 2254 - if (symbol_conf.show_ref_callgraph && 2255 - strstr(ev_name, "call-graph=no")) 2256 - enable_ref = true; 2257 - 2258 - if (!is_report_browser(hbt)) 2259 - scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); 2260 - 2261 - nr_samples = convert_unit(nr_samples, &unit); 2262 - printed = scnprintf(bf, size, 2263 - "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, 2264 - nr_samples, unit, evsel->nr_members > 1 ? "s" : "", 2265 - ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); 2266 - 2267 - 2268 - if (hists->uid_filter_str) 2269 - printed += snprintf(bf + printed, size - printed, 2270 - ", UID: %s", hists->uid_filter_str); 2271 - if (thread) { 2272 - if (hists__has(hists, thread)) { 2273 - printed += scnprintf(bf + printed, size - printed, 2274 - ", Thread: %s(%d)", 2275 - (thread->comm_set ? thread__comm_str(thread) : ""), 2276 - thread->tid); 2277 - } else { 2278 - printed += scnprintf(bf + printed, size - printed, 2279 - ", Thread: %s", 2280 - (thread->comm_set ? thread__comm_str(thread) : "")); 2281 - } 2282 - } 2283 - if (dso) 2284 - printed += scnprintf(bf + printed, size - printed, 2285 - ", DSO: %s", dso->short_name); 2286 - if (socket_id > -1) 2287 - printed += scnprintf(bf + printed, size - printed, 2288 - ", Processor Socket: %d", socket_id); 2289 2217 if (!is_report_browser(hbt)) { 2290 2218 struct perf_top *top = hbt->arg; 2291 2219
+44 -7
tools/perf/util/annotate.c
··· 17 17 #include "config.h" 18 18 #include "cache.h" 19 19 #include "symbol.h" 20 + #include "units.h" 20 21 #include "debug.h" 21 22 #include "annotate.h" 22 23 #include "evsel.h" ··· 2325 2324 struct dso *dso = map->dso; 2326 2325 struct rb_root source_line = RB_ROOT; 2327 2326 struct annotation_options opts = annotation__default_options; 2328 - const char *ev_name = perf_evsel__name(evsel); 2327 + struct annotation *notes = symbol__annotation(sym); 2329 2328 char buf[1024]; 2330 2329 2331 2330 if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0) ··· 2337 2336 print_summary(&source_line, dso->long_name); 2338 2337 } 2339 2338 2340 - if (perf_evsel__is_group_event(evsel)) { 2341 - perf_evsel__group_desc(evsel, buf, sizeof(buf)); 2342 - ev_name = buf; 2343 - } 2344 - 2345 - fprintf(stdout, "%s() %s\nEvent: %s\n\n", sym->name, dso->long_name, ev_name); 2339 + annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel); 2340 + fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name); 2346 2341 symbol__annotate_fprintf2(sym, stdout); 2347 2342 2348 2343 annotated_source__purge(symbol__annotation(sym)->src); ··· 2592 2595 out_free_offsets: 2593 2596 zfree(&notes->offsets); 2594 2597 return -1; 2598 + } 2599 + 2600 + int __annotation__scnprintf_samples_period(struct annotation *notes, 2601 + char *bf, size_t size, 2602 + struct perf_evsel *evsel, 2603 + bool show_freq) 2604 + { 2605 + const char *ev_name = perf_evsel__name(evsel); 2606 + char buf[1024], ref[30] = " show reference callgraph, "; 2607 + char sample_freq_str[64] = ""; 2608 + unsigned long nr_samples = 0; 2609 + int nr_members = 1; 2610 + bool enable_ref = false; 2611 + u64 nr_events = 0; 2612 + char unit; 2613 + int i; 2614 + 2615 + if (perf_evsel__is_group_event(evsel)) { 2616 + perf_evsel__group_desc(evsel, buf, sizeof(buf)); 2617 + ev_name = buf; 2618 + nr_members = evsel->nr_members; 2619 + } 2620 + 2621 + for (i = 0; i < nr_members; i++) { 2622 + struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i); 2623 + 2624 + nr_samples += ah->nr_samples; 2625 + nr_events += ah->period; 2626 + } 2627 + 2628 + if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no")) 2629 + enable_ref = true; 2630 + 2631 + if (show_freq) 2632 + scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); 2633 + 2634 + nr_samples = convert_unit(nr_samples, &unit); 2635 + return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, 2636 + nr_samples, unit, evsel->nr_members > 1 ? "s" : "", 2637 + ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); 2595 2638 } 2596 2639 2597 2640 #define ANNOTATION__CFG(n) \
+12
tools/perf/util/annotate.h
··· 151 151 void annotation_line__write(struct annotation_line *al, struct annotation *notes, 152 152 struct annotation_write_ops *ops); 153 153 154 + int __annotation__scnprintf_samples_period(struct annotation *notes, 155 + char *bf, size_t size, 156 + struct perf_evsel *evsel, 157 + bool show_freq); 158 + 159 + static inline int annotation__scnprintf_samples_period(struct annotation *notes, 160 + char *bf, size_t size, 161 + struct perf_evsel *evsel) 162 + { 163 + return __annotation__scnprintf_samples_period(notes, bf, size, evsel, true); 164 + } 165 + 154 166 int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 155 167 size_t disasm__fprintf(struct list_head *head, FILE *fp); 156 168 void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
+57 -63
tools/perf/util/auxtrace.c
··· 302 302 return 0; 303 303 } 304 304 305 - static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, 306 - struct perf_session *session, 307 - unsigned int idx, 308 - struct auxtrace_buffer *buffer, 309 - struct auxtrace_buffer **buffer_ptr) 310 - { 311 - int err; 312 - 313 - if (session->one_mmap) { 314 - buffer->data = buffer->data_offset - session->one_mmap_offset + 315 - session->one_mmap_addr; 316 - } else if (perf_data__is_pipe(session->data)) { 317 - buffer->data = auxtrace_copy_data(buffer->size, session); 318 - if (!buffer->data) 319 - return -ENOMEM; 320 - buffer->data_needs_freeing = true; 321 - } else if (BITS_PER_LONG == 32 && 322 - buffer->size > BUFFER_LIMIT_FOR_32_BIT) { 323 - err = auxtrace_queues__split_buffer(queues, idx, buffer); 324 - if (err) 325 - return err; 326 - } 327 - 328 - err = auxtrace_queues__queue_buffer(queues, idx, buffer); 329 - if (err) 330 - return err; 331 - 332 - /* FIXME: Doesn't work for split buffer */ 333 - if (buffer_ptr) 334 - *buffer_ptr = buffer; 335 - 336 - return 0; 337 - } 338 - 339 305 static bool filter_cpu(struct perf_session *session, int cpu) 340 306 { 341 307 unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap; ··· 309 343 return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap); 310 344 } 311 345 346 + static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, 347 + struct perf_session *session, 348 + unsigned int idx, 349 + struct auxtrace_buffer *buffer, 350 + struct auxtrace_buffer **buffer_ptr) 351 + { 352 + int err = -ENOMEM; 353 + 354 + if (filter_cpu(session, buffer->cpu)) 355 + return 0; 356 + 357 + buffer = memdup(buffer, sizeof(*buffer)); 358 + if (!buffer) 359 + return -ENOMEM; 360 + 361 + if (session->one_mmap) { 362 + buffer->data = buffer->data_offset - session->one_mmap_offset + 363 + session->one_mmap_addr; 364 + } else if (perf_data__is_pipe(session->data)) { 365 + buffer->data = auxtrace_copy_data(buffer->size, session); 366 + if (!buffer->data) 367 + goto out_free; 368 + buffer->data_needs_freeing = true; 369 + } else if (BITS_PER_LONG == 32 && 370 + buffer->size > BUFFER_LIMIT_FOR_32_BIT) { 371 + err = auxtrace_queues__split_buffer(queues, idx, buffer); 372 + if (err) 373 + goto out_free; 374 + } 375 + 376 + err = auxtrace_queues__queue_buffer(queues, idx, buffer); 377 + if (err) 378 + goto out_free; 379 + 380 + /* FIXME: Doesn't work for split buffer */ 381 + if (buffer_ptr) 382 + *buffer_ptr = buffer; 383 + 384 + return 0; 385 + 386 + out_free: 387 + auxtrace_buffer__free(buffer); 388 + return err; 389 + } 390 + 312 391 int auxtrace_queues__add_event(struct auxtrace_queues *queues, 313 392 struct perf_session *session, 314 393 union perf_event *event, off_t data_offset, 315 394 struct auxtrace_buffer **buffer_ptr) 316 395 { 317 - struct auxtrace_buffer *buffer; 318 - unsigned int idx; 319 - int err; 396 + struct auxtrace_buffer buffer = { 397 + .pid = -1, 398 + .tid = event->auxtrace.tid, 399 + .cpu = event->auxtrace.cpu, 400 + .data_offset = data_offset, 401 + .offset = event->auxtrace.offset, 402 + .reference = event->auxtrace.reference, 403 + .size = event->auxtrace.size, 404 + }; 405 + unsigned int idx = event->auxtrace.idx; 320 406 321 - if (filter_cpu(session, event->auxtrace.cpu)) 322 - return 0; 323 - 324 - buffer = zalloc(sizeof(struct auxtrace_buffer)); 325 - if (!buffer) 326 - return -ENOMEM; 327 - 328 - buffer->pid = -1; 329 - buffer->tid = event->auxtrace.tid; 330 - buffer->cpu = event->auxtrace.cpu; 331 - buffer->data_offset = data_offset; 332 - buffer->offset = event->auxtrace.offset; 333 - buffer->reference = event->auxtrace.reference; 334 - buffer->size = event->auxtrace.size; 335 - idx = event->auxtrace.idx; 336 - 337 - err = auxtrace_queues__add_buffer(queues, session, idx, buffer, 338 - buffer_ptr); 339 - if (err) 340 - goto out_err; 341 - 342 - return 0; 343 - 344 - out_err: 345 - auxtrace_buffer__free(buffer); 346 - return err; 407 + return auxtrace_queues__add_buffer(queues, session, idx, &buffer, 408 + buffer_ptr); 347 409 } 348 410 349 411 static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues,
+1 -1
tools/perf/util/c++/clang-test.cpp
··· 41 41 if (!M) 42 42 return -1; 43 43 for (llvm::Function& F : *M) 44 - if (F.getName() == "bpf_func__SyS_epoll_wait") 44 + if (F.getName() == "bpf_func__SyS_epoll_pwait") 45 45 return 0; 46 46 return -1; 47 47 }
+10 -1
tools/perf/util/c++/clang.cpp
··· 9 9 * Copyright (C) 2016 Huawei Inc. 10 10 */ 11 11 12 + #include "clang/Basic/Version.h" 12 13 #include "clang/CodeGen/CodeGenAction.h" 13 14 #include "clang/Frontend/CompilerInvocation.h" 14 15 #include "clang/Frontend/CompilerInstance.h" ··· 59 58 60 59 FrontendOptions& Opts = CI->getFrontendOpts(); 61 60 Opts.Inputs.clear(); 62 - Opts.Inputs.emplace_back(Path, IK_C); 61 + Opts.Inputs.emplace_back(Path, 62 + FrontendOptions::getInputKindForExtension("c")); 63 63 return CI; 64 64 } 65 65 ··· 73 71 74 72 Clang.setVirtualFileSystem(&*VFS); 75 73 74 + #if CLANG_VERSION_MAJOR < 4 76 75 IntrusiveRefCntPtr<CompilerInvocation> CI = 77 76 createCompilerInvocation(std::move(CFlags), Path, 78 77 Clang.getDiagnostics()); 79 78 Clang.setInvocation(&*CI); 79 + #else 80 + std::shared_ptr<CompilerInvocation> CI( 81 + createCompilerInvocation(std::move(CFlags), Path, 82 + Clang.getDiagnostics())); 83 + Clang.setInvocation(CI); 84 + #endif 80 85 81 86 std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx)); 82 87 if (!Clang.ExecuteAction(*Act))
+1 -1
tools/perf/util/dwarf-aux.c
··· 979 979 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); 980 980 } 981 981 982 - #ifdef HAVE_DWARF_GETLOCATIONS 982 + #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT 983 983 /** 984 984 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE 985 985 * @sp_die: a subprogram DIE
+81
tools/perf/util/hist.c
··· 6 6 #include "session.h" 7 7 #include "namespaces.h" 8 8 #include "sort.h" 9 + #include "units.h" 9 10 #include "evlist.h" 10 11 #include "evsel.h" 11 12 #include "annotate.h" ··· 15 14 #include "ui/progress.h" 16 15 #include <errno.h> 17 16 #include <math.h> 17 + #include <inttypes.h> 18 18 #include <sys/param.h> 19 19 20 20 static bool hists__filter_entry_by_dso(struct hists *hists, ··· 2454 2452 { 2455 2453 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period : 2456 2454 hists->stats.total_period; 2455 + } 2456 + 2457 + int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq) 2458 + { 2459 + char unit; 2460 + int printed; 2461 + const struct dso *dso = hists->dso_filter; 2462 + const struct thread *thread = hists->thread_filter; 2463 + int socket_id = hists->socket_filter; 2464 + unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 2465 + u64 nr_events = hists->stats.total_period; 2466 + struct perf_evsel *evsel = hists_to_evsel(hists); 2467 + const char *ev_name = perf_evsel__name(evsel); 2468 + char buf[512], sample_freq_str[64] = ""; 2469 + size_t buflen = sizeof(buf); 2470 + char ref[30] = " show reference callgraph, "; 2471 + bool enable_ref = false; 2472 + 2473 + if (symbol_conf.filter_relative) { 2474 + nr_samples = hists->stats.nr_non_filtered_samples; 2475 + nr_events = hists->stats.total_non_filtered_period; 2476 + } 2477 + 2478 + if (perf_evsel__is_group_event(evsel)) { 2479 + struct perf_evsel *pos; 2480 + 2481 + perf_evsel__group_desc(evsel, buf, buflen); 2482 + ev_name = buf; 2483 + 2484 + for_each_group_member(pos, evsel) { 2485 + struct hists *pos_hists = evsel__hists(pos); 2486 + 2487 + if (symbol_conf.filter_relative) { 2488 + nr_samples += pos_hists->stats.nr_non_filtered_samples; 2489 + nr_events += pos_hists->stats.total_non_filtered_period; 2490 + } else { 2491 + nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; 2492 + nr_events += pos_hists->stats.total_period; 2493 + } 2494 + } 2495 + } 2496 + 2497 + if (symbol_conf.show_ref_callgraph && 2498 + strstr(ev_name, "call-graph=no")) 2499 + enable_ref = true; 2500 + 2501 + if (show_freq) 2502 + scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); 2503 + 2504 + nr_samples = convert_unit(nr_samples, &unit); 2505 + printed = scnprintf(bf, size, 2506 + "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, 2507 + nr_samples, unit, evsel->nr_members > 1 ? "s" : "", 2508 + ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); 2509 + 2510 + 2511 + if (hists->uid_filter_str) 2512 + printed += snprintf(bf + printed, size - printed, 2513 + ", UID: %s", hists->uid_filter_str); 2514 + if (thread) { 2515 + if (hists__has(hists, thread)) { 2516 + printed += scnprintf(bf + printed, size - printed, 2517 + ", Thread: %s(%d)", 2518 + (thread->comm_set ? thread__comm_str(thread) : ""), 2519 + thread->tid); 2520 + } else { 2521 + printed += scnprintf(bf + printed, size - printed, 2522 + ", Thread: %s", 2523 + (thread->comm_set ? thread__comm_str(thread) : "")); 2524 + } 2525 + } 2526 + if (dso) 2527 + printed += scnprintf(bf + printed, size - printed, 2528 + ", DSO: %s", dso->short_name); 2529 + if (socket_id > -1) 2530 + printed += scnprintf(bf + printed, size - printed, 2531 + ", Processor Socket: %d", socket_id); 2532 + 2533 + return printed; 2457 2534 } 2458 2535 2459 2536 int parse_filter_percentage(const struct option *opt __maybe_unused,
+7
tools/perf/util/hist.h
··· 61 61 HISTC_SRCLINE_TO, 62 62 HISTC_TRACE, 63 63 HISTC_SYM_SIZE, 64 + HISTC_DSO_SIZE, 64 65 HISTC_NR_COLS, /* Last entry */ 65 66 }; 66 67 ··· 504 503 int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, 505 504 struct perf_hpp_list *hpp_list); 506 505 int hists__fprintf_headers(struct hists *hists, FILE *fp); 506 + int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq); 507 + 508 + static inline int hists__scnprintf_title(struct hists *hists, char *bf, size_t size) 509 + { 510 + return __hists__scnprintf_title(hists, bf, size, true); 511 + } 507 512 508 513 #endif /* __PERF_HIST_H */
+4
tools/perf/util/map.h
··· 103 103 return ip; 104 104 } 105 105 106 + static inline size_t map__size(const struct map *map) 107 + { 108 + return map->end - map->start; 109 + } 106 110 107 111 /* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ 108 112 u64 map__rip_2objdump(struct map *map, u64 rip);
+1 -1
tools/perf/util/session.c
··· 1591 1591 drop_rate = (double)stats->total_lost_samples / 1592 1592 (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples); 1593 1593 if (drop_rate > 0.05) { 1594 - ui__warning("Processed %" PRIu64 " samples and lost %3.2f%% samples!\n\n", 1594 + ui__warning("Processed %" PRIu64 " samples and lost %3.2f%%!\n\n", 1595 1595 stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples, 1596 1596 drop_rate * 100.0); 1597 1597 }
+41
tools/perf/util/sort.c
··· 1545 1545 .se_width_idx = HISTC_SYM_SIZE, 1546 1546 }; 1547 1547 1548 + /* --sort dso_size */ 1549 + 1550 + static int64_t _sort__dso_size_cmp(struct map *map_l, struct map *map_r) 1551 + { 1552 + int64_t size_l = map_l != NULL ? map__size(map_l) : 0; 1553 + int64_t size_r = map_r != NULL ? map__size(map_r) : 0; 1554 + 1555 + return size_l < size_r ? -1 : 1556 + size_l == size_r ? 0 : 1; 1557 + } 1558 + 1559 + static int64_t 1560 + sort__dso_size_cmp(struct hist_entry *left, struct hist_entry *right) 1561 + { 1562 + return _sort__dso_size_cmp(right->ms.map, left->ms.map); 1563 + } 1564 + 1565 + static int _hist_entry__dso_size_snprintf(struct map *map, char *bf, 1566 + size_t bf_size, unsigned int width) 1567 + { 1568 + if (map && map->dso) 1569 + return repsep_snprintf(bf, bf_size, "%*d", width, 1570 + map__size(map)); 1571 + 1572 + return repsep_snprintf(bf, bf_size, "%*s", width, "unknown"); 1573 + } 1574 + 1575 + static int hist_entry__dso_size_snprintf(struct hist_entry *he, char *bf, 1576 + size_t size, unsigned int width) 1577 + { 1578 + return _hist_entry__dso_size_snprintf(he->ms.map, bf, size, width); 1579 + } 1580 + 1581 + struct sort_entry sort_dso_size = { 1582 + .se_header = "DSO size", 1583 + .se_cmp = sort__dso_size_cmp, 1584 + .se_snprintf = hist_entry__dso_size_snprintf, 1585 + .se_width_idx = HISTC_DSO_SIZE, 1586 + }; 1587 + 1548 1588 1549 1589 struct sort_dimension { 1550 1590 const char *name; ··· 1609 1569 DIM(SORT_TRANSACTION, "transaction", sort_transaction), 1610 1570 DIM(SORT_TRACE, "trace", sort_trace), 1611 1571 DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size), 1572 + DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size), 1612 1573 DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), 1613 1574 }; 1614 1575
+1
tools/perf/util/sort.h
··· 220 220 SORT_TRANSACTION, 221 221 SORT_TRACE, 222 222 SORT_SYM_SIZE, 223 + SORT_DSO_SIZE, 223 224 SORT_CGROUP_ID, 224 225 225 226 /* branch stack specific sort keys */
+2 -2
tools/perf/util/util.h
··· 11 11 #include <stdlib.h> 12 12 #include <stdarg.h> 13 13 #include <linux/compiler.h> 14 - #include <linux/types.h> 15 - #include "namespaces.h" 14 + #include <sys/types.h> 16 15 17 16 /* General helper functions */ 18 17 void usage(const char *err) __noreturn; ··· 25 26 #define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) 26 27 27 28 struct dirent; 29 + struct nsinfo; 28 30 struct strlist; 29 31 30 32 int mkdir_p(char *path, mode_t mode);