diff options
author | Ingo Molnar <mingo@kernel.org> | 2017-06-20 11:49:08 +0300 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-06-20 11:49:08 +0300 |
commit | 007b811b4041989ec2dc91b9614aa2c41332723e (patch) | |
tree | 34ba98f00635fea2d0f3087e8859afe7b83e74d0 /tools | |
parent | 2eb0fc9bfe7485fec16030b85ff586e7aaea2b6f (diff) | |
parent | dfe1c6d7efa8ead6878b73216d4c891a28207528 (diff) | |
download | linux-007b811b4041989ec2dc91b9614aa2c41332723e.tar.xz |
Merge tag 'perf-core-for-mingo-4.13-20170719' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
User visible changes:
- Allow adding and removing fields to the default 'perf script' columns,
using + or - as field prefixes to do so (Andi Kleen)
- Display titles in left frame in the annotate browser (Jin Yao)
- Allow resolving the DSO name with 'perf script -F brstack{sym,off},dso'
(Mark Santaniello)
- Support function filtering in 'perf ftrace' (Namhyung Kim)
- Allow specifying function call depth in 'perf ftrace' (Namhyumg Kim)
Infrastructure changes:
- Adopt __noreturn, __printf, __scanf, noinline, __packed and __aligned
__alignment__(()) markers, to make the tools/ source code base to be
more compact and look more like kernel code (Arnaldo Carvalho de Melo)
- Remove unnecessary check in annotate_browser_write() (Jin Yao)
- Return arch from symbol__disassemble() so that callers, such as
the annotate TUI browser to use arch specific formattings, such
as the upcoming instruction micro-op fusion on Intel Core (Jin Yao)
- Remove superfluous check before use in the coresight code base (Kim
Phillips)
- Remove unused SAMPLE_SIZE defines and BTS priv array (Kim Phillips)
- Error handling fix/tidy ups in 'perf config' (Taeung Song)
- Avoid error in the BPF proggie built with clang in 'perf test llvm'
when PROFILE_ALL_BRANCHES is set (Wang Nan)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
37 files changed, 496 insertions, 161 deletions
diff --git a/tools/include/linux/compiler-gcc.h b/tools/include/linux/compiler-gcc.h index 825d44f89a29..bd39b2090ad1 100644 --- a/tools/include/linux/compiler-gcc.h +++ b/tools/include/linux/compiler-gcc.h @@ -19,3 +19,13 @@ /* &a[0] degrades to a pointer: a different type from an array */ #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) + +#define noinline __attribute__((noinline)) + +#define __packed __attribute__((packed)) + +#define __noreturn __attribute__((noreturn)) + +#define __aligned(x) __attribute__((aligned(x))) +#define __printf(a, b) __attribute__((format(printf, a, b))) +#define __scanf(a, b) __attribute__((format(scanf, a, b))) diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h index 23299d7e7160..8b129e314c7e 100644 --- a/tools/include/linux/compiler.h +++ b/tools/include/linux/compiler.h @@ -17,6 +17,10 @@ # define __always_inline inline __attribute__((always_inline)) #endif +#ifndef noinline +#define noinline +#endif + /* Are two types/vars the same type (ignoring qualifiers)? */ #ifndef __same_type # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) diff --git a/tools/perf/Documentation/perf-ftrace.txt b/tools/perf/Documentation/perf-ftrace.txt index 6e6a8b22c859..721a447f046e 100644 --- a/tools/perf/Documentation/perf-ftrace.txt +++ b/tools/perf/Documentation/perf-ftrace.txt @@ -48,6 +48,39 @@ OPTIONS Ranges of CPUs are specified with -: 0-2. Default is to trace on all online CPUs. +-T:: +--trace-funcs=:: + Only trace functions given by the argument. Multiple functions + can be given by using this option more than once. The function + argument also can be a glob pattern. It will be passed to + 'set_ftrace_filter' in tracefs. + +-N:: +--notrace-funcs=:: + Do not trace functions given by the argument. Like -T option, + this can be used more than once to specify multiple functions + (or glob patterns). It will be passed to 'set_ftrace_notrace' + in tracefs. + +-G:: +--graph-funcs=:: + Set graph filter on the given function (or a glob pattern). + This is useful for the function_graph tracer only and enables + tracing for functions executed from the given function. + This can be used more than once to specify multiple functions. + It will be passed to 'set_graph_function' in tracefs. + +-g:: +--nograph-funcs=:: + Set graph notrace filter on the given function (or a glob pattern). + Like -G option, this is useful for the function_graph tracer only + and disables tracing for function executed from the given function. + This can be used more than once to specify multiple functions. + It will be passed to 'set_graph_notrace' in tracefs. + +-D:: +--graph-depth=:: + Set max depth for function graph tracer to follow SEE ALSO -------- diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 3517e204a2b3..e2468ed6a307 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -116,7 +116,7 @@ OPTIONS --fields:: Comma separated list of fields to print. Options are: comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, - srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn, + srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn, brstackoff, callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw, to indicate to which event type the field list applies. e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace @@ -130,6 +130,14 @@ OPTIONS i.e., the specified fields apply to all event types if the type string is not given. + In addition to overriding fields, it is also possible to add or remove + fields from the defaults. For example + + -F -cpu,+insn + + removes the cpu field and adds the insn field. Adding/removing fields + cannot be mixed with normal overriding. + The arguments are processed in the order received. A later usage can reset a prior request. e.g.: @@ -203,6 +211,8 @@ OPTIONS is printed. This is the full execution path leading to the sample. This is only supported when the sample was recorded with perf record -b or -j any. + The brstackoff field will print an offset into a specific dso/binary. + -k:: --vmlinux=<file>:: vmlinux pathname diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index 29361d9b635a..7ce3d1a25133 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -17,6 +17,7 @@ #include <api/fs/fs.h> #include <linux/bitops.h> +#include <linux/compiler.h> #include <linux/coresight-pmu.h> #include <linux/kernel.h> #include <linux/log2.h> @@ -202,19 +203,18 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME, opts->auxtrace_snapshot_size); - if (cs_etm_evsel) { - /* - * To obtain the auxtrace buffer file descriptor, the auxtrace - * event must come first. - */ - perf_evlist__to_front(evlist, cs_etm_evsel); - /* - * In the case of per-cpu mmaps, we need the CPU on the - * AUX event. - */ - if (!cpu_map__empty(cpus)) - perf_evsel__set_sample_bit(cs_etm_evsel, CPU); - } + /* + * To obtain the auxtrace buffer file descriptor, the auxtrace + * event must come first. + */ + perf_evlist__to_front(evlist, cs_etm_evsel); + + /* + * In the case of per-cpu mmaps, we need the CPU on the + * AUX event. + */ + if (!cpu_map__empty(cpus)) + perf_evsel__set_sample_bit(cs_etm_evsel, CPU); /* Add dummy event to keep tracking */ if (opts->full_auxtrace) { @@ -583,8 +583,7 @@ static FILE *cs_device__open_file(const char *name) } -static __attribute__((format(printf, 2, 3))) -int cs_device__print_file(const char *name, const char *fmt, ...) +static int __printf(2, 3) cs_device__print_file(const char *name, const char *fmt, ...) { va_list args; FILE *file; diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index af2bce7a2cd6..781df40b2966 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -35,10 +35,6 @@ #define KiB_MASK(x) (KiB(x) - 1) #define MiB_MASK(x) (MiB(x) - 1) -#define INTEL_BTS_DFLT_SAMPLE_SIZE KiB(4) - -#define INTEL_BTS_MAX_SAMPLE_SIZE KiB(60) - struct intel_bts_snapshot_ref { void *ref_buf; size_t ref_offset; diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index f630de0206a1..6fe667b3269e 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -40,10 +40,6 @@ #define KiB_MASK(x) (KiB(x) - 1) #define MiB_MASK(x) (MiB(x) - 1) -#define INTEL_PT_DEFAULT_SAMPLE_SIZE KiB(4) - -#define INTEL_PT_MAX_SAMPLE_SIZE KiB(60) - #define INTEL_PT_PSB_PERIOD_NEAR 256 struct intel_pt_snapshot_ref { diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c index 27de0c8c5c19..469d65b21122 100644 --- a/tools/perf/bench/numa.c +++ b/tools/perf/bench/numa.c @@ -700,7 +700,7 @@ static inline uint32_t lfsr_32(uint32_t lfsr) * kernel (KSM, zero page, etc.) cannot optimize away RAM * accesses: */ -static inline u64 access_data(u64 *data __attribute__((unused)), u64 val) +static inline u64 access_data(u64 *data, u64 val) { if (g->p.data_reads) val += *data; diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index 80668fa7556e..ece45582a48d 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c @@ -156,7 +156,7 @@ static int parse_config_arg(char *arg, char **var, char **value) int cmd_config(int argc, const char **argv) { - int i, ret = 0; + int i, ret = -1; struct perf_config_set *set; char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); const char *config_filename; @@ -186,10 +186,8 @@ int cmd_config(int argc, const char **argv) * because of reinitializing with options config file location. */ set = perf_config_set__new(); - if (!set) { - ret = -1; + if (!set) goto out_err; - } switch (actions) { case ACTION_LIST: @@ -197,41 +195,54 @@ int cmd_config(int argc, const char **argv) pr_err("Error: takes no arguments\n"); parse_options_usage(config_usage, config_options, "l", 1); } else { - ret = show_config(set); - if (ret < 0) + if (show_config(set) < 0) { pr_err("Nothing configured, " "please check your %s \n", config_filename); + goto out_err; + } } break; default: - if (argc) { - for (i = 0; argv[i]; i++) { - char *var, *value; - char *arg = strdup(argv[i]); - - if (!arg) { - pr_err("%s: strdup failed\n", __func__); - ret = -1; - break; - } + if (!argc) { + usage_with_options(config_usage, config_options); + break; + } - if (parse_config_arg(arg, &var, &value) < 0) { - free(arg); - ret = -1; - break; - } + for (i = 0; argv[i]; i++) { + char *var, *value; + char *arg = strdup(argv[i]); + + if (!arg) { + pr_err("%s: strdup failed\n", __func__); + goto out_err; + } - if (value == NULL) - ret = show_spec_config(set, var); - else - ret = set_config(set, config_filename, var, value); + if (parse_config_arg(arg, &var, &value) < 0) { free(arg); + goto out_err; } - } else - usage_with_options(config_usage, config_options); + + if (value == NULL) { + if (show_spec_config(set, var) < 0) { + pr_err("%s is not configured: %s\n", + var, config_filename); + free(arg); + goto out_err; + } + } else { + if (set_config(set, config_filename, var, value) < 0) { + pr_err("Failed to set '%s=%s' on %s\n", + var, value, config_filename); + free(arg); + goto out_err; + } + } + free(arg); + } } - perf_config_set__delete(set); + ret = 0; out_err: + perf_config_set__delete(set); return ret; } diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 9e0b35cd0eea..dd26c62c9893 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -28,9 +28,19 @@ #define DEFAULT_TRACER "function_graph" struct perf_ftrace { - struct perf_evlist *evlist; - struct target target; - const char *tracer; + struct perf_evlist *evlist; + struct target target; + const char *tracer; + struct list_head filters; + struct list_head notrace; + struct list_head graph_funcs; + struct list_head nograph_funcs; + int graph_depth; +}; + +struct filter_entry { + struct list_head list; + char name[]; }; static bool done; @@ -61,6 +71,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append) int fd, ret = -1; ssize_t size = strlen(val); int flags = O_WRONLY; + char errbuf[512]; file = get_tracing_file(name); if (!file) { @@ -75,14 +86,16 @@ static int __write_tracing_file(const char *name, const char *val, bool append) fd = open(file, flags); if (fd < 0) { - pr_debug("cannot open tracing file: %s\n", name); + pr_debug("cannot open tracing file: %s: %s\n", + name, str_error_r(errno, errbuf, sizeof(errbuf))); goto out; } if (write(fd, val, size) == size) ret = 0; else - pr_debug("write '%s' to tracing/%s failed\n", val, name); + pr_debug("write '%s' to tracing/%s failed: %s\n", + val, name, str_error_r(errno, errbuf, sizeof(errbuf))); close(fd); out: @@ -101,6 +114,7 @@ static int append_tracing_file(const char *name, const char *val) } static int reset_tracing_cpu(void); +static void reset_tracing_filters(void); static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused) { @@ -116,6 +130,10 @@ static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused) if (reset_tracing_cpu() < 0) return -1; + if (write_tracing_file("max_graph_depth", "0") < 0) + return -1; + + reset_tracing_filters(); return 0; } @@ -181,6 +199,68 @@ static int reset_tracing_cpu(void) return ret; } +static int __set_tracing_filter(const char *filter_file, struct list_head *funcs) +{ + struct filter_entry *pos; + + list_for_each_entry(pos, funcs, list) { + if (append_tracing_file(filter_file, pos->name) < 0) + return -1; + } + + return 0; +} + +static int set_tracing_filters(struct perf_ftrace *ftrace) +{ + int ret; + + ret = __set_tracing_filter("set_ftrace_filter", &ftrace->filters); + if (ret < 0) + return ret; + + ret = __set_tracing_filter("set_ftrace_notrace", &ftrace->notrace); + if (ret < 0) + return ret; + + ret = __set_tracing_filter("set_graph_function", &ftrace->graph_funcs); + if (ret < 0) + return ret; + + /* old kernels do not have this filter */ + __set_tracing_filter("set_graph_notrace", &ftrace->nograph_funcs); + + return ret; +} + +static void reset_tracing_filters(void) +{ + write_tracing_file("set_ftrace_filter", " "); + write_tracing_file("set_ftrace_notrace", " "); + write_tracing_file("set_graph_function", " "); + write_tracing_file("set_graph_notrace", " "); +} + +static int set_tracing_depth(struct perf_ftrace *ftrace) +{ + char buf[16]; + + if (ftrace->graph_depth == 0) + return 0; + + if (ftrace->graph_depth < 0) { + pr_err("invalid graph depth: %d\n", ftrace->graph_depth); + return -1; + } + + snprintf(buf, sizeof(buf), "%d", ftrace->graph_depth); + + if (write_tracing_file("max_graph_depth", buf) < 0) + return -1; + + return 0; +} + static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv) { char *trace_file; @@ -223,11 +303,23 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv) goto out_reset; } + if (set_tracing_filters(ftrace) < 0) { + pr_err("failed to set tracing filters\n"); + goto out_reset; + } + + if (set_tracing_depth(ftrace) < 0) { + pr_err("failed to set graph depth\n"); + goto out_reset; + } + if (write_tracing_file("current_tracer", ftrace->tracer) < 0) { pr_err("failed to set current_tracer to %s\n", ftrace->tracer); goto out_reset; } + setup_pager(); + trace_file = get_tracing_file("trace_pipe"); if (!trace_file) { pr_err("failed to open trace_pipe\n"); @@ -251,8 +343,6 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv) goto out_close_fd; } - setup_pager(); - perf_evlist__start_workload(ftrace->evlist); while (!done) { @@ -307,6 +397,32 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb) return -1; } +static int parse_filter_func(const struct option *opt, const char *str, + int unset __maybe_unused) +{ + struct list_head *head = opt->value; + struct filter_entry *entry; + + entry = malloc(sizeof(*entry) + strlen(str) + 1); + if (entry == NULL) + return -ENOMEM; + + strcpy(entry->name, str); + list_add_tail(&entry->list, head); + + return 0; +} + +static void delete_filter_func(struct list_head *head) +{ + struct filter_entry *pos, *tmp; + + list_for_each_entry_safe(pos, tmp, head, list) { + list_del(&pos->list); + free(pos); + } +} + int cmd_ftrace(int argc, const char **argv) { int ret; @@ -330,9 +446,24 @@ int cmd_ftrace(int argc, const char **argv) "system-wide collection from all CPUs"), OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu", "list of cpus to monitor"), + OPT_CALLBACK('T', "trace-funcs", &ftrace.filters, "func", + "trace given functions only", parse_filter_func), + OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func", + "do not trace given functions", parse_filter_func), + OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func", + "Set graph filter on given functions", parse_filter_func), + OPT_CALLBACK('g', "nograph-funcs", &ftrace.nograph_funcs, "func", + "Set nograph filter on given functions", parse_filter_func), + OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth, + "Max depth for function graph tracer"), OPT_END() }; + INIT_LIST_HEAD(&ftrace.filters); + INIT_LIST_HEAD(&ftrace.notrace); + INIT_LIST_HEAD(&ftrace.graph_funcs); + INIT_LIST_HEAD(&ftrace.nograph_funcs); + ret = perf_config(perf_ftrace_config, &ftrace); if (ret < 0) return -1; @@ -348,12 +479,14 @@ int cmd_ftrace(int argc, const char **argv) target__strerror(&ftrace.target, ret, errbuf, 512); pr_err("%s\n", errbuf); - return -EINVAL; + goto out_delete_filters; } ftrace.evlist = perf_evlist__new(); - if (ftrace.evlist == NULL) - return -ENOMEM; + if (ftrace.evlist == NULL) { + ret = -ENOMEM; + goto out_delete_filters; + } ret = perf_evlist__create_maps(ftrace.evlist, &ftrace.target); if (ret < 0) @@ -364,5 +497,11 @@ int cmd_ftrace(int argc, const char **argv) out_delete_evlist: perf_evlist__delete(ftrace.evlist); +out_delete_filters: + delete_filter_func(&ftrace.filters); + delete_filter_func(&ftrace.notrace); + delete_filter_func(&ftrace.graph_funcs); + delete_filter_func(&ftrace.nograph_funcs); + return ret; } diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 4761b0d7fcb5..db5261c3f719 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -85,6 +85,7 @@ enum perf_output_field { PERF_OUTPUT_INSN = 1U << 21, PERF_OUTPUT_INSNLEN = 1U << 22, PERF_OUTPUT_BRSTACKINSN = 1U << 23, + PERF_OUTPUT_BRSTACKOFF = 1U << 24, }; struct output_option { @@ -115,6 +116,7 @@ struct output_option { {.str = "insn", .field = PERF_OUTPUT_INSN}, {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN}, {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, + {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, }; /* default set to maintain compatibility with current format */ @@ -298,10 +300,10 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, "selected.\n"); return -EINVAL; } - if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { - pr_err("Display of DSO requested but neither sample IP nor " - "sample address\nis selected. Hence, no addresses to convert " - "to DSO.\n"); + if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR) && + !PRINT_FIELD(BRSTACK) && !PRINT_FIELD(BRSTACKSYM) && !PRINT_FIELD(BRSTACKOFF)) { + pr_err("Display of DSO requested but no address to convert. Select\n" + "sample IP, sample address, brstack, brstacksym, or brstackoff.\n"); return -EINVAL; } if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { @@ -514,18 +516,43 @@ mispred_str(struct branch_entry *br) return br->flags.predicted ? 'P' : 'M'; } -static void print_sample_brstack(struct perf_sample *sample) +static void print_sample_brstack(struct perf_sample *sample, + struct thread *thread, + struct perf_event_attr *attr) { struct branch_stack *br = sample->branch_stack; - u64 i; + struct addr_location alf, alt; + u64 i, from, to; if (!(br && br->nr)) return; for (i = 0; i < br->nr; i++) { - printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ", - br->entries[i].from, - br->entries[i].to, + from = br->entries[i].from; + to = br->entries[i].to; + + if (PRINT_FIELD(DSO)) { + memset(&alf, 0, sizeof(alf)); + memset(&alt, 0, sizeof(alt)); + thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); + thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); + } + + printf("0x%"PRIx64, from); + if (PRINT_FIELD(DSO)) { + printf("("); + map__fprintf_dsoname(alf.map, stdout); + printf(")"); + } + + printf("/0x%"PRIx64, to); + if (PRINT_FIELD(DSO)) { + printf("("); + map__fprintf_dsoname(alt.map, stdout); + printf(")"); + } + + printf("/%c/%c/%c/%d ", mispred_str( br->entries + i), br->entries[i].flags.in_tx? 'X' : '-', br->entries[i].flags.abort? 'A' : '-', @@ -534,7 +561,8 @@ static void print_sample_brstack(struct perf_sample *sample) } static void print_sample_brstacksym(struct perf_sample *sample, - struct thread *thread) + struct thread *thread, + struct perf_event_attr *attr) { struct branch_stack *br = sample->branch_stack; struct addr_location alf, alt; @@ -559,8 +587,18 @@ static void print_sample_brstacksym(struct perf_sample *sample, alt.sym = map__find_symbol(alt.map, alt.addr); symbol__fprintf_symname_offs(alf.sym, &alf, stdout); + if (PRINT_FIELD(DSO)) { + printf("("); + map__fprintf_dsoname(alf.map, stdout); + printf(")"); + } putchar('/'); symbol__fprintf_symname_offs(alt.sym, &alt, stdout); + if (PRINT_FIELD(DSO)) { + printf("("); + map__fprintf_dsoname(alt.map, stdout); + printf(")"); + } printf("/%c/%c/%c/%d ", mispred_str( br->entries + i), br->entries[i].flags.in_tx? 'X' : '-', @@ -569,6 +607,51 @@ static void print_sample_brstacksym(struct perf_sample *sample, } } +static void print_sample_brstackoff(struct perf_sample *sample, + struct thread *thread, + struct perf_event_attr *attr) +{ + struct branch_stack *br = sample->branch_stack; + struct addr_location alf, alt; + u64 i, from, to; + + if (!(br && br->nr)) + return; + + for (i = 0; i < br->nr; i++) { + + memset(&alf, 0, sizeof(alf)); + memset(&alt, 0, sizeof(alt)); + from = br->entries[i].from; + to = br->entries[i].to; + + thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); + if (alf.map && !alf.map->dso->adjust_symbols) + from = map__map_ip(alf.map, from); + + thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); + if (alt.map && !alt.map->dso->adjust_symbols) + to = map__map_ip(alt.map, to); + + printf("0x%"PRIx64, from); + if (PRINT_FIELD(DSO)) { + printf("("); + map__fprintf_dsoname(alf.map, stdout); + printf(")"); + } + printf("/0x%"PRIx64, to); + if (PRINT_FIELD(DSO)) { + printf("("); + map__fprintf_dsoname(alt.map, stdout); + printf(")"); + } + printf("/%c/%c/%c/%d ", + mispred_str(br->entries + i), + br->entries[i].flags.in_tx ? 'X' : '-', + br->entries[i].flags.abort ? 'A' : '-', + br->entries[i].flags.cycles); + } +} #define MAXBB 16384UL static int grab_bb(u8 *buffer, u64 start, u64 end, @@ -1187,9 +1270,11 @@ static void process_event(struct perf_script *script, print_sample_iregs(sample, attr); if (PRINT_FIELD(BRSTACK)) - print_sample_brstack(sample); + print_sample_brstack(sample, thread, attr); else if (PRINT_FIELD(BRSTACKSYM)) - print_sample_brstacksym(sample, thread); + print_sample_brstacksym(sample, thread, attr); + else if (PRINT_FIELD(BRSTACKOFF)) + print_sample_brstackoff(sample, thread, attr); if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) print_sample_bpf_output(sample); @@ -1727,6 +1812,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused, int rc = 0; char *str = strdup(arg); int type = -1; + enum { DEFAULT, SET, ADD, REMOVE } change = DEFAULT; if (!str) return -ENOMEM; @@ -1772,6 +1858,10 @@ static int parse_output_fields(const struct option *opt __maybe_unused, goto out; } + /* Don't override defaults for +- */ + if (strchr(str, '+') || strchr(str, '-')) + goto parse; + if (output_set_by_user()) pr_warning("Overriding previous field request for all events.\n"); @@ -1782,13 +1872,30 @@ static int parse_output_fields(const struct option *opt __maybe_unused, } } +parse: for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) { + if (*tok == '+') { + if (change == SET) + goto out_badmix; + change = ADD; + tok++; + } else if (*tok == '-') { + if (change == SET) + goto out_badmix; + change = REMOVE; + tok++; + } else { + if (change != SET && change != DEFAULT) + goto out_badmix; + change = SET; + } + for (i = 0; i < imax; ++i) { if (strcmp(tok, all_output_options[i].str) == 0) break; } if (i == imax && strcmp(tok, "flags") == 0) { - print_flags = true; + print_flags = change == REMOVE ? false : true; continue; } if (i == imax) { @@ -1805,8 +1912,12 @@ static int parse_output_fields(const struct option *opt __maybe_unused, if (output[j].invalid_fields & all_output_options[i].field) { pr_warning("\'%s\' not valid for %s events. Ignoring.\n", all_output_options[i].str, event_type(j)); - } else - output[j].fields |= all_output_options[i].field; + } else { + if (change == REMOVE) + output[j].fields &= ~all_output_options[i].field; + else + output[j].fields |= all_output_options[i].field; + } } } else { if (output[type].invalid_fields & all_output_options[i].field) { @@ -1826,7 +1937,11 @@ static int parse_output_fields(const struct option *opt __maybe_unused, "Events will not be displayed.\n", event_type(type)); } } + goto out; +out_badmix: + fprintf(stderr, "Cannot mix +-field with overridden fields\n"); + rc = -EINVAL; out: free(str); return rc; @@ -2444,6 +2559,7 @@ int cmd_script(int argc, const char **argv) symbol__config_symfs), OPT_CALLBACK('F', "fields", NULL, "str", "comma separated output fields prepend with 'type:'. " + "+field to add and -field to remove." "Valid types: hw,sw,trace,raw. " "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," "addr,symoff,period,iregs,brstack,brstacksym,flags," diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 10b6362ca0bf..2bcfa46913c8 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -134,7 +134,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) return err; } - err = symbol__disassemble(sym, map, NULL, 0); + err = symbol__disassemble(sym, map, NULL, 0, NULL); if (err == 0) { out_assign: top->sym_filter_entry = he; diff --git a/tools/perf/jvmti/jvmti_agent.h b/tools/perf/jvmti/jvmti_agent.h index bedf5d0ba9ff..c53a41f48b63 100644 --- a/tools/perf/jvmti/jvmti_agent.h +++ b/tools/perf/jvmti/jvmti_agent.h @@ -5,8 +5,6 @@ #include <stdint.h> #include <jvmti.h> -#define __unused __attribute__((unused)) - #if defined(__cplusplus) extern "C" { #endif diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c index 5612641c69b4..6d710904c837 100644 --- a/tools/perf/jvmti/libjvmti.c +++ b/tools/perf/jvmti/libjvmti.c @@ -1,3 +1,4 @@ +#include <linux/compiler.h> #include <sys/types.h> #include <stdio.h> #include <string.h> @@ -238,7 +239,7 @@ code_generated_cb(jvmtiEnv *jvmti, } JNIEXPORT jint JNICALL -Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused) +Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __maybe_unused) { jvmtiEventCallbacks cb; jvmtiCapabilities caps1; @@ -313,7 +314,7 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused) } JNIEXPORT void JNICALL -Agent_OnUnload(JavaVM *jvm __unused) +Agent_OnUnload(JavaVM *jvm __maybe_unused) { int ret; diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c index baa073f38334..bd0aabb2bd0f 100644 --- a/tools/perf/pmu-events/jevents.c +++ b/tools/perf/pmu-events/jevents.c @@ -48,10 +48,6 @@ #include "json.h" #include "jevents.h" -#ifndef __maybe_unused -#define __maybe_unused __attribute__((unused)) -#endif - int verbose; char *prog; diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c index 8ba2c4618fe9..39bbb97cd30a 100644 --- a/tools/perf/tests/bp_signal.c +++ b/tools/perf/tests/bp_signal.c @@ -62,8 +62,7 @@ static void __test_function(volatile long *ptr) } #endif -__attribute__ ((noinline)) -static int test_function(void) +static noinline int test_function(void) { __test_function(&the_var); the_var++; diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c index 89f92fa67cc4..3b1ac6f31b15 100644 --- a/tools/perf/tests/bp_signal_overflow.c +++ b/tools/perf/tests/bp_signal_overflow.c @@ -28,8 +28,7 @@ static int overflows; -__attribute__ ((noinline)) -static int test_function(void) +static noinline int test_function(void) { return time(NULL); } diff --git a/tools/perf/tests/bpf-script-test-prologue.c b/tools/perf/tests/bpf-script-test-prologue.c index 7230e62c70fc..b4ebc75e25ae 100644 --- a/tools/perf/tests/bpf-script-test-prologue.c +++ b/tools/perf/tests/bpf-script-test-prologue.c @@ -10,6 +10,15 @@ #include <uapi/linux/fs.h> +/* + * If CONFIG_PROFILE_ALL_BRANCHES is selected, + * 'if' is redefined after include kernel header. + * Recover 'if' for BPF object code. + */ +#ifdef if +# undef if +#endif + #define FMODE_READ 0x1 #define FMODE_WRITE 0x2 diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c index dfe5c89e2049..3e56d08f7995 100644 --- a/tools/perf/tests/dwarf-unwind.c +++ b/tools/perf/tests/dwarf-unwind.c @@ -76,8 +76,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) return strcmp((const char *) symbol, funcs[idx]); } -__attribute__ ((noinline)) -static int unwind_thread(struct thread *thread) +static noinline int unwind_thread(struct thread *thread) { struct perf_sample sample; unsigned long cnt = 0; @@ -108,8 +107,7 @@ static int unwind_thread(struct thread *thread) static int global_unwind_retval = -INT_MAX; -__attribute__ ((noinline)) -static int compare(void *p1, void *p2) +static noinline int compare(void *p1, void *p2) { /* Any possible value should be 'thread' */ struct thread *thread = *(struct thread **)p1; @@ -128,8 +126,7 @@ static int compare(void *p1, void *p2) return p1 - p2; } -__attribute__ ((noinline)) -static int krava_3(struct thread *thread) +static noinline int krava_3(struct thread *thread) { struct thread *array[2] = {thread, thread}; void *fp = &bsearch; @@ -147,14 +144,12 @@ static int krava_3(struct thread *thread) return global_unwind_retval; } -__attribute__ ((noinline)) -static int krava_2(struct thread *thread) +static noinline int krava_2(struct thread *thread) { return krava_3(thread); } -__attribute__ ((noinline)) -static int krava_1(struct thread *thread) +static noinline int krava_1(struct thread *thread) { return krava_2(thread); } diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index d990ad08a3c6..27f41f28dcb4 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -46,12 +46,15 @@ static struct annotate_browser_opt { .jump_arrows = true, }; +struct arch; + struct annotate_browser { struct ui_browser b; struct rb_root entries; struct rb_node *curr_hot; struct disasm_line *selection; struct disasm_line **offsets; + struct arch *arch; int nr_events; u64 start; int nr_asm_entries; @@ -125,43 +128,57 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int int i, pcnt_width = annotate_browser__pcnt_width(ab); double percent_max = 0.0; char bf[256]; + bool show_title = false; for (i = 0; i < ab->nr_events; i++) { if (bdl->samples[i].percent > percent_max) percent_max = bdl->samples[i].percent; } + if ((row == 0) && (dl->offset == -1 || percent_max == 0.0)) { + if (ab->have_cycles) { + if (dl->ipc == 0.0 && dl->cycles == 0) + show_title = true; + } else + show_title = true; + } + if (dl->offset != -1 && percent_max != 0.0) { - if (percent_max != 0.0) { - for (i = 0; i < ab->nr_events; i++) { - ui_browser__set_percent_color(browser, - bdl->samples[i].percent, - current_entry); - if (annotate_browser__opts.show_total_period) { - ui_browser__printf(browser, "%6" PRIu64 " ", - bdl->samples[i].nr); - } else { - ui_browser__printf(browser, "%6.2f ", - bdl->samples[i].percent); - } + for (i = 0; i < ab->nr_events; i++) { + ui_browser__set_percent_color(browser, + bdl->samples[i].percent, + current_entry); + if (annotate_browser__opts.show_total_period) { + ui_browser__printf(browser, "%6" PRIu64 " ", + bdl->samples[i].nr); + } else { + ui_browser__printf(browser, "%6.2f ", + bdl->samples[i].percent); } - } else { - ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); } } else { ui_browser__set_percent_color(browser, 0, current_entry); - ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); + + if (!show_title) + ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); + else + ui_browser__printf(browser, "%*s", 7, "Percent"); } if (ab->have_cycles) { if (dl->ipc) ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc); - else + else if (!show_title) ui_browser__write_nstring(browser, " ", IPC_WIDTH); + else + ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC"); + if (dl->cycles) ui_browser__printf(browser, "%*" PRIu64 " ", CYCLES_WIDTH - 1, dl->cycles); - else + else if (!show_title) ui_browser__write_nstring(browser, " ", CYCLES_WIDTH); + else + ui_browser__printf(browser, "%*s ", CYCLES_WIDTH - 1, "Cycle"); } SLsmg_write_char(' '); @@ -1056,7 +1073,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, (nr_pcnt - 1); } - err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), sizeof_bdl); + err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), + sizeof_bdl, &browser.arch); if (err) { char msg[BUFSIZ]; symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index e99ba86158d2..d903fd493416 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c @@ -168,7 +168,8 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map, if (map->dso->annotate_warned) return -1; - err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 0); + err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), + 0, NULL); if (err) { char msg[BUFSIZ]; symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index ddbd56df9187..be1caabb9290 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1379,7 +1379,9 @@ static const char *annotate__norm_arch(const char *arch_name) return normalize_arch((char *)arch_name); } -int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize) +int symbol__disassemble(struct symbol *sym, struct map *map, + const char *arch_name, size_t privsize, + struct arch **parch) { struct dso *dso = map->dso; char command[PATH_MAX * 2]; @@ -1405,6 +1407,9 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na if (arch == NULL) return -ENOTSUP; + if (parch) + *parch = arch; + if (arch->init) { err = arch->init(arch); if (err) { @@ -1901,7 +1906,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, struct rb_root source_line = RB_ROOT; u64 len; - if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), 0) < 0) + if (symbol__disassemble(sym, map, perf_evsel__env_arch(evsel), + 0, NULL) < 0) return -1; len = symbol__size(sym); diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 948aa8e6fd39..21055034aedd 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -158,7 +158,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); int symbol__alloc_hist(struct symbol *sym); void symbol__annotate_zero_histograms(struct symbol *sym); -int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_name, size_t privsize); +int symbol__disassemble(struct symbol *sym, struct map *map, + const char *arch_name, size_t privsize, + struct arch **parch); enum symbol_disassemble_errno { SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 0328f297a748..0175765c05b9 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -5,6 +5,7 @@ #include <subcmd/pager.h> #include "../ui/ui.h" +#include <linux/compiler.h> #include <linux/string.h> #define CMD_EXEC_PATH "--exec-path" @@ -24,6 +25,6 @@ static inline int is_absolute_path(const char *path) return path[0] == '/'; } -char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); +char *mkpath(const char *fmt, ...) __printf(1, 2); #endif /* __PERF_CACHE_H */ diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 8a23ea1a71c7..c818bdb1c1ab 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -4,6 +4,7 @@ #include <stdbool.h> #include <string.h> +#include <linux/compiler.h> #include "event.h" #include "../ui/helpline.h" #include "../ui/progress.h" @@ -40,16 +41,16 @@ extern int debug_data_convert; #define STRERR_BUFSIZE 128 /* For the buffer size of str_error_r */ -int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +int dump_printf(const char *fmt, ...) __printf(1, 2); void trace_event(union perf_event *event); -int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); -int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); +int ui__error(const char *format, ...) __printf(1, 2); +int ui__warning(const char *format, ...) __printf(1, 2); void pr_stat(const char *fmt, ...); -int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4))); -int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__((format(printf, 4, 5))); +int eprintf(int level, int var, const char *fmt, ...) __printf(3, 4); +int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __printf(4, 5); int veprintf(int level, int var, const char *fmt, va_list args); int perf_debug_option(const char *str); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 94cea4398a13..8d601fbdd8d6 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -1,6 +1,7 @@ #ifndef __PERF_EVLIST_H #define __PERF_EVLIST_H 1 +#include <linux/compiler.h> #include <linux/kernel.h> #include <linux/refcount.h> #include <linux/list.h> @@ -34,7 +35,7 @@ struct perf_mmap { refcount_t refcnt; u64 prev; struct auxtrace_mmap auxtrace_mmap; - char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); + char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); }; static inline size_t diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index cda44b0e821c..7f78f27f5382 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -15,6 +15,7 @@ #include <traceevent/event-parse.h> #include <linux/hw_breakpoint.h> #include <linux/perf_event.h> +#include <linux/compiler.h> #include <linux/err.h> #include <sys/ioctl.h> #include <sys/resource.h> @@ -1441,7 +1442,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, } static int __open_attr__fprintf(FILE *fp, const char *name, const char *val, - void *priv __attribute__((unused))) + void *priv __maybe_unused) { return fprintf(fp, " %-32s %s\n", name, val); } diff --git a/tools/perf/util/genelf_debug.c b/tools/perf/util/genelf_debug.c index 5980f7d256b1..40789d8603d0 100644 --- a/tools/perf/util/genelf_debug.c +++ b/tools/perf/util/genelf_debug.c @@ -11,6 +11,7 @@ * @remark Copyright 2007 OProfile authors * @author Philippe Elie */ +#include <linux/compiler.h> #include <sys/types.h> #include <stdio.h> #include <getopt.h> @@ -125,7 +126,7 @@ struct debug_line_header { * and filesize, last entry is followed by en empty string. */ /* follow the first program statement */ -} __attribute__((packed)); +} __packed; /* DWARF 2 spec talk only about one possible compilation unit header while * binutils can handle two flavours of dwarf 2, 32 and 64 bits, this is not @@ -138,7 +139,7 @@ struct compilation_unit_header { uhalf version; uword debug_abbrev_offset; ubyte pointer_size; -} __attribute__((packed)); +} __packed; #define DW_LNS_num_opcode (DW_LNS_set_isa + 1) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index b5baff3007bb..76ed7d03e500 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -8,6 +8,7 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <linux/compiler.h> #include <linux/list.h> #include <linux/kernel.h> #include <linux/bitops.h> @@ -1274,7 +1275,7 @@ error: } static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val, - void *priv __attribute__((unused))) + void *priv __maybe_unused) { return fprintf(fp, ", %s = %s", name, val); } diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index b2834ac7b1f5..218ee2bac9a5 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c @@ -866,8 +866,6 @@ static void intel_bts_print_info(u64 *arr, int start, int finish) fprintf(stdout, intel_bts_info_fmts[i], arr[i]); } -u64 intel_bts_auxtrace_info_priv[INTEL_BTS_AUXTRACE_PRIV_SIZE]; - int intel_bts_process_auxtrace_info(union perf_event *event, struct perf_session *session) { diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.h b/tools/perf/util/intel-pt-decoder/intel-pt-log.h index debe751dc3d6..45b64f93f358 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-log.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.h @@ -16,6 +16,7 @@ #ifndef INCLUDE__INTEL_PT_LOG_H__ #define INCLUDE__INTEL_PT_LOG_H__ +#include <linux/compiler.h> #include <stdint.h> #include <inttypes.h> @@ -34,8 +35,7 @@ void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip); void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip); -__attribute__((format(printf, 1, 2))) -void __intel_pt_log(const char *fmt, ...); +void __intel_pt_log(const char *fmt, ...) __printf(1, 2); #define intel_pt_log(fmt, ...) \ do { \ diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index ea7f450dc609..389e9729331f 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -2,6 +2,7 @@ #define __PMU_H #include <linux/bitmap.h> +#include <linux/compiler.h> #include <linux/perf_event.h> #include <stdbool.h> #include "evsel.h" @@ -83,8 +84,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet, bool long_desc, bool details_flag); bool pmu_have_event(const char *pname, const char *name); -int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, - ...) __attribute__((format(scanf, 3, 4))); +int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, ...) __scanf(3, 4); int perf_pmu__test(void); diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 373842656fb6..5812947418dd 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -1,6 +1,7 @@ #ifndef _PROBE_EVENT_H #define _PROBE_EVENT_H +#include <linux/compiler.h> #include <stdbool.h> #include "intlist.h" @@ -171,8 +172,7 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev, struct symbol *sym); /* If there is no space to write, returns -E2BIG. */ -int e_snprintf(char *str, size_t size, const char *format, ...) - __attribute__((format(printf, 3, 4))); +int e_snprintf(char *str, size_t size, const char *format, ...) __printf(3, 4); /* Maximum index number of event-name postfix */ #define MAX_EVENT_INDEX 1024 diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 40de3cb40d21..57b7a00e6f16 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -28,6 +28,7 @@ #include <stdbool.h> #include <errno.h> #include <linux/bitmap.h> +#include <linux/compiler.h> #include <linux/time64.h> #include "../../perf.h" @@ -84,7 +85,7 @@ struct tables { static struct tables tables_global; -static void handler_call_die(const char *handler_name) NORETURN; +static void handler_call_die(const char *handler_name) __noreturn; static void handler_call_die(const char *handler_name) { PyErr_Print(); diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index 318424ea561d..802d743378af 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h @@ -42,6 +42,7 @@ #include <stdarg.h> #include <stddef.h> #include <string.h> +#include <linux/compiler.h> #include <sys/types.h> extern char strbuf_slopbuf[]; @@ -85,8 +86,7 @@ static inline int strbuf_addstr(struct strbuf *sb, const char *s) { return strbuf_add(sb, s, strlen(s)); } -__attribute__((format(printf,2,3))) -int strbuf_addf(struct strbuf *sb, const char *fmt, ...); +int strbuf_addf(struct strbuf *sb, const char *fmt, ...) __printf(2, 3); /* XXX: if read fails, any partial read is undone */ ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c index 996046a66fe5..aacb65e079aa 100644 --- a/tools/perf/util/usage.c +++ b/tools/perf/util/usage.c @@ -16,13 +16,13 @@ static void report(const char *prefix, const char *err, va_list params) fprintf(stderr, " %s%s\n", prefix, msg); } -static NORETURN void usage_builtin(const char *err) +static __noreturn void usage_builtin(const char *err) { fprintf(stderr, "\n Usage: %s\n", err); exit(129); } -static NORETURN void die_builtin(const char *err, va_list params) +static __noreturn void die_builtin(const char *err, va_list params) { report(" Fatal: ", err, params); exit(128); @@ -40,7 +40,7 @@ static void warn_builtin(const char *warn, va_list params) /* If we are in a dlopen()ed .so write to a global variable would segfault * (ugh), so keep things static. */ -static void (*usage_routine)(const char *err) NORETURN = usage_builtin; +static void (*usage_routine)(const char *err) __noreturn = usage_builtin; static void (*error_routine)(const char *err, va_list params) = error_builtin; static void (*warn_routine)(const char *err, va_list params) = warn_builtin; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 5dfb9bb6482d..21c6db173bcc 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -11,22 +11,14 @@ #include <stddef.h> #include <stdlib.h> #include <stdarg.h> +#include <linux/compiler.h> #include <linux/types.h> -#ifdef __GNUC__ -#define NORETURN __attribute__((__noreturn__)) -#else -#define NORETURN -#ifndef __attribute__ -#define __attribute__(x) -#endif -#endif - /* General helper functions */ -void usage(const char *err) NORETURN; -void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); -int error(const char *err, ...) __attribute__((format (printf, 1, 2))); -void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); +void usage(const char *err) __noreturn; +void die(const char *err, ...) __noreturn __printf(1, 2); +int error(const char *err, ...) __printf(1, 2); +void warning(const char *err, ...) __printf(1, 2); void set_warning_routine(void (*routine)(const char *err, va_list params)); |