perf/core improvements and fixes:
User visible: - 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: - 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> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJZSHfUAAoJENZQFvNTUqpA3UYP/1T4VPphm1CItrZJW6vzepev eaHWBmVPpjnSb2/bN5Blh1GKcmfAwuGJPYQx9fONXCMUL6DXIYTzYaSZ0jQ2tGSG bCpnUJ2ccmvaCs7kUPvnkgaANsuqBQW7RSDNzzy9059r8udybtlXkQw0eBRcHrpf S6ql3H0uAMlK9M+QiLSc/OiDkW93EqsKtYSCBTL9bMsxokSQY+K5mYo0mZFojS4p 43Gs9JDt58nxydRcplEoNdvN11yS9M6KyxFjl/38swzdXH3/KLQ7ZHeqgOq4YDnI 8Zpzbi6n/yUjeUDGXWNu19F1JgdSprgZ3plZo4m5doFuWc4A03WvoBefCvYc1Gxc 5X9nxc3DjNsA8XJAsoGgB0B19wqgNzk5jgzhKMBOumre5gSUSP/uSOzbG7RQ+k+y mHXRFXUesNWo6TX065xdstr0tOd0fbkOA7mAkuYY5QyrTQcON2HKMUqvMGu86UfR StJPYRUFwLgjO2tQ967+LC3I+WQVZVwPMBAZ52cBSvYbj97H3dEm7SuBEqG/FrLp WEkibvcvEaVcfZuaZcgokodwIBDHeqWZYm+vHGaOZO2A0W6S5kvc2l2tf9uNbodp ye99FJdIsxv5eKTZmxps/W3Mjw245D5HF9i7Fy5vgoZgwiAi/vJ1kMHYxFd6LwW6 O/wnSzNzXSPICqH1M6Rd =wK/k -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
007b811b40
|
@ -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)))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
--------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 (parse_config_arg(arg, &var, &value) < 0) {
|
||||
free(arg);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (value == NULL)
|
||||
ret = show_spec_config(set, var);
|
||||
else
|
||||
ret = set_config(set, config_filename, var, value);
|
||||
free(arg);
|
||||
}
|
||||
} else
|
||||
if (!argc) {
|
||||
usage_with_options(config_usage, config_options);
|
||||
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 (parse_config_arg(arg, &var, &value) < 0) {
|
||||
free(arg);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#include <stdint.h>
|
||||
#include <jvmti.h>
|
||||
|
||||
#define __unused __attribute__((unused))
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -48,10 +48,6 @@
|
|||
#include "json.h"
|
||||
#include "jevents.h"
|
||||
|
||||
#ifndef __maybe_unused
|
||||
#define __maybe_unused __attribute__((unused))
|
||||
#endif
|
||||
|
||||
int verbose;
|
||||
char *prog;
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
|
||||
static int overflows;
|
||||
|
||||
__attribute__ ((noinline))
|
||||
static int test_function(void)
|
||||
static noinline int test_function(void)
|
||||
{
|
||||
return time(NULL);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 { \
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
Loading…
Reference in a new issue