Commit 007b811b authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo-4.13-20170719' of...

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 2eb0fc9b dfe1c6d7
...@@ -19,3 +19,13 @@ ...@@ -19,3 +19,13 @@
/* &a[0] degrades to a pointer: a different type from an array */ /* &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 __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)))
...@@ -17,6 +17,10 @@ ...@@ -17,6 +17,10 @@
# define __always_inline inline __attribute__((always_inline)) # define __always_inline inline __attribute__((always_inline))
#endif #endif
#ifndef noinline
#define noinline
#endif
/* Are two types/vars the same type (ignoring qualifiers)? */ /* Are two types/vars the same type (ignoring qualifiers)? */
#ifndef __same_type #ifndef __same_type
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
......
...@@ -48,6 +48,39 @@ OPTIONS ...@@ -48,6 +48,39 @@ OPTIONS
Ranges of CPUs are specified with -: 0-2. Ranges of CPUs are specified with -: 0-2.
Default is to trace on all online CPUs. 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 SEE ALSO
-------- --------
......
...@@ -116,7 +116,7 @@ OPTIONS ...@@ -116,7 +116,7 @@ OPTIONS
--fields:: --fields::
Comma separated list of fields to print. Options are: Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 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, 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. 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 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
...@@ -130,6 +130,14 @@ OPTIONS ...@@ -130,6 +130,14 @@ OPTIONS
i.e., the specified fields apply to all event types if the type string i.e., the specified fields apply to all event types if the type string
is not given. 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 The arguments are processed in the order received. A later usage can
reset a prior request. e.g.: reset a prior request. e.g.:
...@@ -203,6 +211,8 @@ OPTIONS ...@@ -203,6 +211,8 @@ OPTIONS
is printed. This is the full execution path leading to the sample. This is only supported when the 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. sample was recorded with perf record -b or -j any.
The brstackoff field will print an offset into a specific dso/binary.
-k:: -k::
--vmlinux=<file>:: --vmlinux=<file>::
vmlinux pathname vmlinux pathname
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/coresight-pmu.h> #include <linux/coresight-pmu.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/log2.h> #include <linux/log2.h>
...@@ -202,19 +203,18 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, ...@@ -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, pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME,
opts->auxtrace_snapshot_size); opts->auxtrace_snapshot_size);
if (cs_etm_evsel) {
/* /*
* To obtain the auxtrace buffer file descriptor, the auxtrace * To obtain the auxtrace buffer file descriptor, the auxtrace
* event must come first. * event must come first.
*/ */
perf_evlist__to_front(evlist, cs_etm_evsel); perf_evlist__to_front(evlist, cs_etm_evsel);
/* /*
* In the case of per-cpu mmaps, we need the CPU on the * In the case of per-cpu mmaps, we need the CPU on the
* AUX event. * AUX event.
*/ */
if (!cpu_map__empty(cpus)) if (!cpu_map__empty(cpus))
perf_evsel__set_sample_bit(cs_etm_evsel, CPU); perf_evsel__set_sample_bit(cs_etm_evsel, CPU);
}
/* Add dummy event to keep tracking */ /* Add dummy event to keep tracking */
if (opts->full_auxtrace) { if (opts->full_auxtrace) {
...@@ -583,8 +583,7 @@ static FILE *cs_device__open_file(const char *name) ...@@ -583,8 +583,7 @@ static FILE *cs_device__open_file(const char *name)
} }
static __attribute__((format(printf, 2, 3))) static int __printf(2, 3) cs_device__print_file(const char *name, const char *fmt, ...)
int cs_device__print_file(const char *name, const char *fmt, ...)
{ {
va_list args; va_list args;
FILE *file; FILE *file;
......
...@@ -35,10 +35,6 @@ ...@@ -35,10 +35,6 @@
#define KiB_MASK(x) (KiB(x) - 1) #define KiB_MASK(x) (KiB(x) - 1)
#define MiB_MASK(x) (MiB(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 { struct intel_bts_snapshot_ref {
void *ref_buf; void *ref_buf;
size_t ref_offset; size_t ref_offset;
......
...@@ -40,10 +40,6 @@ ...@@ -40,10 +40,6 @@
#define KiB_MASK(x) (KiB(x) - 1) #define KiB_MASK(x) (KiB(x) - 1)
#define MiB_MASK(x) (MiB(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 #define INTEL_PT_PSB_PERIOD_NEAR 256
struct intel_pt_snapshot_ref { struct intel_pt_snapshot_ref {
......
...@@ -700,7 +700,7 @@ static inline uint32_t lfsr_32(uint32_t lfsr) ...@@ -700,7 +700,7 @@ static inline uint32_t lfsr_32(uint32_t lfsr)
* kernel (KSM, zero page, etc.) cannot optimize away RAM * kernel (KSM, zero page, etc.) cannot optimize away RAM
* accesses: * 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) if (g->p.data_reads)
val += *data; val += *data;
......
...@@ -156,7 +156,7 @@ static int parse_config_arg(char *arg, char **var, char **value) ...@@ -156,7 +156,7 @@ static int parse_config_arg(char *arg, char **var, char **value)
int cmd_config(int argc, const char **argv) int cmd_config(int argc, const char **argv)
{ {
int i, ret = 0; int i, ret = -1;
struct perf_config_set *set; struct perf_config_set *set;
char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
const char *config_filename; const char *config_filename;
...@@ -186,10 +186,8 @@ int cmd_config(int argc, const char **argv) ...@@ -186,10 +186,8 @@ int cmd_config(int argc, const char **argv)
* because of reinitializing with options config file location. * because of reinitializing with options config file location.
*/ */
set = perf_config_set__new(); set = perf_config_set__new();
if (!set) { if (!set)
ret = -1;
goto out_err; goto out_err;
}
switch (actions) { switch (actions) {
case ACTION_LIST: case ACTION_LIST:
...@@ -197,41 +195,54 @@ int cmd_config(int argc, const char **argv) ...@@ -197,41 +195,54 @@ int cmd_config(int argc, const char **argv)
pr_err("Error: takes no arguments\n"); pr_err("Error: takes no arguments\n");
parse_options_usage(config_usage, config_options, "l", 1); parse_options_usage(config_usage, config_options, "l", 1);
} else { } else {
ret = show_config(set); if (show_config(set) < 0) {
if (ret < 0)
pr_err("Nothing configured, " pr_err("Nothing configured, "
"please check your %s \n", config_filename); "please check your %s \n", config_filename);
goto out_err;
}
} }
break; break;
default: default:
if (argc) { if (!argc) {
usage_with_options(config_usage, config_options);
break;
}
for (i = 0; argv[i]; i++) { for (i = 0; argv[i]; i++) {
char *var, *value; char *var, *value;
char *arg = strdup(argv[i]); char *arg = strdup(argv[i]);
if (!arg) { if (!arg) {
pr_err("%s: strdup failed\n", __func__); pr_err("%s: strdup failed\n", __func__);
ret = -1; goto out_err;
break;
} }
if (parse_config_arg(arg, &var, &value) < 0) { if (parse_config_arg(arg, &var, &value) < 0) {
free(arg); free(arg);
ret = -1; goto out_err;
break;
} }
if (value == NULL) if (value == NULL) {
ret = show_spec_config(set, var); if (show_spec_config(set, var) < 0) {
else pr_err("%s is not configured: %s\n",
ret = set_config(set, config_filename, var, value); 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); free(arg);
} }
} else
usage_with_options(config_usage, config_options);
} }
perf_config_set__delete(set); ret = 0;
out_err: out_err:
perf_config_set__delete(set);
return ret; return ret;
} }
...@@ -31,6 +31,16 @@ struct perf_ftrace { ...@@ -31,6 +31,16 @@ struct perf_ftrace {
struct perf_evlist *evlist; struct perf_evlist *evlist;
struct target target; struct target target;
const char *tracer; 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; static bool done;
...@@ -61,6 +71,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append) ...@@ -61,6 +71,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
int fd, ret = -1; int fd, ret = -1;
ssize_t size = strlen(val); ssize_t size = strlen(val);
int flags = O_WRONLY; int flags = O_WRONLY;
char errbuf[512];
file = get_tracing_file(name); file = get_tracing_file(name);
if (!file) { if (!file) {
...@@ -75,14 +86,16 @@ static int __write_tracing_file(const char *name, const char *val, bool append) ...@@ -75,14 +86,16 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
fd = open(file, flags); fd = open(file, flags);
if (fd < 0) { 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; goto out;
} }
if (write(fd, val, size) == size) if (write(fd, val, size) == size)
ret = 0; ret = 0;
else 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); close(fd);
out: out:
...@@ -101,6 +114,7 @@ static int append_tracing_file(const char *name, const char *val) ...@@ -101,6 +114,7 @@ static int append_tracing_file(const char *name, const char *val)
} }
static int reset_tracing_cpu(void); static int reset_tracing_cpu(void);
static void reset_tracing_filters(void);
static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused) 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) ...@@ -116,6 +130,10 @@ static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
if (reset_tracing_cpu() < 0) if (reset_tracing_cpu() < 0)
return -1; return -1;
if (write_tracing_file("max_graph_depth", "0") < 0)
return -1;
reset_tracing_filters();
return 0; return 0;
} }
...@@ -181,6 +199,68 @@ static int reset_tracing_cpu(void) ...@@ -181,6 +199,68 @@ static int reset_tracing_cpu(void)
return ret; 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) static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
{ {
char *trace_file; char *trace_file;
...@@ -223,11 +303,23 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv) ...@@ -223,11 +303,23 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
goto out_reset; 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) { if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer); pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset; goto out_reset;
} }
setup_pager();
trace_file = get_tracing_file("trace_pipe"); trace_file = get_tracing_file("trace_pipe");
if (!trace_file) { if (!trace_file) {
pr_err("failed to open trace_pipe\n"); 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) ...@@ -251,8 +343,6 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
goto out_close_fd; goto out_close_fd;
} }
setup_pager();
perf_evlist__start_workload(ftrace->evlist); perf_evlist__start_workload(ftrace->evlist);
while (!done) { while (!done) {
...@@ -307,6 +397,32 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb) ...@@ -307,6 +397,32 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb)
return -1; 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 cmd_ftrace(int argc, const char **argv)
{ {
int ret; int ret;
...@@ -330,9 +446,24 @@ int cmd_ftrace(int argc, const char **argv) ...@@ -330,9 +446,24 @@ int cmd_ftrace(int argc, const char **argv)
"system-wide collection from all CPUs"), "system-wide collection from all CPUs"),
OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu", OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu",
"list of cpus to monitor"), "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() 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); ret = perf_config(perf_ftrace_config, &ftrace);
if (ret < 0) if (ret < 0)
return -1; return -1;
...@@ -348,12 +479,14 @@ int cmd_ftrace(int argc, const char **argv) ...@@ -348,12 +479,14 @@ int cmd_ftrace(int argc, const char **argv)
target__strerror(&ftrace.target, ret, errbuf, 512); target__strerror(&ftrace.target, ret, errbuf, 512);
pr_err("%s\n", errbuf); pr_err("%s\n", errbuf);
return -EINVAL; goto out_delete_filters;
} }
ftrace.evlist = perf_evlist__new(); ftrace.evlist = perf_evlist__new();
if (ftrace.evlist == NULL) if (ftrace.evlist == NULL) {
return -ENOMEM; ret = -ENOMEM;
goto out_delete_filters;
}
ret = perf_evlist__create_maps(ftrace.evlist, &ftrace.target); ret = perf_evlist__create_maps(ftrace.evlist, &ftrace.target);
if (ret < 0) if (ret < 0)
...@@ -364,5 +497,11 @@ int cmd_ftrace(int argc, const char **argv) ...@@ -364,5 +497,11 @@ int cmd_ftrace(int argc, const char **argv)
out_delete_evlist: out_delete_evlist:
perf_evlist__delete(ftrace.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; return ret;
} }
...@@ -85,6 +85,7 @@ enum perf_output_field { ...@@ -85,6 +85,7 @@ enum perf_output_field {
PERF_OUTPUT_INSN = 1U << 21, PERF_OUTPUT_INSN = 1U << 21,
PERF_OUTPUT_INSNLEN = 1U << 22, PERF_OUTPUT_INSNLEN = 1U << 22,
PERF_OUTPUT_BRSTACKINSN = 1U << 23, PERF_OUTPUT_BRSTACKINSN = 1U << 23,
PERF_OUTPUT_BRSTACKOFF = 1U << 24,
}; };
struct output_option { struct output_option {
...@@ -115,6 +116,7 @@ struct output_option { ...@@ -115,6 +116,7 @@ struct output_option {
{.str = "insn", .field = PERF_OUTPUT_INSN}, {.str = "insn", .field = PERF_OUTPUT_INSN},
{.str = "insnlen", .field = PERF_OUTPUT_INSNLEN}, {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
{.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
{.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF},
}; };
/* default set to maintain compatibility with current format */ /* default set to maintain compatibility with current format */
...@@ -298,10 +300,10 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, ...@@ -298,10 +300,10 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
"selected.\n"); "selected.\n");
return -EINVAL; return -EINVAL;
} }
if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR) &&
pr_err("Display of DSO requested but neither sample IP nor " !PRINT_FIELD(BRSTACK) && !PRINT_FIELD(BRSTACKSYM) && !PRINT_FIELD(BRSTACKOFF)) {
"sample address\nis selected. Hence, no addresses to convert " pr_err("Display of DSO requested but no address to convert. Select\n"
"to DSO.\n"); "sample IP, sample address, brstack, brstacksym, or brstackoff.\n");
return -EINVAL; return -EINVAL;
} }
if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
...@@ -514,18 +516,43 @@ mispred_str(struct branch_entry *br) ...@@ -514,18 +516,43 @@ mispred_str(struct branch_entry *br)
return br->flags.predicted ? 'P' : 'M'; 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; struct branch_stack *br = sample->branch_stack;
u64 i; struct addr_location alf, alt;
u64 i, from, to;
if (!(br && br->nr)) if (!(br && br->nr))
return; return;
for (i = 0; i < br->nr; i++) { for (i = 0; i < br->nr; i++) {
printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ", from = br->entries[i].from;
br->entries[i].from, to = br->entries[i].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), mispred_str( br->entries + i),
br->entries[i].flags.in_tx? 'X' : '-', br->entries[i].flags.in_tx? 'X' : '-',
br->entries[i].flags.abort? 'A' : '-', br->entries[i].flags.abort? 'A' : '-',
...@@ -534,7 +561,8 @@ static void print_sample_brstack(struct perf_sample *sample) ...@@ -534,7 +561,8 @@ static void print_sample_brstack(struct perf_sample *sample)
} }
static void print_sample_brstacksym(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 branch_stack *br = sample->branch_stack;
struct addr_location alf, alt; struct addr_location alf, alt;
...@@ -559,8 +587,18 @@ static void print_sample_brstacksym(struct perf_sample *sample, ...@@ -559,8 +587,18 @@ static void print_sample_brstacksym(struct perf_sample *sample,
alt.sym = map__find_symbol(alt.map, alt.addr); alt.sym = map__find_symbol(alt.map, alt.addr);
symbol__fprintf_symname_offs(alf.sym, &alf, stdout); symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
if (PRINT_FIELD(DSO)) {
printf("(");
map__fprintf_dsoname(alf.map, stdout);
printf(")");
}
putchar('/'); putchar('/');
symbol__fprintf_symname_offs(alt.sym, &alt, stdout); 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 ", printf("/%c/%c/%c/%d ",
mispred_str( br->entries + i), mispred_str( br->entries + i),
br->entries[i].flags.in_tx? 'X' : '-', br->entries[i].flags.in_tx? 'X' : '-',
...@@ -569,6 +607,51 @@ static void print_sample_brstacksym(struct perf_sample *sample, ...@@ -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 #define MAXBB 16384UL
static int grab_bb(u8 *buffer, u64 start, u64 end, static int grab_bb(u8 *buffer, u64 start, u64 end,
...@@ -1187,9 +1270,11 @@ static void process_event(struct perf_script *script, ...@@ -1187,9 +1270,11 @@ static void process_event(struct perf_script *script,
print_sample_iregs(sample, attr); print_sample_iregs(sample, attr);
if (PRINT_FIELD(BRSTACK)) if (PRINT_FIELD(BRSTACK))
print_sample_brstack(sample); print_sample_brstack(sample, thread, attr);
else if (PRINT_FIELD(BRSTACKSYM)) 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)) if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
print_sample_bpf_output(sample); print_sample_bpf_output(sample);
...@@ -1727,6 +1812,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused, ...@@ -1727,6 +1812,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
int rc = 0; int rc = 0;
char *str = strdup(arg); char *str = strdup(arg);
int type = -1; int type = -1;
enum { DEFAULT, SET, ADD, REMOVE } change = DEFAULT;
if (!str) if (!str)
return -ENOMEM; return -ENOMEM;
...@@ -1772,6 +1858,10 @@ static int parse_output_fields(const struct option *opt __maybe_unused, ...@@ -1772,6 +1858,10 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
goto out; goto out;
} }
/* Don't override defaults for +- */
if (strchr(str, '+') || strchr(str, '-'))
goto parse;
if (output_set_by_user()) if (output_set_by_user())
pr_warning("Overriding previous field request for all events.\n"); 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, ...@@ -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)) { 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) { for (i = 0; i < imax; ++i) {
if (strcmp(tok, all_output_options[i].str) == 0) if (strcmp(tok, all_output_options[i].str) == 0)
break; break;
} }
if (i == imax && strcmp(tok, "flags") == 0) { if (i == imax && strcmp(tok, "flags") == 0) {
print_flags = true; print_flags = change == REMOVE ? false : true;
continue; continue;
} }
if (i == imax) { if (i == imax) {
...@@ -1805,9 +1912,13 @@ static int parse_output_fields(const struct option *opt __maybe_unused, ...@@ -1805,9 +1912,13 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
if (output[j].invalid_fields & all_output_options[i].field) { if (output[j].invalid_fields & all_output_options[i].field) {
pr_warning("\'%s\' not valid for %s events. Ignoring.\n", pr_warning("\'%s\' not valid for %s events. Ignoring.\n",
all_output_options[i].str, event_type(j)); all_output_options[i].str, event_type(j));
} else } else {
if (change == REMOVE)
output[j].fields &= ~all_output_options[i].field;
else
output[j].fields |= all_output_options[i].field; output[j].fields |= all_output_options[i].field;
} }
}
} else { } else {
if (output[type].invalid_fields & all_output_options[i].field) { if (output[type].invalid_fields & all_output_options[i].field) {
fprintf(stderr, "\'%s\' not valid for %s events.\n", fprintf(stderr, "\'%s\' not valid for %s events.\n",
...@@ -1826,7 +1937,11 @@ static int parse_output_fields(const struct option *opt __maybe_unused, ...@@ -1826,7 +1937,11 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
"Events will not be displayed.\n", event_type(type)); "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: out:
free(str); free(str);
return rc; return rc;
...@@ -2444,6 +2559,7 @@ int cmd_script(int argc, const char **argv) ...@@ -2444,6 +2559,7 @@ int cmd_script(int argc, const char **argv)
symbol__config_symfs), symbol__config_symfs),
OPT_CALLBACK('F', "fields", NULL, "str", OPT_CALLBACK('F', "fields", NULL, "str",
"comma separated output fields prepend with 'type:'. " "comma separated output fields prepend with 'type:'. "
"+field to add and -field to remove."
"Valid types: hw,sw,trace,raw. " "Valid types: hw,sw,trace,raw. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,period,iregs,brstack,brstacksym,flags," "addr,symoff,period,iregs,brstack,brstacksym,flags,"
......
...@@ -134,7 +134,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) ...@@ -134,7 +134,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
return err; return err;
} }
err = symbol__disassemble(sym, map, NULL, 0); err = symbol__disassemble(sym, map, NULL, 0, NULL);
if (err == 0) { if (err == 0) {
out_assign: out_assign:
top->sym_filter_entry = he; top->sym_filter_entry = he;
......
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
#include <stdint.h> #include <stdint.h>
#include <jvmti.h> #include <jvmti.h>
#define __unused __attribute__((unused))
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
......
#include <linux/compiler.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
...@@ -238,7 +239,7 @@ code_generated_cb(jvmtiEnv *jvmti, ...@@ -238,7 +239,7 @@ code_generated_cb(jvmtiEnv *jvmti,
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused) Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __maybe_unused)
{ {
jvmtiEventCallbacks cb; jvmtiEventCallbacks cb;
jvmtiCapabilities caps1; jvmtiCapabilities caps1;
...@@ -313,7 +314,7 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused) ...@@ -313,7 +314,7 @@ Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused)
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *jvm __unused) Agent_OnUnload(JavaVM *jvm __maybe_unused)
{ {
int ret; int ret;
......
...@@ -48,10 +48,6 @@ ...@@ -48,10 +48,6 @@
#include "json.h" #include "json.h"
#include "jevents.h" #include "jevents.h"
#ifndef __maybe_unused
#define __maybe_unused __attribute__((unused))
#endif
int verbose; int verbose;
char *prog; char *prog;
......
...@@ -62,8 +62,7 @@ static void __test_function(volatile long *ptr) ...@@ -62,8 +62,7 @@ static void __test_function(volatile long *ptr)
} }
#endif #endif
__attribute__ ((noinline)) static noinline int test_function(void)
static int test_function(void)
{ {
__test_function(&the_var); __test_function(&the_var);
the_var++; the_var++;
......
...@@ -28,8 +28,7 @@ ...@@ -28,8 +28,7 @@
static int overflows; static int overflows;
__attribute__ ((noinline)) static noinline int test_function(void)
static int test_function(void)
{ {
return time(NULL); return time(NULL);
} }
......
...@@ -10,6 +10,15 @@ ...@@ -10,6 +10,15 @@
#include <uapi/linux/fs.h> #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_READ 0x1
#define FMODE_WRITE 0x2 #define FMODE_WRITE 0x2
......
...@@ -76,8 +76,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) ...@@ -76,8 +76,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
return strcmp((const char *) symbol, funcs[idx]); return strcmp((const char *) symbol, funcs[idx]);
} }
__attribute__ ((noinline)) static noinline int unwind_thread(struct thread *thread)
static int unwind_thread(struct thread *thread)
{ {
struct perf_sample sample; struct perf_sample sample;
unsigned long cnt = 0; unsigned long cnt = 0;
...@@ -108,8 +107,7 @@ static int unwind_thread(struct thread *thread) ...@@ -108,8 +107,7 @@ static int unwind_thread(struct thread *thread)
static int global_unwind_retval = -INT_MAX; static int global_unwind_retval = -INT_MAX;
__attribute__ ((noinline)) static noinline int compare(void *p1, void *p2)
static int compare(void *p1, void *p2)
{ {
/* Any possible value should be 'thread' */ /* Any possible value should be 'thread' */
struct thread *thread = *(struct thread **)p1; struct thread *thread = *(struct thread **)p1;
...@@ -128,8 +126,7 @@ static int compare(void *p1, void *p2) ...@@ -128,8 +126,7 @@ static int compare(void *p1, void *p2)
return p1 - p2; return p1 - p2;
} }
__attribute__ ((noinline)) static noinline int krava_3(struct thread *thread)
static int krava_3(struct thread *thread)
{ {
struct thread *array[2] = {thread, thread}; struct thread *array[2] = {thread, thread};
void *fp = &bsearch; void *fp = &bsearch;
...@@ -147,14 +144,12 @@ static int krava_3(struct thread *thread) ...@@ -147,14 +144,12 @@ static int krava_3(struct thread *thread)
return global_unwind_retval; return global_unwind_retval;
} }
__attribute__ ((noinline)) static noinline int krava_2(struct thread *thread)
static int krava_2(struct thread *thread)
{ {
return krava_3(thread); return krava_3(thread);
} }
__attribute__ ((noinline)) static noinline int krava_1(struct thread *thread)
static int krava_1(struct thread *thread)
{ {
return krava_2(thread); return krava_2(thread);
} }
......
...@@ -46,12 +46,15 @@ static struct annotate_browser_opt { ...@@ -46,12 +46,15 @@ static struct annotate_browser_opt {
.jump_arrows = true, .jump_arrows = true,
}; };
struct arch;
struct annotate_browser { struct annotate_browser {
struct ui_browser b; struct ui_browser b;
struct rb_root entries; struct rb_root entries;
struct rb_node *curr_hot; struct rb_node *curr_hot;
struct disasm_line *selection; struct disasm_line *selection;
struct disasm_line **offsets; struct disasm_line **offsets;
struct arch *arch;
int nr_events; int nr_events;
u64 start; u64 start;
int nr_asm_entries; int nr_asm_entries;
...@@ -125,14 +128,22 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int ...@@ -125,14 +128,22 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
int i, pcnt_width = annotate_browser__pcnt_width(ab); int i, pcnt_width = annotate_browser__pcnt_width(ab);
double percent_max = 0.0; double percent_max = 0.0;
char bf[256]; char bf[256];
bool show_title = false;
for (i = 0; i < ab->nr_events; i++) { for (i = 0; i < ab->nr_events; i++) {
if (bdl->samples[i].percent > percent_max) if (bdl->samples[i].percent > percent_max)
percent_max = bdl->samples[i].percent; 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 (dl->offset != -1 && percent_max != 0.0) {
if (percent_max != 0.0) {
for (i = 0; i < ab->nr_events; i++) { for (i = 0; i < ab->nr_events; i++) {
ui_browser__set_percent_color(browser, ui_browser__set_percent_color(browser,
bdl->samples[i].percent, bdl->samples[i].percent,
...@@ -145,23 +156,29 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int ...@@ -145,23 +156,29 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
bdl->samples[i].percent); bdl->samples[i].percent);
} }
} }
} else {
ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);
}
} else { } else {
ui_browser__set_percent_color(browser, 0, current_entry); ui_browser__set_percent_color(browser, 0, current_entry);
if (!show_title)
ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); ui_browser__write_nstring(browser, " ", 7 * ab->nr_events);
else
ui_browser__printf(browser, "%*s", 7, "Percent");
} }
if (ab->have_cycles) { if (ab->have_cycles) {
if (dl->ipc) if (dl->ipc)
ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc); ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, dl->ipc);
else else if (!show_title)
ui_browser__write_nstring(browser, " ", IPC_WIDTH); ui_browser__write_nstring(browser, " ", IPC_WIDTH);
else
ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC");
if (dl->cycles) if (dl->cycles)
ui_browser__printf(browser, "%*" PRIu64 " ", ui_browser__printf(browser, "%*" PRIu64 " ",
CYCLES_WIDTH - 1, dl->cycles); CYCLES_WIDTH - 1, dl->cycles);
else else if (!show_title)
ui_browser__write_nstring(browser, " ", CYCLES_WIDTH); ui_browser__write_nstring(browser, " ", CYCLES_WIDTH);
else
ui_browser__printf(browser, "%*s ", CYCLES_WIDTH - 1, "Cycle");
} }
SLsmg_write_char(' '); SLsmg_write_char(' ');
...@@ -1056,7 +1073,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, ...@@ -1056,7 +1073,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
(nr_pcnt - 1); (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) { if (err) {
char msg[BUFSIZ]; char msg[BUFSIZ];
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
......
...@@ -168,7 +168,8 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map, ...@@ -168,7 +168,8 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
if (map->dso->annotate_warned) if (map->dso->annotate_warned)
return -1; 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) { if (err) {
char msg[BUFSIZ]; char msg[BUFSIZ];
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
......
...@@ -1379,7 +1379,9 @@ static const char *annotate__norm_arch(const char *arch_name) ...@@ -1379,7 +1379,9 @@ static const char *annotate__norm_arch(const char *arch_name)
return normalize_arch((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; struct dso *dso = map->dso;
char command[PATH_MAX * 2]; char command[PATH_MAX * 2];
...@@ -1405,6 +1407,9 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na ...@@ -1405,6 +1407,9 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
if (arch == NULL) if (arch == NULL)
return -ENOTSUP; return -ENOTSUP;
if (parch)
*parch = arch;
if (arch->init) { if (arch->init) {
err = arch->init(arch); err = arch->init(arch);
if (err) { if (err) {
...@@ -1901,7 +1906,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, ...@@ -1901,7 +1906,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
struct rb_root source_line = RB_ROOT; struct rb_root source_line = RB_ROOT;
u64 len; 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; return -1;
len = symbol__size(sym); len = symbol__size(sym);
......
...@@ -158,7 +158,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); ...@@ -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); int symbol__alloc_hist(struct symbol *sym);
void symbol__annotate_zero_histograms(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 { enum symbol_disassemble_errno {
SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <subcmd/pager.h> #include <subcmd/pager.h>
#include "../ui/ui.h" #include "../ui/ui.h"
#include <linux/compiler.h>
#include <linux/string.h> #include <linux/string.h>
#define CMD_EXEC_PATH "--exec-path" #define CMD_EXEC_PATH "--exec-path"
...@@ -24,6 +25,6 @@ static inline int is_absolute_path(const char *path) ...@@ -24,6 +25,6 @@ static inline int is_absolute_path(const char *path)
return path[0] == '/'; 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 */ #endif /* __PERF_CACHE_H */
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <linux/compiler.h>
#include "event.h" #include "event.h"
#include "../ui/helpline.h" #include "../ui/helpline.h"
#include "../ui/progress.h" #include "../ui/progress.h"
...@@ -40,16 +41,16 @@ extern int debug_data_convert; ...@@ -40,16 +41,16 @@ extern int debug_data_convert;
#define STRERR_BUFSIZE 128 /* For the buffer size of str_error_r */ #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); void trace_event(union perf_event *event);
int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); int ui__error(const char *format, ...) __printf(1, 2);
int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); int ui__warning(const char *format, ...) __printf(1, 2);
void pr_stat(const char *fmt, ...); void pr_stat(const char *fmt, ...);
int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4))); int eprintf(int level, int var, const char *fmt, ...) __printf(3, 4);
int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__((format(printf, 4, 5))); 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 veprintf(int level, int var, const char *fmt, va_list args);
int perf_debug_option(const char *str); int perf_debug_option(const char *str);
......
#ifndef __PERF_EVLIST_H #ifndef __PERF_EVLIST_H
#define __PERF_EVLIST_H 1 #define __PERF_EVLIST_H 1
#include <linux/compiler.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/refcount.h> #include <linux/refcount.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -34,7 +35,7 @@ struct perf_mmap { ...@@ -34,7 +35,7 @@ struct perf_mmap {
refcount_t refcnt; refcount_t refcnt;
u64 prev; u64 prev;
struct auxtrace_mmap auxtrace_mmap; 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 static inline size_t
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <traceevent/event-parse.h> #include <traceevent/event-parse.h>
#include <linux/hw_breakpoint.h> #include <linux/hw_breakpoint.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/compiler.h>
#include <linux/err.h> #include <linux/err.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/resource.h> #include <sys/resource.h>
...@@ -1441,7 +1442,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, ...@@ -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, 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); return fprintf(fp, " %-32s %s\n", name, val);
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* @remark Copyright 2007 OProfile authors * @remark Copyright 2007 OProfile authors
* @author Philippe Elie * @author Philippe Elie
*/ */
#include <linux/compiler.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include <getopt.h> #include <getopt.h>
...@@ -125,7 +126,7 @@ struct debug_line_header { ...@@ -125,7 +126,7 @@ struct debug_line_header {
* and filesize, last entry is followed by en empty string. * and filesize, last entry is followed by en empty string.
*/ */
/* follow the first program statement */ /* follow the first program statement */
} __attribute__((packed)); } __packed;
/* DWARF 2 spec talk only about one possible compilation unit header while /* 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 * binutils can handle two flavours of dwarf 2, 32 and 64 bits, this is not
...@@ -138,7 +139,7 @@ struct compilation_unit_header { ...@@ -138,7 +139,7 @@ struct compilation_unit_header {
uhalf version; uhalf version;
uword debug_abbrev_offset; uword debug_abbrev_offset;
ubyte pointer_size; ubyte pointer_size;
} __attribute__((packed)); } __packed;
#define DW_LNS_num_opcode (DW_LNS_set_isa + 1) #define DW_LNS_num_opcode (DW_LNS_set_isa + 1)
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <linux/compiler.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/bitops.h> #include <linux/bitops.h>
...@@ -1274,7 +1275,7 @@ read_event_desc(struct perf_header *ph, int fd) ...@@ -1274,7 +1275,7 @@ read_event_desc(struct perf_header *ph, int fd)
} }
static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val, 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); return fprintf(fp, ", %s = %s", name, val);
} }
......
...@@ -866,8 +866,6 @@ static void intel_bts_print_info(u64 *arr, int start, int finish) ...@@ -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]); 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, int intel_bts_process_auxtrace_info(union perf_event *event,
struct perf_session *session) struct perf_session *session)
{ {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#ifndef INCLUDE__INTEL_PT_LOG_H__ #ifndef INCLUDE__INTEL_PT_LOG_H__
#define INCLUDE__INTEL_PT_LOG_H__ #define INCLUDE__INTEL_PT_LOG_H__
#include <linux/compiler.h>
#include <stdint.h> #include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
...@@ -34,8 +35,7 @@ void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip); ...@@ -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, void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
uint64_t ip); uint64_t ip);
__attribute__((format(printf, 1, 2))) void __intel_pt_log(const char *fmt, ...) __printf(1, 2);
void __intel_pt_log(const char *fmt, ...);
#define intel_pt_log(fmt, ...) \ #define intel_pt_log(fmt, ...) \
do { \ do { \
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __PMU_H #define __PMU_H
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/compiler.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <stdbool.h> #include <stdbool.h>
#include "evsel.h" #include "evsel.h"
...@@ -83,8 +84,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet, ...@@ -83,8 +84,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet,
bool long_desc, bool details_flag); bool long_desc, bool details_flag);
bool pmu_have_event(const char *pname, const char *name); 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, int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, ...) __scanf(3, 4);
...) __attribute__((format(scanf, 3, 4)));
int perf_pmu__test(void); int perf_pmu__test(void);
......
#ifndef _PROBE_EVENT_H #ifndef _PROBE_EVENT_H
#define _PROBE_EVENT_H #define _PROBE_EVENT_H
#include <linux/compiler.h>
#include <stdbool.h> #include <stdbool.h>
#include "intlist.h" #include "intlist.h"
...@@ -171,8 +172,7 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev, ...@@ -171,8 +172,7 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev,
struct symbol *sym); struct symbol *sym);
/* If there is no space to write, returns -E2BIG. */ /* If there is no space to write, returns -E2BIG. */
int e_snprintf(char *str, size_t size, const char *format, ...) int e_snprintf(char *str, size_t size, const char *format, ...) __printf(3, 4);
__attribute__((format(printf, 3, 4)));
/* Maximum index number of event-name postfix */ /* Maximum index number of event-name postfix */
#define MAX_EVENT_INDEX 1024 #define MAX_EVENT_INDEX 1024
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <errno.h> #include <errno.h>
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/compiler.h>
#include <linux/time64.h> #include <linux/time64.h>
#include "../../perf.h" #include "../../perf.h"
...@@ -84,7 +85,7 @@ struct tables { ...@@ -84,7 +85,7 @@ struct tables {
static struct tables tables_global; 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) static void handler_call_die(const char *handler_name)
{ {
PyErr_Print(); PyErr_Print();
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <linux/compiler.h>
#include <sys/types.h> #include <sys/types.h>
extern char strbuf_slopbuf[]; extern char strbuf_slopbuf[];
...@@ -85,8 +86,7 @@ static inline int strbuf_addstr(struct strbuf *sb, const char *s) { ...@@ -85,8 +86,7 @@ static inline int strbuf_addstr(struct strbuf *sb, const char *s) {
return strbuf_add(sb, s, strlen(s)); return strbuf_add(sb, s, strlen(s));
} }
__attribute__((format(printf,2,3))) int strbuf_addf(struct strbuf *sb, const char *fmt, ...) __printf(2, 3);
int strbuf_addf(struct strbuf *sb, const char *fmt, ...);
/* XXX: if read fails, any partial read is undone */ /* XXX: if read fails, any partial read is undone */
ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
......
...@@ -16,13 +16,13 @@ static void report(const char *prefix, const char *err, va_list params) ...@@ -16,13 +16,13 @@ static void report(const char *prefix, const char *err, va_list params)
fprintf(stderr, " %s%s\n", prefix, msg); 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); fprintf(stderr, "\n Usage: %s\n", err);
exit(129); 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); report(" Fatal: ", err, params);
exit(128); exit(128);
...@@ -40,7 +40,7 @@ static void warn_builtin(const char *warn, va_list params) ...@@ -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 /* If we are in a dlopen()ed .so write to a global variable would segfault
* (ugh), so keep things static. */ * (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 (*error_routine)(const char *err, va_list params) = error_builtin;
static void (*warn_routine)(const char *err, va_list params) = warn_builtin; static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
......
...@@ -11,22 +11,14 @@ ...@@ -11,22 +11,14 @@
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <linux/compiler.h>
#include <linux/types.h> #include <linux/types.h>
#ifdef __GNUC__
#define NORETURN __attribute__((__noreturn__))
#else
#define NORETURN
#ifndef __attribute__
#define __attribute__(x)
#endif
#endif
/* General helper functions */ /* General helper functions */
void usage(const char *err) NORETURN; void usage(const char *err) __noreturn;
void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); void die(const char *err, ...) __noreturn __printf(1, 2);
int error(const char *err, ...) __attribute__((format (printf, 1, 2))); int error(const char *err, ...) __printf(1, 2);
void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); void warning(const char *err, ...) __printf(1, 2);
void set_warning_routine(void (*routine)(const char *err, va_list params)); void set_warning_routine(void (*routine)(const char *err, va_list params));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment