Pull tooling improvements and fixes from Arnaldo Carvalho de Melo: perf annotate fixes and improvements: - Allow showing offsets in more than just jump targets, use the new 'O' hotkey in the TUI, config ~/.perfconfig annotate.offset_level for it and for --stdio2 (Arnaldo Carvalho de Melo) - Use the resolved variable names from objdump disassembled lines to make them more compact, just like was already done for some instructions, like "mov", this eventually will be done more generally, but lets now add some more to the existing mechanism (Arnaldo Carvalho de Melo) perf record fixes: - Change warning for missing topology sysfs entry to debug, as not all architectures have those files, s390 being one of those (Thomas Richter) perf sched fixes: - Fix -g/--call-graph documentation (Takuya Yamamoto) perf stat: - Enable 1ms interval for printing event counters values in (Alexey Budankov) perf test fixes: - Run dwarf unwind on arm32 (Kim Phillips) - Remove unused ptrace.h include from LLVM test, sidesteping older clang's lack of support for some asm constructs (Arnaldo Carvalho de Melo) perf version fixes: - Do not print info about HAVE_LIBAUDIT_SUPPORT in 'perf version --build-options' when HAVE_SYSCALL_TABLE_SUPPORT is true, as libaudit won't be used in that case, print info about syscall_table support instead (Jin Yao) Build system fixes: - Use HAVE_..._SUPPORT used consistently (Jin Yao) - Restore READ_ONCE() C++ compatibility in tools/include (Mark Rutland) - Give hints about package names needed to build jvmti (Arnaldo Carvalho de Melo)
Unified · Split
| @@ -136,7 +136,6 @@ · 135 unmodified lines | ||
| 136 | 136 | #endif |
| 137 | 137 | |
| 138 | 138 | #ifndef __ASSEMBLY__ |
| 139 | −#ifndef __BPF__ | |
| 140 | 139 | /* |
| 141 | 140 | * This output constraint should be used for any inline asm which has a "call" |
| 142 | 141 | * instruction. Otherwise the asm may be inserted before the frame pointer |
| @@ -146,6 +145,5 @@ · 3 unmodified lines | ||
| 146 | 145 | register unsigned long current_stack_pointer asm(_ASM_SP); |
| 147 | 146 | #define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer) |
| 148 | 147 | #endif |
| 149 | −#endif | |
| 150 | 148 | |
| 151 | 149 | #endif /* _ASM_X86_ASM_H */ |
| @@ -151,11 +151,21 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s · 150 unmodified lines | ||
| 151 | 151 | * required ordering. |
| 152 | 152 | */ |
| 153 | 153 | |
| 154 | −#define READ_ONCE(x) \ | |
| 155 | − ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) | |
| 156 | − | |
| 157 | −#define WRITE_ONCE(x, val) \ | |
| 158 | − ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) | |
| 154 | +#define READ_ONCE(x) \ | |
| 155 | +({ \ | |
| 156 | + union { typeof(x) __val; char __c[1]; } __u = \ | |
| 157 | + { .__c = { 0 } }; \ | |
| 158 | + __read_once_size(&(x), __u.__c, sizeof(x)); \ | |
| 159 | + __u.__val; \ | |
| 160 | +}) | |
| 161 | + | |
| 162 | +#define WRITE_ONCE(x, val) \ | |
| 163 | +({ \ | |
| 164 | + union { typeof(x) __val; char __c[1]; } __u = \ | |
| 165 | + { .__val = (val) }; \ | |
| 166 | + __write_once_size(&(x), __u.__c, sizeof(x)); \ | |
| 167 | + __u.__val; \ | |
| 168 | +}) | |
| 159 | 169 | |
| 160 | 170 | |
| 161 | 171 | #ifndef __fallthrough |
| @@ -334,6 +334,11 @@ annotate.*:: · 333 unmodified lines | ||
| 334 | 334 | |
| 335 | 335 | 99.93 │ mov %eax,%eax |
| 336 | 336 | |
| 337 | + annotate.offset_level:: | |
| 338 | + Default is '1', meaning just jump targets will have offsets show right beside | |
| 339 | + the instruction. When set to '2' 'call' instructions will also have its offsets | |
| 340 | + shown, 3 or higher will show offsets for all instructions. | |
| 341 | + | |
| 337 | 342 | hist.*:: |
| 338 | 343 | hist.percentage:: |
| 339 | 344 | This option control the way to calculate overhead of filtered entries - |
| @@ -104,8 +104,8 @@ OPTIONS for 'perf sched timehist' · 103 unmodified lines | ||
| 104 | 104 | kallsyms pathname |
| 105 | 105 | |
| 106 | 106 | -g:: |
| 107 | −--no-call-graph:: | |
| 108 | − Do not display call chains if present. | |
| 107 | +--call-graph:: | |
| 108 | + Display call chains if present (default on). | |
| 109 | 109 | |
| 110 | 110 | --max-stack:: |
| 111 | 111 | Maximum number of functions to display in backtrace, default 5. |
| @@ -153,7 +153,7 @@ perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' -- m · 152 unmodified lines | ||
| 153 | 153 | |
| 154 | 154 | -I msecs:: |
| 155 | 155 | --interval-print msecs:: |
| 156 | −Print count deltas every N milliseconds (minimum: 10ms) | |
| 156 | +Print count deltas every N milliseconds (minimum: 1ms) | |
| 157 | 157 | The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution. |
| 158 | 158 | example: 'perf stat -I 1000 -e cycles -a sleep 5' |
| 159 | 159 | |
| @@ -68,7 +68,7 @@ ifeq ($(NO_PERF_REGS),0) · 67 unmodified lines | ||
| 68 | 68 | endif |
| 69 | 69 | |
| 70 | 70 | ifneq ($(NO_SYSCALL_TABLE),1) |
| 71 | − CFLAGS += -DHAVE_SYSCALL_TABLE | |
| 71 | + CFLAGS += -DHAVE_SYSCALL_TABLE_SUPPORT | |
| 72 | 72 | endif |
| 73 | 73 | |
| 74 | 74 | # So far there's only x86 and arm libdw unwind support merged in perf. |
| @@ -847,7 +847,7 @@ ifndef NO_JVMTI · 772 unmodified lines | ||
| 847 | 847 | ifeq ($(feature-jvmti), 1) |
| 848 | 848 | $(call detected_var,JDIR) |
| 849 | 849 | else |
| 850 | − $(warning No openjdk development package found, please install JDK package) | |
| 850 | + $(warning No openjdk development package found, please install JDK package, e.g. openjdk-8-jdk, java-1.8.0-openjdk-devel) | |
| 851 | 851 | NO_JVMTI := 1 |
| 852 | 852 | endif |
| 853 | 853 | endif |
| @@ -0,0 +1,12 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | +#ifndef ARCH_TESTS_H | |
| 3 | +#define ARCH_TESTS_H | |
| 4 | + | |
| 5 | +#ifdef HAVE_DWARF_UNWIND_SUPPORT | |
| 6 | +struct thread; | |
| 7 | +struct perf_sample; | |
| 8 | +#endif | |
| 9 | + | |
| 10 | +extern struct test arch_tests[]; | |
| 11 | + | |
| 12 | +#endif | |
| @@ -1,2 +1,4 @@ | ||
| 1 | 1 | libperf-y += regs_load.o |
| 2 | 2 | libperf-y += dwarf-unwind.o |
| 3 | + | |
| 4 | +libperf-y += arch-tests.o | |
| @@ -0,0 +1,16 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +#include <string.h> | |
| 3 | +#include "tests/tests.h" | |
| 4 | +#include "arch-tests.h" | |
| 5 | + | |
| 6 | +struct test arch_tests[] = { | |
| 7 | +#ifdef HAVE_DWARF_UNWIND_SUPPORT | |
| 8 | + { | |
| 9 | + .desc = "DWARF unwind", | |
| 10 | + .func = test__dwarf_unwind, | |
| 11 | + }, | |
| 12 | +#endif | |
| 13 | + { | |
| 14 | + .func = NULL, | |
| 15 | + }, | |
| 16 | +}; | |
| @@ -1,21 +1,43 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | static struct ins x86__instructions[] = { |
| 3 | + { .name = "adc", .ops = &mov_ops, }, | |
| 4 | + { .name = "adcb", .ops = &mov_ops, }, | |
| 5 | + { .name = "adcl", .ops = &mov_ops, }, | |
| 3 | 6 | { .name = "add", .ops = &mov_ops, }, |
| 4 | 7 | { .name = "addl", .ops = &mov_ops, }, |
| 5 | 8 | { .name = "addq", .ops = &mov_ops, }, |
| 9 | + { .name = "addsd", .ops = &mov_ops, }, | |
| 6 | 10 | { .name = "addw", .ops = &mov_ops, }, |
| 7 | 11 | { .name = "and", .ops = &mov_ops, }, |
| 12 | + { .name = "andb", .ops = &mov_ops, }, | |
| 13 | + { .name = "andl", .ops = &mov_ops, }, | |
| 14 | + { .name = "andpd", .ops = &mov_ops, }, | |
| 15 | + { .name = "andps", .ops = &mov_ops, }, | |
| 16 | + { .name = "andq", .ops = &mov_ops, }, | |
| 17 | + { .name = "andw", .ops = &mov_ops, }, | |
| 18 | + { .name = "bsr", .ops = &mov_ops, }, | |
| 19 | + { .name = "bt", .ops = &mov_ops, }, | |
| 20 | + { .name = "btr", .ops = &mov_ops, }, | |
| 8 | 21 | { .name = "bts", .ops = &mov_ops, }, |
| 22 | + { .name = "btsq", .ops = &mov_ops, }, | |
| 9 | 23 | { .name = "call", .ops = &call_ops, }, |
| 10 | 24 | { .name = "callq", .ops = &call_ops, }, |
| 25 | + { .name = "cmovbe", .ops = &mov_ops, }, | |
| 26 | + { .name = "cmove", .ops = &mov_ops, }, | |
| 27 | + { .name = "cmovae", .ops = &mov_ops, }, | |
| 11 | 28 | { .name = "cmp", .ops = &mov_ops, }, |
| 12 | 29 | { .name = "cmpb", .ops = &mov_ops, }, |
| 13 | 30 | { .name = "cmpl", .ops = &mov_ops, }, |
| 14 | 31 | { .name = "cmpq", .ops = &mov_ops, }, |
| 15 | 32 | { .name = "cmpw", .ops = &mov_ops, }, |
| 16 | 33 | { .name = "cmpxch", .ops = &mov_ops, }, |
| 34 | + { .name = "cmpxchg", .ops = &mov_ops, }, | |
| 35 | + { .name = "cs", .ops = &mov_ops, }, | |
| 17 | 36 | { .name = "dec", .ops = &dec_ops, }, |
| 18 | 37 | { .name = "decl", .ops = &dec_ops, }, |
| 38 | + { .name = "divsd", .ops = &mov_ops, }, | |
| 39 | + { .name = "divss", .ops = &mov_ops, }, | |
| 40 | + { .name = "gs", .ops = &mov_ops, }, | |
| 19 | 41 | { .name = "imul", .ops = &mov_ops, }, |
| 20 | 42 | { .name = "inc", .ops = &dec_ops, }, |
| 21 | 43 | { .name = "incl", .ops = &dec_ops, }, |
| @@ -57,25 +79,68 @@ static struct ins x86__instructions[] = { · 35 unmodified lines | ||
| 57 | 79 | { .name = "lea", .ops = &mov_ops, }, |
| 58 | 80 | { .name = "lock", .ops = &lock_ops, }, |
| 59 | 81 | { .name = "mov", .ops = &mov_ops, }, |
| 82 | + { .name = "movapd", .ops = &mov_ops, }, | |
| 83 | + { .name = "movaps", .ops = &mov_ops, }, | |
| 60 | 84 | { .name = "movb", .ops = &mov_ops, }, |
| 61 | 85 | { .name = "movdqa", .ops = &mov_ops, }, |
| 86 | + { .name = "movdqu", .ops = &mov_ops, }, | |
| 62 | 87 | { .name = "movl", .ops = &mov_ops, }, |
| 63 | 88 | { .name = "movq", .ops = &mov_ops, }, |
| 89 | + { .name = "movsd", .ops = &mov_ops, }, | |
| 64 | 90 | { .name = "movslq", .ops = &mov_ops, }, |
| 91 | + { .name = "movss", .ops = &mov_ops, }, | |
| 92 | + { .name = "movupd", .ops = &mov_ops, }, | |
| 93 | + { .name = "movups", .ops = &mov_ops, }, | |
| 94 | + { .name = "movw", .ops = &mov_ops, }, | |
| 65 | 95 | { .name = "movzbl", .ops = &mov_ops, }, |
| 66 | 96 | { .name = "movzwl", .ops = &mov_ops, }, |
| 97 | + { .name = "mulsd", .ops = &mov_ops, }, | |
| 98 | + { .name = "mulss", .ops = &mov_ops, }, | |
| 67 | 99 | { .name = "nop", .ops = &nop_ops, }, |
| 68 | 100 | { .name = "nopl", .ops = &nop_ops, }, |
| 69 | 101 | { .name = "nopw", .ops = &nop_ops, }, |
| 70 | 102 | { .name = "or", .ops = &mov_ops, }, |
| 103 | + { .name = "orb", .ops = &mov_ops, }, | |
| 71 | 104 | { .name = "orl", .ops = &mov_ops, }, |
| 105 | + { .name = "orps", .ops = &mov_ops, }, | |
| 106 | + { .name = "orq", .ops = &mov_ops, }, | |
| 107 | + { .name = "pand", .ops = &mov_ops, }, | |
| 108 | + { .name = "paddq", .ops = &mov_ops, }, | |
| 109 | + { .name = "pcmpeqb", .ops = &mov_ops, }, | |
| 110 | + { .name = "por", .ops = &mov_ops, }, | |
| 111 | + { .name = "rclb", .ops = &mov_ops, }, | |
| 112 | + { .name = "rcll", .ops = &mov_ops, }, | |
| 113 | + { .name = "retq", .ops = &ret_ops, }, | |
| 114 | + { .name = "sbb", .ops = &mov_ops, }, | |
| 115 | + { .name = "sbbl", .ops = &mov_ops, }, | |
| 116 | + { .name = "sete", .ops = &mov_ops, }, | |
| 117 | + { .name = "sub", .ops = &mov_ops, }, | |
| 118 | + { .name = "subl", .ops = &mov_ops, }, | |
| 119 | + { .name = "subq", .ops = &mov_ops, }, | |
| 120 | + { .name = "subsd", .ops = &mov_ops, }, | |
| 121 | + { .name = "subw", .ops = &mov_ops, }, | |
| 72 | 122 | { .name = "test", .ops = &mov_ops, }, |
| 73 | 123 | { .name = "testb", .ops = &mov_ops, }, |
| 74 | 124 | { .name = "testl", .ops = &mov_ops, }, |
| 125 | + { .name = "ucomisd", .ops = &mov_ops, }, | |
| 126 | + { .name = "ucomiss", .ops = &mov_ops, }, | |
| 127 | + { .name = "vaddsd", .ops = &mov_ops, }, | |
| 128 | + { .name = "vandpd", .ops = &mov_ops, }, | |
| 129 | + { .name = "vmovdqa", .ops = &mov_ops, }, | |
| 130 | + { .name = "vmovq", .ops = &mov_ops, }, | |
| 131 | + { .name = "vmovsd", .ops = &mov_ops, }, | |
| 132 | + { .name = "vmulsd", .ops = &mov_ops, }, | |
| 133 | + { .name = "vorpd", .ops = &mov_ops, }, | |
| 134 | + { .name = "vsubsd", .ops = &mov_ops, }, | |
| 135 | + { .name = "vucomisd", .ops = &mov_ops, }, | |
| 75 | 136 | { .name = "xadd", .ops = &mov_ops, }, |
| 76 | 137 | { .name = "xbeginl", .ops = &jump_ops, }, |
| 77 | 138 | { .name = "xbeginq", .ops = &jump_ops, }, |
| 78 | − { .name = "retq", .ops = &ret_ops, }, | |
| 139 | + { .name = "xchg", .ops = &mov_ops, }, | |
| 140 | + { .name = "xor", .ops = &mov_ops, }, | |
| 141 | + { .name = "xorb", .ops = &mov_ops, }, | |
| 142 | + { .name = "xorpd", .ops = &mov_ops, }, | |
| 143 | + { .name = "xorps", .ops = &mov_ops, }, | |
| 79 | 144 | }; |
| 80 | 145 | |
| 81 | 146 | static bool x86__ins_is_fused(struct arch *arch, const char *ins1, |
| @@ -439,7 +439,7 @@ int cmd_help(int argc, const char **argv) · 438 unmodified lines | ||
| 439 | 439 | #ifdef HAVE_LIBELF_SUPPORT |
| 440 | 440 | "probe", |
| 441 | 441 | #endif |
| 442 | −#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE) | |
| 442 | +#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT) | |
| 443 | 443 | "trace", |
| 444 | 444 | #endif |
| 445 | 445 | NULL }; |
| @@ -2801,11 +2801,11 @@ int find_scripts(char **scripts_array, char **scripts_path_array) · 2800 unmodified lines | ||
| 2801 | 2801 | for_each_lang(scripts_path, scripts_dir, lang_dirent) { |
| 2802 | 2802 | scnprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, |
| 2803 | 2803 | lang_dirent->d_name); |
| 2804 | −#ifdef NO_LIBPERL | |
| 2804 | +#ifndef HAVE_LIBPERL_SUPPORT | |
| 2805 | 2805 | if (strstr(lang_path, "perl")) |
| 2806 | 2806 | continue; |
| 2807 | 2807 | #endif |
| 2808 | −#ifdef NO_LIBPYTHON | |
| 2808 | +#ifndef HAVE_LIBPYTHON_SUPPORT | |
| 2809 | 2809 | if (strstr(lang_path, "python")) |
| 2810 | 2810 | continue; |
| 2811 | 2811 | #endif |
| @@ -1943,7 +1943,8 @@ static const struct option stat_options[] = { · 1942 unmodified lines | ||
| 1943 | 1943 | OPT_STRING(0, "post", &post_cmd, "command", |
| 1944 | 1944 | "command to run after to the measured command"), |
| 1945 | 1945 | OPT_UINTEGER('I', "interval-print", &stat_config.interval, |
| 1946 | − "print counts at regular interval in ms (>= 10)"), | |
| 1946 | + "print counts at regular interval in ms " | |
| 1947 | + "(overhead is possible for values <= 100ms)"), | |
| 1947 | 1948 | OPT_INTEGER(0, "interval-count", &stat_config.times, |
| 1948 | 1949 | "print counts for fixed number of times"), |
| 1949 | 1950 | OPT_UINTEGER(0, "timeout", &stat_config.timeout, |
| @@ -2923,17 +2924,6 @@ int cmd_stat(int argc, const char **argv) · 973 unmodified lines | ||
| 2923 | 2924 | } |
| 2924 | 2925 | } |
| 2925 | 2926 | |
| 2926 | − if (interval && interval < 100) { | |
| 2927 | − if (interval < 10) { | |
| 2928 | − pr_err("print interval must be >= 10ms\n"); | |
| 2929 | − parse_options_usage(stat_usage, stat_options, "I", 1); | |
| 2930 | − goto out; | |
| 2931 | − } else | |
| 2932 | − pr_warning("print interval < 100ms. " | |
| 2933 | − "The overhead percentage could be high in some cases. " | |
| 2934 | − "Please proceed with caution.\n"); | |
| 2935 | − } | |
| 2936 | − | |
| 2937 | 2927 | if (stat_config.times && interval) |
| 2938 | 2928 | interval_count = true; |
| 2939 | 2929 | else if (stat_config.times && !interval) { |
| @@ -60,7 +60,10 @@ static void library_status(void) · 59 unmodified lines | ||
| 60 | 60 | STATUS(HAVE_DWARF_GETLOCATIONS_SUPPORT, dwarf_getlocations); |
| 61 | 61 | STATUS(HAVE_GLIBC_SUPPORT, glibc); |
| 62 | 62 | STATUS(HAVE_GTK2_SUPPORT, gtk2); |
| 63 | +#ifndef HAVE_SYSCALL_TABLE_SUPPORT | |
| 63 | 64 | STATUS(HAVE_LIBAUDIT_SUPPORT, libaudit); |
| 65 | +#endif | |
| 66 | + STATUS(HAVE_SYSCALL_TABLE_SUPPORT, syscall_table); | |
| 64 | 67 | STATUS(HAVE_LIBBFD_SUPPORT, libbfd); |
| 65 | 68 | STATUS(HAVE_LIBELF_SUPPORT, libelf); |
| 66 | 69 | STATUS(HAVE_LIBNUMA_SUPPORT, libnuma); |
| @@ -73,7 +73,7 @@ static struct cmd_struct commands[] = { · 72 unmodified lines | ||
| 73 | 73 | { "lock", cmd_lock, 0 }, |
| 74 | 74 | { "kvm", cmd_kvm, 0 }, |
| 75 | 75 | { "test", cmd_test, 0 }, |
| 76 | −#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE) | |
| 76 | +#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT) | |
| 77 | 77 | { "trace", cmd_trace, 0 }, |
| 78 | 78 | #endif |
| 79 | 79 | { "inject", cmd_inject, 0 }, |
| @@ -491,7 +491,7 @@ int main(int argc, const char **argv) · 411 unmodified lines | ||
| 491 | 491 | argv[0] = cmd; |
| 492 | 492 | } |
| 493 | 493 | if (strstarts(cmd, "trace")) { |
| 494 | −#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE) | |
| 494 | +#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT) | |
| 495 | 495 | setup_path(); |
| 496 | 496 | argv[0] = "trace"; |
| 497 | 497 | return cmd_trace(argc, argv); |
| @@ -9,7 +9,6 @@ · 8 unmodified lines | ||
| 9 | 9 | #define SEC(NAME) __attribute__((section(NAME), used)) |
| 10 | 10 | |
| 11 | 11 | #include <uapi/linux/fs.h> |
| 12 | −#include <uapi/asm/ptrace.h> | |
| 13 | 12 | |
| 14 | 13 | SEC("func=vfs_llseek") |
| 15 | 14 | int bpf_func__vfs_llseek(void *ctx) |
| @@ -118,6 +118,7 @@ static struct test generic_tests[] = { · 117 unmodified lines | ||
| 118 | 118 | { |
| 119 | 119 | .desc = "Breakpoint accounting", |
| 120 | 120 | .func = test__bp_accounting, |
| 121 | + .is_supported = test__bp_signal_is_supported, | |
| 121 | 122 | }, |
| 122 | 123 | { |
| 123 | 124 | .desc = "Number of exit events of a simple workload", |
| @@ -692,6 +692,7 @@ static int annotate_browser__run(struct annotate_browser *browser, · 691 unmodified lines | ||
| 692 | 692 | "J Toggle showing number of jump sources on targets\n" |
| 693 | 693 | "n Search next string\n" |
| 694 | 694 | "o Toggle disassembler output/simplified view\n" |
| 695 | + "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n" | |
| 695 | 696 | "s Toggle source code view\n" |
| 696 | 697 | "t Circulate percent, total period, samples view\n" |
| 697 | 698 | "/ Search string\n" |
| @@ -719,6 +720,10 @@ static int annotate_browser__run(struct annotate_browser *browser, · 21 unmodified lines | ||
| 719 | 720 | notes->options->use_offset = !notes->options->use_offset; |
| 720 | 721 | annotation__update_column_widths(notes); |
| 721 | 722 | continue; |
| 723 | + case 'O': | |
| 724 | + if (++notes->options->offset_level > ANNOTATION__MAX_OFFSET_LEVEL) | |
| 725 | + notes->options->offset_level = ANNOTATION__MIN_OFFSET_LEVEL; | |
| 726 | + continue; | |
| 722 | 727 | case 'j': |
| 723 | 728 | notes->options->jump_arrows = !notes->options->jump_arrows; |
| 724 | 729 | continue; |
| @@ -46,6 +46,7 @@ · 45 unmodified lines | ||
| 46 | 46 | struct annotation_options annotation__default_options = { |
| 47 | 47 | .use_offset = true, |
| 48 | 48 | .jump_arrows = true, |
| 49 | + .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS, | |
| 49 | 50 | }; |
| 50 | 51 | |
| 51 | 52 | const char *disassembler_style; |
| @@ -2512,7 +2513,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati · 2460 unmodified lines | ||
| 2512 | 2513 | if (!notes->options->use_offset) { |
| 2513 | 2514 | printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr); |
| 2514 | 2515 | } else { |
| 2515 | − if (al->jump_sources) { | |
| 2516 | + if (al->jump_sources && | |
| 2517 | + notes->options->offset_level >= ANNOTATION__OFFSET_JUMP_TARGETS) { | |
| 2516 | 2518 | if (notes->options->show_nr_jumps) { |
| 2517 | 2519 | int prev; |
| 2518 | 2520 | printed = scnprintf(bf, sizeof(bf), "%*d ", |
| @@ -2523,9 +2525,14 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati · 4 unmodified lines | ||
| 2523 | 2525 | obj__printf(obj, bf); |
| 2524 | 2526 | obj__set_color(obj, prev); |
| 2525 | 2527 | } |
| 2526 | − | |
| 2528 | +print_addr: | |
| 2527 | 2529 | printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ", |
| 2528 | 2530 | notes->widths.target, addr); |
| 2531 | + } else if (ins__is_call(&disasm_line(al)->ins) && | |
| 2532 | + notes->options->offset_level >= ANNOTATION__OFFSET_CALL) { | |
| 2533 | + goto print_addr; | |
| 2534 | + } else if (notes->options->offset_level == ANNOTATION__MAX_OFFSET_LEVEL) { | |
| 2535 | + goto print_addr; | |
| 2529 | 2536 | } else { |
| 2530 | 2537 | printed = scnprintf(bf, sizeof(bf), "%-*s ", |
| 2531 | 2538 | notes->widths.addr, " "); |
| @@ -2642,10 +2649,11 @@ int __annotation__scnprintf_samples_period(struct annotation *notes, · 110 unmodified lines | ||
| 2642 | 2649 | */ |
| 2643 | 2650 | static struct annotation_config { |
| 2644 | 2651 | const char *name; |
| 2645 | − bool *value; | |
| 2652 | + void *value; | |
| 2646 | 2653 | } annotation__configs[] = { |
| 2647 | 2654 | ANNOTATION__CFG(hide_src_code), |
| 2648 | 2655 | ANNOTATION__CFG(jump_arrows), |
| 2656 | + ANNOTATION__CFG(offset_level), | |
| 2649 | 2657 | ANNOTATION__CFG(show_linenr), |
| 2650 | 2658 | ANNOTATION__CFG(show_nr_jumps), |
| 2651 | 2659 | ANNOTATION__CFG(show_nr_samples), |
| @@ -2677,8 +2685,16 @@ static int annotation__config(const char *var, const char *value, · 25 unmodified lines | ||
| 2677 | 2685 | |
| 2678 | 2686 | if (cfg == NULL) |
| 2679 | 2687 | pr_debug("%s variable unknown, ignoring...", var); |
| 2680 | − else | |
| 2681 | − *cfg->value = perf_config_bool(name, value); | |
| 2688 | + else if (strcmp(var, "annotate.offset_level") == 0) { | |
| 2689 | + perf_config_int(cfg->value, name, value); | |
| 2690 | + | |
| 2691 | + if (*(int *)cfg->value > ANNOTATION__MAX_OFFSET_LEVEL) | |
| 2692 | + *(int *)cfg->value = ANNOTATION__MAX_OFFSET_LEVEL; | |
| 2693 | + else if (*(int *)cfg->value < ANNOTATION__MIN_OFFSET_LEVEL) | |
| 2694 | + *(int *)cfg->value = ANNOTATION__MIN_OFFSET_LEVEL; | |
| 2695 | + } else { | |
| 2696 | + *(bool *)cfg->value = perf_config_bool(name, value); | |
| 2697 | + } | |
| 2682 | 2698 | return 0; |
| 2683 | 2699 | } |
| 2684 | 2700 | |
| @@ -70,8 +70,17 @@ struct annotation_options { · 69 unmodified lines | ||
| 70 | 70 | show_nr_jumps, |
| 71 | 71 | show_nr_samples, |
| 72 | 72 | show_total_period; |
| 73 | + u8 offset_level; | |
| 73 | 74 | }; |
| 74 | 75 | |
| 76 | +enum { | |
| 77 | + ANNOTATION__OFFSET_JUMP_TARGETS = 1, | |
| 78 | + ANNOTATION__OFFSET_CALL, | |
| 79 | + ANNOTATION__MAX_OFFSET_LEVEL, | |
| 80 | +}; | |
| 81 | + | |
| 82 | +#define ANNOTATION__MIN_OFFSET_LEVEL ANNOTATION__OFFSET_JUMP_TARGETS | |
| 83 | + | |
| 75 | 84 | extern struct annotation_options annotation__default_options; |
| 76 | 85 | |
| 77 | 86 | struct annotation; |
| @@ -38,7 +38,7 @@ do · 37 unmodified lines | ||
| 38 | 38 | done |
| 39 | 39 | echo "#endif /* HAVE_LIBELF_SUPPORT */" |
| 40 | 40 | |
| 41 | −echo "#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE)" | |
| 41 | +echo "#if defined(HAVE_LIBAUDIT_SUPPORT) || defined(HAVE_SYSCALL_TABLE_SUPPORT)" | |
| 42 | 42 | sed -n -e 's/^perf-\([^ ]*\)[ ].* audit*/\1/p' command-list.txt | |
| 43 | 43 | sort | |
| 44 | 44 | while read cmd |
| @@ -1320,7 +1320,8 @@ static int build_mem_topology(struct memory_node *nodes, u64 size, u64 *cntp) · 1319 unmodified lines | ||
| 1320 | 1320 | |
| 1321 | 1321 | dir = opendir(path); |
| 1322 | 1322 | if (!dir) { |
| 1323 | − pr_warning("failed: can't open node sysfs data\n"); | |
| 1323 | + pr_debug2("%s: could't read %s, does this arch have topology information?\n", | |
| 1324 | + __func__, path); | |
| 1324 | 1325 | return -1; |
| 1325 | 1326 | } |
| 1326 | 1327 | |
| @@ -2091,16 +2091,14 @@ static bool symbol__read_kptr_restrict(void) · 2090 unmodified lines | ||
| 2091 | 2091 | |
| 2092 | 2092 | int symbol__annotation_init(void) |
| 2093 | 2093 | { |
| 2094 | + if (symbol_conf.init_annotation) | |
| 2095 | + return 0; | |
| 2096 | + | |
| 2094 | 2097 | if (symbol_conf.initialized) { |
| 2095 | 2098 | pr_err("Annotation needs to be init before symbol__init()\n"); |
| 2096 | 2099 | return -1; |
| 2097 | 2100 | } |
| 2098 | 2101 | |
| 2099 | − if (symbol_conf.init_annotation) { | |
| 2100 | − pr_warning("Annotation being initialized multiple times\n"); | |
| 2101 | − return 0; | |
| 2102 | − } | |
| 2103 | − | |
| 2104 | 2102 | symbol_conf.priv_size += sizeof(struct annotation); |
| 2105 | 2103 | symbol_conf.init_annotation = true; |
| 2106 | 2104 | return 0; |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <stdlib.h> |
| 18 | 18 | #include <linux/compiler.h> |
| 19 | 19 | |
| 20 | −#ifdef HAVE_SYSCALL_TABLE | |
| 20 | +#ifdef HAVE_SYSCALL_TABLE_SUPPORT | |
| 21 | 21 | #include <string.h> |
| 22 | 22 | #include "string2.h" |
| 23 | 23 | #include "util.h" |
| @@ -139,7 +139,7 @@ int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_g · 115 unmodified lines | ||
| 139 | 139 | return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx); |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | −#else /* HAVE_SYSCALL_TABLE */ | |
| 142 | +#else /* HAVE_SYSCALL_TABLE_SUPPORT */ | |
| 143 | 143 | |
| 144 | 144 | #include <libaudit.h> |
| 145 | 145 | |
| @@ -176,4 +176,4 @@ int syscalltbl__strglobmatch_first(struct syscalltbl *tbl, const char *syscall_g · 30 unmodified lines | ||
| 176 | 176 | { |
| 177 | 177 | return syscalltbl__strglobmatch_next(tbl, syscall_glob, idx); |
| 178 | 178 | } |
| 179 | −#endif /* HAVE_SYSCALL_TABLE */ | |
| 179 | +#endif /* HAVE_SYSCALL_TABLE_SUPPORT */ | |
| @@ -98,7 +98,7 @@ static void register_python_scripting(struct scripting_ops *scripting_ops) · 97 unmodified lines | ||
| 98 | 98 | } |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | −#ifdef NO_LIBPYTHON | |
| 101 | +#ifndef HAVE_LIBPYTHON_SUPPORT | |
| 102 | 102 | void setup_python_scripting(void) |
| 103 | 103 | { |
| 104 | 104 | register_python_scripting(&python_scripting_unsupported_ops); |
| @@ -161,7 +161,7 @@ static void register_perl_scripting(struct scripting_ops *scripting_ops) · 56 unmodified lines | ||
| 161 | 161 | } |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | −#ifdef NO_LIBPERL | |
| 164 | +#ifndef HAVE_LIBPERL_SUPPORT | |
| 165 | 165 | void setup_perl_scripting(void) |
| 166 | 166 | { |
| 167 | 167 | register_perl_scripting(&perl_scripting_unsupported_ops); |