summaryrefslogtreecommitdiff
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/cpumap.c17
-rw-r--r--tools/perf/util/cpumap.h1
-rw-r--r--tools/perf/util/evsel.c9
-rw-r--r--tools/perf/util/evsel.h4
-rw-r--r--tools/perf/util/parse-events.c14
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/parse-options.c62
-rw-r--r--tools/perf/util/parse-options.h5
-rw-r--r--tools/perf/util/strbuf.c22
-rw-r--r--tools/perf/util/strbuf.h2
-rw-r--r--tools/perf/util/symbol-minimal.c2
-rw-r--r--tools/perf/util/symbol.c11
13 files changed, 131 insertions, 22 deletions
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index aa6b490aa471..10af1e7524fb 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -203,6 +203,23 @@ struct cpu_map *cpu_map__dummy_new(void)
return cpus;
}
+struct cpu_map *cpu_map__empty_new(int nr)
+{
+ struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr);
+
+ if (cpus != NULL) {
+ int i;
+
+ cpus->nr = nr;
+ for (i = 0; i < nr; i++)
+ cpus->map[i] = -1;
+
+ atomic_set(&cpus->refcnt, 1);
+ }
+
+ return cpus;
+}
+
static void cpu_map__delete(struct cpu_map *map)
{
if (map) {
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index f1bcd2cfa164..85f7772457fa 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -15,6 +15,7 @@ struct cpu_map {
};
struct cpu_map *cpu_map__new(const char *cpu_list);
+struct cpu_map *cpu_map__empty_new(int nr);
struct cpu_map *cpu_map__dummy_new(void);
struct cpu_map *cpu_map__read(FILE *file);
size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ab05fa52a5cd..3ac4ee9c6a6e 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -652,6 +652,15 @@ static void apply_config_terms(struct perf_evsel *evsel,
case PERF_EVSEL__CONFIG_TERM_STACK_USER:
dump_size = term->val.stack_user;
break;
+ case PERF_EVSEL__CONFIG_TERM_INHERIT:
+ /*
+ * attr->inherit should has already been set by
+ * perf_evsel__config. If user explicitly set
+ * inherit using config terms, override global
+ * opt->no_inherit setting.
+ */
+ attr->inherit = term->val.inherit ? 1 : 0;
+ break;
default:
break;
}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 02a5fed8d924..1e8ff1906f71 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -43,6 +43,7 @@ enum {
PERF_EVSEL__CONFIG_TERM_TIME,
PERF_EVSEL__CONFIG_TERM_CALLGRAPH,
PERF_EVSEL__CONFIG_TERM_STACK_USER,
+ PERF_EVSEL__CONFIG_TERM_INHERIT,
PERF_EVSEL__CONFIG_TERM_MAX,
};
@@ -55,6 +56,7 @@ struct perf_evsel_config_term {
bool time;
char *callgraph;
u64 stack_user;
+ bool inherit;
} val;
};
@@ -90,9 +92,9 @@ struct perf_evsel {
double scale;
const char *unit;
struct event_format *tp_format;
+ off_t id_offset;
union {
void *priv;
- off_t id_offset;
u64 db_id;
};
struct cgroup_sel *cgrp;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 991bbd469bea..72abcf254ccb 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -666,6 +666,12 @@ do { \
case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
CHECK_TYPE_VAL(NUM);
break;
+ case PARSE_EVENTS__TERM_TYPE_INHERIT:
+ CHECK_TYPE_VAL(NUM);
+ break;
+ case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
+ CHECK_TYPE_VAL(NUM);
+ break;
case PARSE_EVENTS__TERM_TYPE_NAME:
CHECK_TYPE_VAL(STR);
break;
@@ -701,6 +707,8 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
switch (term->type_term) {
case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
+ case PARSE_EVENTS__TERM_TYPE_INHERIT:
+ case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
return config_term_common(attr, term, err);
default:
if (err) {
@@ -764,6 +772,12 @@ do { \
case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
break;
+ case PARSE_EVENTS__TERM_TYPE_INHERIT:
+ ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 1 : 0);
+ break;
+ case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
+ ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1);
+ break;
default:
break;
}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index f13d3ccda444..13c9063513eb 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -67,6 +67,8 @@ enum {
PARSE_EVENTS__TERM_TYPE_TIME,
PARSE_EVENTS__TERM_TYPE_CALLGRAPH,
PARSE_EVENTS__TERM_TYPE_STACKSIZE,
+ PARSE_EVENTS__TERM_TYPE_NOINHERIT,
+ PARSE_EVENTS__TERM_TYPE_INHERIT
};
struct parse_events_term {
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index be244573a02e..8d0de5b2991d 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -187,6 +187,8 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE
time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
+inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
+no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
, { return ','; }
"/" { BEGIN(INITIAL); return '/'; }
{name_minus} { return str(yyscanner, PE_NAME); }
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 22c2806bda98..9fca09296eb3 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -7,6 +7,8 @@
#define OPT_SHORT 1
#define OPT_UNSET 2
+static struct strbuf error_buf = STRBUF_INIT;
+
static int opterror(const struct option *opt, const char *reason, int flags)
{
if (flags & OPT_SHORT)
@@ -540,9 +542,11 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
exit(130);
default: /* PARSE_OPT_UNKNOWN */
if (ctx.argv[0][1] == '-') {
- error("unknown option `%s'", ctx.argv[0] + 2);
+ strbuf_addf(&error_buf, "unknown option `%s'",
+ ctx.argv[0] + 2);
} else {
- error("unknown switch `%c'", *ctx.opt);
+ strbuf_addf(&error_buf, "unknown switch `%c'",
+ *ctx.opt);
}
usage_with_options(usagestr, options);
}
@@ -691,8 +695,21 @@ static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx
for (i = 1; i < ctx->argc; ++i) {
const char *arg = ctx->argv[i];
- if (arg[0] != '-')
+ if (arg[0] != '-') {
+ if (arg[1] == '\0') {
+ if (arg[0] == opt->short_name)
+ return true;
+ continue;
+ }
+
+ if (opt->long_name && strcmp(opt->long_name, arg) == 0)
+ return true;
+
+ if (opt->help && strcasestr(opt->help, arg) != NULL)
+ return true;
+
continue;
+ }
if (arg[1] == opt->short_name ||
(arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0))
@@ -711,6 +728,13 @@ int usage_with_options_internal(const char * const *usagestr,
if (!usagestr)
return PARSE_OPT_HELP;
+ setup_pager();
+
+ if (strbuf_avail(&error_buf)) {
+ fprintf(stderr, " Error: %s\n", error_buf.buf);
+ strbuf_release(&error_buf);
+ }
+
fprintf(stderr, "\n Usage: %s\n", *usagestr++);
while (*usagestr && **usagestr)
fprintf(stderr, " or: %s\n", *usagestr++);
@@ -749,6 +773,21 @@ void usage_with_options(const char * const *usagestr,
exit(129);
}
+void usage_with_options_msg(const char * const *usagestr,
+ const struct option *opts, const char *fmt, ...)
+{
+ va_list ap;
+
+ exit_browser(false);
+
+ va_start(ap, fmt);
+ strbuf_addv(&error_buf, fmt, ap);
+ va_end(ap);
+
+ usage_with_options_internal(usagestr, opts, 0, NULL);
+ exit(129);
+}
+
int parse_options_usage(const char * const *usagestr,
const struct option *opts,
const char *optstr, bool short_opt)
@@ -770,24 +809,23 @@ int parse_options_usage(const char * const *usagestr,
opt:
for ( ; opts->type != OPTION_END; opts++) {
if (short_opt) {
- if (opts->short_name == *optstr)
+ if (opts->short_name == *optstr) {
+ print_option_help(opts, 0);
break;
+ }
continue;
}
if (opts->long_name == NULL)
continue;
- if (!prefixcmp(optstr, opts->long_name))
- break;
- if (!prefixcmp(optstr, "no-") &&
- !prefixcmp(optstr + 3, opts->long_name))
- break;
+ if (!prefixcmp(opts->long_name, optstr))
+ print_option_help(opts, 0);
+ if (!prefixcmp("no-", optstr) &&
+ !prefixcmp(opts->long_name, optstr + 3))
+ print_option_help(opts, 0);
}
- if (opts->type != OPTION_END)
- print_option_help(opts, 0);
-
return PARSE_OPT_HELP;
}
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 367d8b816cc7..a8e407bc251e 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -111,6 +111,7 @@ struct option {
#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) }
#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) }
+#define OPT_BOOLEAN_FLAG(s, l, v, h, f) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h), .flags = (f) }
#define OPT_BOOLEAN_SET(s, l, v, os, h) \
{ .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \
.value = check_vtype(v, bool *), .help = (h), \
@@ -160,6 +161,10 @@ extern int parse_options_subcommand(int argc, const char **argv,
extern NORETURN void usage_with_options(const char * const *usagestr,
const struct option *options);
+extern NORETURN __attribute__((format(printf,3,4)))
+void usage_with_options_msg(const char * const *usagestr,
+ const struct option *options,
+ const char *fmt, ...);
/*----- incremantal advanced APIs -----*/
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 4abe23550c73..25671fa16618 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -82,23 +82,22 @@ void strbuf_add(struct strbuf *sb, const void *data, size_t len)
strbuf_setlen(sb, sb->len + len);
}
-void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
+void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
{
int len;
- va_list ap;
+ va_list ap_saved;
if (!strbuf_avail(sb))
strbuf_grow(sb, 64);
- va_start(ap, fmt);
+
+ va_copy(ap_saved, ap);
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
- va_end(ap);
if (len < 0)
die("your vsnprintf is broken");
if (len > strbuf_avail(sb)) {
strbuf_grow(sb, len);
- va_start(ap, fmt);
- len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
- va_end(ap);
+ len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
+ va_end(ap_saved);
if (len > strbuf_avail(sb)) {
die("this should not happen, your vsnprintf is broken");
}
@@ -106,6 +105,15 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
strbuf_setlen(sb, sb->len + len);
}
+void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ strbuf_addv(sb, fmt, ap);
+ va_end(ap);
+}
+
ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
{
size_t oldlen = sb->len;
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index 436ac319f6c7..529f2f035249 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -39,6 +39,7 @@
*/
#include <assert.h>
+#include <stdarg.h>
extern char strbuf_slopbuf[];
struct strbuf {
@@ -85,6 +86,7 @@ static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
__attribute__((format(printf,2,3)))
extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
+extern void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap);
/* XXX: if read fails, any partial read is undone */
extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index fd8477cacf88..48906333a858 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -337,7 +337,7 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
symbol_filter_t filter __maybe_unused,
int kmodule __maybe_unused)
{
- unsigned char *build_id[BUILD_ID_SIZE];
+ unsigned char build_id[BUILD_ID_SIZE];
int ret;
ret = fd__is_64_bit(ss->fd);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e7bf0c46918d..b4cc7662677e 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -680,7 +680,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
pos->start -= curr_map->start - curr_map->pgoff;
if (pos->end)
pos->end -= curr_map->start - curr_map->pgoff;
- if (curr_map != map) {
+ if (curr_map->dso != map->dso) {
rb_erase_init(&pos->rb_node, root);
symbols__insert(
&curr_map->dso->symbols[curr_map->type],
@@ -1406,6 +1406,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
struct symsrc ss_[2];
struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
bool kmod;
+ unsigned char build_id[BUILD_ID_SIZE];
pthread_mutex_lock(&dso->lock);
@@ -1461,6 +1462,14 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE ||
dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
+
+ /*
+ * Read the build id if possible. This is required for
+ * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
+ */
+ if (filename__read_build_id(dso->name, build_id, BUILD_ID_SIZE) > 0)
+ dso__set_build_id(dso, build_id);
+
/*
* Iterate over candidate debug images.
* Keep track of "interesting" ones (those which have a symtab, dynsym,