diff options
Diffstat (limited to 'tools/perf/util')
| -rw-r--r-- | tools/perf/util/evlist.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 325 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 6 | ||||
| -rw-r--r-- | tools/perf/util/header.c | 28 | ||||
| -rw-r--r-- | tools/perf/util/machine.c | 5 | ||||
| -rw-r--r-- | tools/perf/util/map.c | 20 | ||||
| -rw-r--r-- | tools/perf/util/map.h | 6 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 8 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.l | 2 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.c | 5 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 3 | ||||
| -rw-r--r-- | tools/perf/util/symbol-elf.c | 16 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 34 |
13 files changed, 267 insertions, 193 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 82bf224bbee9..76ef7ee62640 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -695,7 +695,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) static bool perf_mmap__empty(struct perf_mmap *md) { - return perf_mmap__read_head(md) != md->prev; + return perf_mmap__read_head(md) == md->prev; } static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 358e5954baa8..33e3fd8c2e68 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -32,8 +32,12 @@ static struct { bool exclude_guest; bool mmap2; bool cloexec; + bool clockid; + bool clockid_wrong; } perf_missing_features; +static clockid_t clockid; + static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) { return 0; @@ -761,6 +765,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) attr->disabled = 0; attr->enable_on_exec = 0; } + + clockid = opts->clockid; + if (opts->use_clockid) { + attr->use_clockid = 1; + attr->clockid = opts->clockid; + } } static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) @@ -1001,67 +1011,126 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) return fd; } -#define __PRINT_ATTR(fmt, cast, field) \ - fprintf(fp, " %-19s "fmt"\n", #field, cast attr->field) - -#define PRINT_ATTR_U32(field) __PRINT_ATTR("%u" , , field) -#define PRINT_ATTR_X32(field) __PRINT_ATTR("%#x", , field) -#define PRINT_ATTR_U64(field) __PRINT_ATTR("%" PRIu64, (uint64_t), field) -#define PRINT_ATTR_X64(field) __PRINT_ATTR("%#"PRIx64, (uint64_t), field) - -#define PRINT_ATTR2N(name1, field1, name2, field2) \ - fprintf(fp, " %-19s %u %-19s %u\n", \ - name1, attr->field1, name2, attr->field2) - -#define PRINT_ATTR2(field1, field2) \ - PRINT_ATTR2N(#field1, field1, #field2, field2) - -static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) -{ - size_t ret = 0; - - ret += fprintf(fp, "%.60s\n", graph_dotted_line); - ret += fprintf(fp, "perf_event_attr:\n"); - - ret += PRINT_ATTR_U32(type); - ret += PRINT_ATTR_U32(size); - ret += PRINT_ATTR_X64(config); - ret += PRINT_ATTR_U64(sample_period); - ret += PRINT_ATTR_U64(sample_freq); - ret += PRINT_ATTR_X64(sample_type); - ret += PRINT_ATTR_X64(read_format); - - ret += PRINT_ATTR2(disabled, inherit); - ret += PRINT_ATTR2(pinned, exclusive); - ret += PRINT_ATTR2(exclude_user, exclude_kernel); - ret += PRINT_ATTR2(exclude_hv, exclude_idle); - ret += PRINT_ATTR2(mmap, comm); - ret += PRINT_ATTR2(mmap2, comm_exec); - ret += PRINT_ATTR2(freq, inherit_stat); - ret += PRINT_ATTR2(enable_on_exec, task); - ret += PRINT_ATTR2(watermark, precise_ip); - ret += PRINT_ATTR2(mmap_data, sample_id_all); - ret += PRINT_ATTR2(exclude_host, exclude_guest); - ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel, - "excl.callchain_user", exclude_callchain_user); - - ret += PRINT_ATTR_U32(wakeup_events); - ret += PRINT_ATTR_U32(wakeup_watermark); - ret += PRINT_ATTR_X32(bp_type); - ret += PRINT_ATTR_X64(bp_addr); - ret += PRINT_ATTR_X64(config1); - ret += PRINT_ATTR_U64(bp_len); - ret += PRINT_ATTR_X64(config2); - ret += PRINT_ATTR_X64(branch_sample_type); - ret += PRINT_ATTR_X64(sample_regs_user); - ret += PRINT_ATTR_U32(sample_stack_user); - ret += PRINT_ATTR_X64(sample_regs_intr); - - ret += fprintf(fp, "%.60s\n", graph_dotted_line); +struct bit_names { + int bit; + const char *name; +}; + +static void __p_bits(char *buf, size_t size, u64 value, struct bit_names *bits) +{ + bool first_bit = true; + int i = 0; + + do { + if (value & bits[i].bit) { + buf += scnprintf(buf, size, "%s%s", first_bit ? "" : "|", bits[i].name); + first_bit = false; + } + } while (bits[++i].name != NULL); +} + +static void __p_sample_type(char *buf, size_t size, u64 value) +{ +#define bit_name(n) { PERF_SAMPLE_##n, #n } + struct bit_names bits[] = { + bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR), + bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), + bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), + bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), + bit_name(IDENTIFIER), bit_name(REGS_INTR), + { .name = NULL, } + }; +#undef bit_name + __p_bits(buf, size, value, bits); +} + +static void __p_read_format(char *buf, size_t size, u64 value) +{ +#define bit_name(n) { PERF_FORMAT_##n, #n } + struct bit_names bits[] = { + bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING), + bit_name(ID), bit_name(GROUP), + { .name = NULL, } + }; +#undef bit_name + __p_bits(buf, size, value, bits); +} + +#define BUF_SIZE 1024 + +#define p_hex(val) snprintf(buf, BUF_SIZE, "%"PRIx64, (uint64_t)(val)) +#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val)) +#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val)) +#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val) +#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val) + +#define PRINT_ATTRn(_n, _f, _p) \ +do { \ + if (attr->_f) { \ + _p(attr->_f); \ + ret += attr__fprintf(fp, _n, buf, priv);\ + } \ +} while (0) + +#define PRINT_ATTRf(_f, _p) PRINT_ATTRn(#_f, _f, _p) + +int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, + attr__fprintf_f attr__fprintf, void *priv) +{ + char buf[BUF_SIZE]; + int ret = 0; + + PRINT_ATTRf(type, p_unsigned); + PRINT_ATTRf(size, p_unsigned); + PRINT_ATTRf(config, p_hex); + PRINT_ATTRn("{ sample_period, sample_freq }", sample_period, p_unsigned); + PRINT_ATTRf(sample_type, p_sample_type); + PRINT_ATTRf(read_format, p_read_format); + + PRINT_ATTRf(disabled, p_unsigned); + PRINT_ATTRf(inherit, p_unsigned); + PRINT_ATTRf(pinned, p_unsigned); + PRINT_ATTRf(exclusive, p_unsigned); + PRINT_ATTRf(exclude_user, p_unsigned); + PRINT_ATTRf(exclude_kernel, p_unsigned); + PRINT_ATTRf(exclude_hv, p_unsigned); + PRINT_ATTRf(exclude_idle, p_unsigned); + PRINT_ATTRf(mmap, p_unsigned); + PRINT_ATTRf(comm, p_unsigned); + PRINT_ATTRf(freq, p_unsigned); + PRINT_ATTRf(inherit_stat, p_unsigned); + PRINT_ATTRf(enable_on_exec, p_unsigned); + PRINT_ATTRf(task, p_unsigned); + PRINT_ATTRf(watermark, p_unsigned); + PRINT_ATTRf(precise_ip, p_unsigned); + PRINT_ATTRf(mmap_data, p_unsigned); + PRINT_ATTRf(sample_id_all, p_unsigned); + PRINT_ATTRf(exclude_host, p_unsigned); + PRINT_ATTRf(exclude_guest, p_unsigned); + PRINT_ATTRf(exclude_callchain_kernel, p_unsigned); + PRINT_ATTRf(exclude_callchain_user, p_unsigned); + PRINT_ATTRf(mmap2, p_unsigned); + PRINT_ATTRf(comm_exec, p_unsigned); + PRINT_ATTRf(use_clockid, p_unsigned); + + PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); + PRINT_ATTRf(bp_type, p_unsigned); + PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); + PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); + PRINT_ATTRf(sample_regs_user, p_hex); + PRINT_ATTRf(sample_stack_user, p_unsigned); + PRINT_ATTRf(clockid, p_signed); + PRINT_ATTRf(sample_regs_intr, p_hex); return ret; } +static int __open_attr__fprintf(FILE *fp, const char *name, const char *val, + void *priv __attribute__((unused))) +{ + return fprintf(fp, " %-32s %s\n", name, val); +} + static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, struct thread_map *threads) { @@ -1085,6 +1154,12 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, } fallback_missing_features: + if (perf_missing_features.clockid_wrong) + evsel->attr.clockid = CLOCK_MONOTONIC; /* should always work */ + if (perf_missing_features.clockid) { + evsel->attr.use_clockid = 0; + evsel->attr.clockid = 0; + } if (perf_missing_features.cloexec) flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC; if (perf_missing_features.mmap2) @@ -1095,8 +1170,12 @@ retry_sample_id: if (perf_missing_features.sample_id_all) evsel->attr.sample_id_all = 0; - if (verbose >= 2) - perf_event_attr__fprintf(&evsel->attr, stderr); + if (verbose >= 2) { + fprintf(stderr, "%.60s\n", graph_dotted_line); + fprintf(stderr, "perf_event_attr:\n"); + perf_event_attr__fprintf(stderr, &evsel->attr, __open_attr__fprintf, NULL); + fprintf(stderr, "%.60s\n", graph_dotted_line); + } for (cpu = 0; cpu < cpus->nr; cpu++) { @@ -1122,6 +1201,17 @@ retry_open: goto try_fallback; } set_rlimit = NO_CHANGE; + + /* + * If we succeeded but had to kill clockid, fail and + * have perf_evsel__open_strerror() print us a nice + * error. + */ + if (perf_missing_features.clockid || + perf_missing_features.clockid_wrong) { + err = -EINVAL; + goto out_close; + } } } @@ -1155,7 +1245,17 @@ try_fallback: if (err != -EINVAL || cpu > 0 || thread > 0) goto out_close; - if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { + /* + * Must probe features in the order they were added to the + * perf_event_attr interface. + */ + if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { + perf_missing_features.clockid_wrong = true; + goto fallback_missing_features; + } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { + perf_missing_features.clockid = true; + goto fallback_missing_features; + } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { perf_missing_features.cloexec = true; goto fallback_missing_features; } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { @@ -1956,62 +2056,9 @@ static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...) return ret; } -static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value) -{ - if (value == 0) - return 0; - - return comma_fprintf(fp, first, " %s: %" PRIu64, field, value); -} - -#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field) - -struct bit_names { - int bit; - const char *name; -}; - -static int bits__fprintf(FILE *fp, const char *field, u64 value, - struct bit_names *bits, bool *first) -{ - int i = 0, printed = comma_fprintf(fp, first, " %s: ", field); - bool first_bit = true; - - do { - if (value & bits[i].bit) { - printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name); - first_bit = false; - } - } while (bits[++i].name != NULL); - - return printed; -} - -static int sample_type__fprintf(FILE *fp, bool *first, u64 value) +static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv) { -#define bit_name(n) { PERF_SAMPLE_##n, #n } - struct bit_names bits[] = { - bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR), - bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), - bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), - bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), - bit_name(IDENTIFIER), bit_name(REGS_INTR), - { .name = NULL, } - }; -#undef bit_name - return bits__fprintf(fp, "sample_type", value, bits, first); -} - -static int read_format__fprintf(FILE *fp, bool *first, u64 value) -{ -#define bit_name(n) { PERF_FORMAT_##n, #n } - struct bit_names bits[] = { - bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING), - bit_name(ID), bit_name(GROUP), - { .name = NULL, } - }; -#undef bit_name - return bits__fprintf(fp, "read_format", value, bits, first); + return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val); } int perf_evsel__fprintf(struct perf_evsel *evsel, @@ -2040,47 +2087,13 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, printed += fprintf(fp, "%s", perf_evsel__name(evsel)); - if (details->verbose || details->freq) { + if (details->verbose) { + printed += perf_event_attr__fprintf(fp, &evsel->attr, + __print_attr__fprintf, &first); + } else if (details->freq) { printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64, (u64)evsel->attr.sample_freq); } - - if (details->verbose) { - if_print(type); - if_print(config); - if_print(config1); - if_print(config2); - if_print(size); - printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type); - if (evsel->attr.read_format) - printed += read_format__fprintf(fp, &first, evsel->attr.read_format); - if_print(disabled); - if_print(inherit); - if_print(pinned); - if_print(exclusive); - if_print(exclude_user); - if_print(exclude_kernel); - if_print(exclude_hv); - if_print(exclude_idle); - if_print(mmap); - if_print(mmap2); - if_print(comm); - if_print(comm_exec); - if_print(freq); - if_print(inherit_stat); - if_print(enable_on_exec); - if_print(task); - if_print(watermark); - if_print(precise_ip); - if_print(mmap_data); - if_print(sample_id_all); - if_print(exclude_host); - if_print(exclude_guest); - if_print(__reserved_1); - if_print(wakeup_events); - if_print(bp_type); - if_print(branch_sample_type); - } out: fputc('\n', fp); return ++printed; @@ -2158,6 +2171,12 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, "The PMU counters are busy/taken by another profiler.\n" "We found oprofile daemon running, please stop it and try again."); break; + case EINVAL: + if (perf_missing_features.clockid) + return scnprintf(msg, size, "clockid feature not supported."); + if (perf_missing_features.clockid_wrong) + return scnprintf(msg, size, "wrong clockid (%d).", clockid); + break; default: break; } diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index c5a43d6b13dc..e486151b0308 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -360,4 +360,10 @@ static inline bool has_branch_callstack(struct perf_evsel *evsel) { return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; } + +typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *); + +int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, + attr__fprintf_f attr__fprintf, void *priv); + #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index fb432153e2aa..fff3b2a455ae 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1055,6 +1055,12 @@ error: goto out; } +static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val, + void *priv __attribute__((unused))) +{ + return fprintf(fp, ", %s = %s", name, val); +} + static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) { struct perf_evsel *evsel, *events = read_event_desc(ph, fd); @@ -1069,26 +1075,6 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) for (evsel = events; evsel->attr.size; evsel++) { fprintf(fp, "# event : name = %s, ", evsel->name); - fprintf(fp, "type = %d, config = 0x%"PRIx64 - ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64, - evsel->attr.type, - (u64)evsel->attr.config, - (u64)evsel->attr.config1, - (u64)evsel->attr.config2); - - fprintf(fp, ", excl_usr = %d, excl_kern = %d", - evsel->attr.exclude_user, - evsel->attr.exclude_kernel); - - fprintf(fp, ", excl_host = %d, excl_guest = %d", - evsel->attr.exclude_host, - evsel->attr.exclude_guest); - - fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip); - - fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2); - fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap); - fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data); if (evsel->ids) { fprintf(fp, ", id = {"); for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { @@ -1099,6 +1085,8 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) fprintf(fp, " }"); } + perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL); + fputc('\n', fp); } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index e45c8f33a8fd..9c380a2caa54 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -679,6 +679,9 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) machine->vmlinux_maps[type]->unmap_ip = identity__map_ip; kmap = map__kmap(machine->vmlinux_maps[type]); + if (!kmap) + return -1; + kmap->kmaps = &machine->kmaps; map_groups__insert(&machine->kmaps, machine->vmlinux_maps[type]); @@ -700,7 +703,7 @@ void machine__destroy_kernel_maps(struct machine *machine) kmap = map__kmap(machine->vmlinux_maps[type]); map_groups__remove(&machine->kmaps, machine->vmlinux_maps[type]); - if (kmap->ref_reloc_sym) { + if (kmap && kmap->ref_reloc_sym) { /* * ref_reloc_sym is shared among all maps, so free just * on one of them. diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 62ca9f2607d5..a14f08f41686 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -778,3 +778,23 @@ struct map *maps__next(struct map *map) return rb_entry(next, struct map, rb_node); return NULL; } + +struct kmap *map__kmap(struct map *map) +{ + if (!map->dso || !map->dso->kernel) { + pr_err("Internal error: map__kmap with a non-kernel map\n"); + return NULL; + } + return (struct kmap *)(map + 1); +} + +struct map_groups *map__kmaps(struct map *map) +{ + struct kmap *kmap = map__kmap(map); + + if (!kmap || !kmap->kmaps) { + pr_err("Internal error: map__kmaps with a non-kernel map\n"); + return NULL; + } + return kmap->kmaps; +} diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 0e42438b1e59..ec19c59ca38e 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -76,10 +76,8 @@ static inline struct map_groups *map_groups__get(struct map_groups *mg) void map_groups__put(struct map_groups *mg); -static inline struct kmap *map__kmap(struct map *map) -{ - return (struct kmap *)(map + 1); -} +struct kmap *map__kmap(struct map *map); +struct map_groups *map__kmaps(struct map *map); static inline u64 map__map_ip(struct map *map, u64 ip) { diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index fe07573d5ed4..be0655388b38 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -709,6 +709,7 @@ struct event_modifier { int eh; int eH; int eG; + int eI; int precise; int exclude_GH; int sample_read; @@ -723,6 +724,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str, int eh = evsel ? evsel->attr.exclude_hv : 0; int eH = evsel ? evsel->attr.exclude_host : 0; int eG = evsel ? evsel->attr.exclude_guest : 0; + int eI = evsel ? evsel->attr.exclude_idle : 0; int precise = evsel ? evsel->attr.precise_ip : 0; int sample_read = 0; int pinned = evsel ? evsel->attr.pinned : 0; @@ -753,6 +755,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str, if (!exclude_GH) exclude_GH = eG = eH = 1; eH = 0; + } else if (*str == 'I') { + eI = 1; } else if (*str == 'p') { precise++; /* use of precise requires exclude_guest */ @@ -786,6 +790,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str, mod->eh = eh; mod->eH = eH; mod->eG = eG; + mod->eI = eI; mod->precise = precise; mod->exclude_GH = exclude_GH; mod->sample_read = sample_read; @@ -803,7 +808,7 @@ static int check_modifier(char *str) char *p = str; /* The sizeof includes 0 byte as well. */ - if (strlen(str) > (sizeof("ukhGHpppSD") - 1)) + if (strlen(str) > (sizeof("ukhGHpppSDI") - 1)) return -1; while (*p) { @@ -839,6 +844,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) evsel->attr.precise_ip = mod.precise; evsel->attr.exclude_host = mod.eH; evsel->attr.exclude_guest = mod.eG; + evsel->attr.exclude_idle = mod.eI; evsel->exclude_GH = mod.exclude_GH; evsel->sample_read = mod.sample_read; diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 94eacb6c1ef7..8895cf3132ab 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -101,7 +101,7 @@ num_raw_hex [a-fA-F0-9]+ name [a-zA-Z_*?][a-zA-Z0-9_*?]* name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* /* If you add a modifier you need to update check_modifier() */ -modifier_event [ukhpGHSD]+ +modifier_event [ukhpGHSDI]+ modifier_bp [rwx]{1,3} %% diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 8feac0774c41..b78851732a71 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -135,6 +135,8 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) return NULL; kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); + if (!kmap) + return NULL; return kmap->ref_reloc_sym; } @@ -320,7 +322,8 @@ static int find_alternative_probe_point(struct debuginfo *dinfo, ret = -ENOENT; goto out; } - pr_debug("Symbol %s address found : %lx\n", pp->function, address); + pr_debug("Symbol %s address found : %" PRIx64 "\n", + pp->function, address); ret = debuginfo__find_probe_point(dinfo, (unsigned long)address, result); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index dfacf1d50162..0c74012575ac 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1466,6 +1466,9 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps, for (i = 0; i < MAP__NR_TYPES; ++i) { struct kmap *kmap = map__kmap(maps[i]); + + if (!kmap) + continue; kmap->ref_reloc_sym = ref; } diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 476268c99431..a7ab6063e038 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -776,6 +776,7 @@ int dso__load_sym(struct dso *dso, struct map *map, symbol_filter_t filter, int kmodule) { struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; + struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL; struct map *curr_map = map; struct dso *curr_dso = dso; Elf_Data *symstrs, *secstrs; @@ -791,6 +792,9 @@ int dso__load_sym(struct dso *dso, struct map *map, int nr = 0; bool remap_kernel = false, adjust_kernel_syms = false; + if (kmap && !kmaps) + return -1; + dso->symtab_type = syms_ss->type; dso->is_64_bit = syms_ss->is_64_bit; dso->rel = syms_ss->ehdr.e_type == ET_REL; @@ -958,8 +962,10 @@ int dso__load_sym(struct dso *dso, struct map *map, map->map_ip = map__map_ip; map->unmap_ip = map__unmap_ip; /* Ensure maps are correctly ordered */ - map_groups__remove(kmap->kmaps, map); - map_groups__insert(kmap->kmaps, map); + if (kmaps) { + map_groups__remove(kmaps, map); + map_groups__insert(kmaps, map); + } } /* @@ -983,7 +989,7 @@ int dso__load_sym(struct dso *dso, struct map *map, snprintf(dso_name, sizeof(dso_name), "%s%s", dso->short_name, section_name); - curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); + curr_map = map_groups__find_by_name(kmaps, map->type, dso_name); if (curr_map == NULL) { u64 start = sym.st_value; @@ -1013,7 +1019,7 @@ int dso__load_sym(struct dso *dso, struct map *map, curr_map->unmap_ip = identity__map_ip; } curr_dso->symtab_type = dso->symtab_type; - map_groups__insert(kmap->kmaps, curr_map); + map_groups__insert(kmaps, curr_map); /* * The new DSO should go to the kernel DSOS */ @@ -1075,7 +1081,7 @@ new_symbol: * We need to fixup this here too because we create new * maps here, for things like vsyscall sections. */ - __map_groups__fixup_end(kmap->kmaps, map->type); + __map_groups__fixup_end(kmaps, map->type); } } err = nr; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fddeb9073039..201f6c4ca738 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -630,13 +630,16 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename, static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, symbol_filter_t filter) { - struct map_groups *kmaps = map__kmap(map)->kmaps; + struct map_groups *kmaps = map__kmaps(map); struct map *curr_map; struct symbol *pos; int count = 0, moved = 0; struct rb_root *root = &dso->symbols[map->type]; struct rb_node *next = rb_first(root); + if (!kmaps) + return -1; + while (next) { char *module; @@ -682,8 +685,8 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, symbol_filter_t filter) { - struct map_groups *kmaps = map__kmap(map)->kmaps; - struct machine *machine = kmaps->machine; + struct map_groups *kmaps = map__kmaps(map); + struct machine *machine; struct map *curr_map = map; struct symbol *pos; int count = 0, moved = 0; @@ -691,6 +694,11 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, struct rb_node *next = rb_first(root); int kernel_range = 0; + if (!kmaps) + return -1; + + machine = kmaps->machine; + while (next) { char *module; @@ -1025,9 +1033,12 @@ static bool filename_from_kallsyms_filename(char *filename, static int validate_kcore_modules(const char *kallsyms_filename, struct map *map) { - struct map_groups *kmaps = map__kmap(map)->kmaps; + struct map_groups *kmaps = map__kmaps(map); char modules_filename[PATH_MAX]; + if (!kmaps) + return -EINVAL; + if (!filename_from_kallsyms_filename(modules_filename, "modules", kallsyms_filename)) return -EINVAL; @@ -1043,6 +1054,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename, { struct kmap *kmap = map__kmap(map); + if (!kmap) + return -EINVAL; + if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { u64 start; @@ -1081,8 +1095,8 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) static int dso__load_kcore(struct dso *dso, struct map *map, const char *kallsyms_filename) { - struct map_groups *kmaps = map__kmap(map)->kmaps; - struct machine *machine = kmaps->machine; + struct map_groups *kmaps = map__kmaps(map); + struct machine *machine; struct kcore_mapfn_data md; struct map *old_map, *new_map, *replacement_map = NULL; bool is_64_bit; @@ -1090,6 +1104,11 @@ static int dso__load_kcore(struct dso *dso, struct map *map, char kcore_filename[PATH_MAX]; struct symbol *sym; + if (!kmaps) + return -EINVAL; + + machine = kmaps->machine; + /* This function requires that the map is the kernel map */ if (map != machine->vmlinux_maps[map->type]) return -EINVAL; @@ -1202,6 +1221,9 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) struct kmap *kmap = map__kmap(map); u64 addr; + if (!kmap) + return -1; + if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) return 0; |
