diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-08 01:00:49 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-08 19:58:35 (GMT) |
commit | 47d2261a3fa71cde24263559a4219a25e50d8c89 (patch) | |
tree | 28774d5b330ccf1b777a3af222d8356918328013 /tools/perf/util | |
parent | fb7f27080adc65cd5f341bdf56a1d0c14f316c1b (diff) | |
parent | 5fb9d37f27351e42f002e372074249f92cbdf815 (diff) | |
download | linux-fsl-qoriq-47d2261a3fa71cde24263559a4219a25e50d8c89.tar.xz |
Merge branch 'merge' into sdk-v1.6.x
This reverts v3.13-rc3+ (78fd82238d0e5716) to v3.12, except for
commits which I noticed which appear relevant to the SDK.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Conflicts:
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/e500.c
arch/powerpc/kvm/e500mc.c
arch/powerpc/sysdev/fsl_soc.h
drivers/Kconfig
drivers/cpufreq/ppc-corenet-cpufreq.c
drivers/dma/fsldma.c
drivers/dma/s3c24xx-dma.c
drivers/misc/Makefile
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mtd/devices/m25p80.c
drivers/net/ethernet/freescale/gianfar.h
drivers/platform/Kconfig
drivers/platform/Makefile
drivers/spi/spi-fsl-espi.c
include/crypto/algapi.h
include/linux/netdev_features.h
include/linux/skbuff.h
include/net/ip.h
net/core/ethtool.c
Diffstat (limited to 'tools/perf/util')
82 files changed, 1383 insertions, 3830 deletions
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 39f1750..15a77b7 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN @@ -19,9 +19,6 @@ if test -d ../../.git -o -f ../../.git then TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null ) CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID" -elif test -f ../../PERF-VERSION-FILE -then - TAG=$(cut -d' ' -f3 ../../PERF-VERSION-FILE | sed -e 's/\"//g') fi if test -z "$TAG" then @@ -43,7 +40,7 @@ else VC=unset fi test "$VN" = "$VC" || { - echo >&2 " PERF_VERSION = $VN" + echo >&2 "PERF_VERSION = $VN" echo "#define PERF_VERSION \"$VN\"" >$GVF } diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index cf6242c..7eae548 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -825,16 +825,20 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, dl->ops.target.offset = dl->ops.target.addr - map__rip_2objdump(map, sym->start); - /* kcore has no symbols, so add the call target name */ + /* + * kcore has no symbols, so add the call target name if it is on the + * same map. + */ if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) { - struct addr_map_symbol target = { - .map = map, - .addr = dl->ops.target.addr, - }; - - if (!map_groups__find_ams(&target, NULL) && - target.sym->start == target.al_addr) - dl->ops.target.name = strdup(target.sym->name); + struct symbol *s; + u64 ip = dl->ops.target.addr; + + if (ip >= map->start && ip <= map->end) { + ip = map->map_ip(map, ip); + s = map__find_symbol(map, ip, NULL); + if (s && s->start == ip) + dl->ops.target.name = strdup(s->name); + } } disasm__add(¬es->src->source, dl); @@ -875,8 +879,6 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) FILE *file; int err = 0; char symfs_filename[PATH_MAX]; - struct kcore_extract kce; - bool delete_extract = false; if (filename) { snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", @@ -938,23 +940,6 @@ fallback: pr_debug("annotating [%p] %30s : [%p] %30s\n", dso, dso->long_name, sym, sym->name); - if (dso__is_kcore(dso)) { - kce.kcore_filename = symfs_filename; - kce.addr = map__rip_2objdump(map, sym->start); - kce.offs = sym->start; - kce.len = sym->end + 1 - sym->start; - if (!kcore_extract__create(&kce)) { - delete_extract = true; - strlcpy(symfs_filename, kce.extract_filename, - sizeof(symfs_filename)); - if (free_filename) { - free(filename); - free_filename = false; - } - filename = symfs_filename; - } - } - snprintf(command, sizeof(command), "%s %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 @@ -987,8 +972,6 @@ fallback: pclose(file); out_free_filename: - if (delete_extract) - kcore_extract__delete(&kce); if (free_filename) free(filename); return err; @@ -1087,7 +1070,7 @@ static void symbol__free_source_line(struct symbol *sym, int len) (sizeof(src_line->p) * (src_line->nr_pcnt - 1)); for (i = 0; i < len; i++) { - free_srcline(src_line->path); + free(src_line->path); src_line = (void *)src_line + sizeof_src_line; } @@ -1098,11 +1081,13 @@ static void symbol__free_source_line(struct symbol *sym, int len) /* Get the filename:line for the colored entries */ static int symbol__get_source_line(struct symbol *sym, struct map *map, struct perf_evsel *evsel, - struct rb_root *root, int len) + struct rb_root *root, int len, + const char *filename) { u64 start; int i, k; int evidx = evsel->idx; + char cmd[PATH_MAX * 2]; struct source_line *src_line; struct annotation *notes = symbol__annotation(sym); struct sym_hist *h = annotation__histogram(notes, evidx); @@ -1130,7 +1115,10 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, start = map__rip_2objdump(map, sym->start); for (i = 0; i < len; i++) { + char *path = NULL; + size_t line_len; u64 offset; + FILE *fp; double percent_max = 0.0; src_line->nr_pcnt = nr_pcnt; @@ -1147,9 +1135,23 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, goto next; offset = start + i; - src_line->path = get_srcline(map->dso, offset); + sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset); + fp = popen(cmd, "r"); + if (!fp) + goto next; + + if (getline(&path, &line_len, fp) < 0 || !line_len) + goto next_close; + + src_line->path = malloc(sizeof(char) * line_len + 1); + if (!src_line->path) + goto next_close; + + strcpy(src_line->path, path); insert_source_line(&tmp_root, src_line); + next_close: + pclose(fp); next: src_line = (void *)src_line + sizeof_src_line; } @@ -1190,7 +1192,7 @@ static void print_summary(struct rb_root *root, const char *filename) path = src_line->path; color = get_percent_color(percent_max); - color_fprintf(stdout, color, " %s\n", path); + color_fprintf(stdout, color, " %s", path); node = rb_next(node); } @@ -1354,6 +1356,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, bool full_paths, int min_pcnt, int max_lines) { struct dso *dso = map->dso; + const char *filename = dso->long_name; struct rb_root source_line = RB_ROOT; u64 len; @@ -1363,8 +1366,9 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, len = symbol__size(sym); if (print_lines) { - symbol__get_source_line(sym, map, evsel, &source_line, len); - print_summary(&source_line, dso->long_name); + symbol__get_source_line(sym, map, evsel, &source_line, + len, filename); + print_summary(&source_line, filename); } symbol__annotate_printf(sym, map, evsel, full_paths, diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 834b7b5..af75515 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -150,7 +150,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, struct perf_evsel *evsel, bool print_lines, bool full_paths, int min_pcnt, int max_lines); -#ifdef HAVE_SLANG_SUPPORT +#ifdef SLANG_SUPPORT int symbol__tui_annotate(struct symbol *sym, struct map *map, struct perf_evsel *evsel, struct hist_browser_timer *hbt); @@ -165,6 +165,30 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, } #endif +#ifdef GTK2_SUPPORT +int symbol__gtk_annotate(struct symbol *sym, struct map *map, + struct perf_evsel *evsel, + struct hist_browser_timer *hbt); + +static inline int hist_entry__gtk_annotate(struct hist_entry *he, + struct perf_evsel *evsel, + struct hist_browser_timer *hbt) +{ + return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt); +} + +void perf_gtk__show_annotations(void); +#else +static inline int hist_entry__gtk_annotate(struct hist_entry *he __maybe_unused, + struct perf_evsel *evsel __maybe_unused, + struct hist_browser_timer *hbt __maybe_unused) +{ + return 0; +} + +static inline void perf_gtk__show_annotations(void) {} +#endif + extern const char *disassembler_style; #endif /* __PERF_ANNOTATE_H */ diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index a92770c..7ded71d 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -89,14 +89,14 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf) return raw - build_id; } -char *dso__build_id_filename(struct dso *dso, char *bf, size_t size) +char *dso__build_id_filename(struct dso *self, char *bf, size_t size) { char build_id_hex[BUILD_ID_SIZE * 2 + 1]; - if (!dso->has_build_id) + if (!self->has_build_id) return NULL; - build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex); + build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex); if (bf == NULL) { if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir, build_id_hex, build_id_hex + 2) < 0) diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 929f28a..a811f5c 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h @@ -10,9 +10,10 @@ extern struct perf_tool build_id__mark_dso_hit_ops; struct dso; int build_id__sprintf(const u8 *build_id, int len, char *bf); -char *dso__build_id_filename(struct dso *dso, char *bf, size_t size); +char *dso__build_id_filename(struct dso *self, char *bf, size_t size); int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine); + #endif diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 7b176dd..26e3672 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -70,7 +70,8 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2 extern char *perf_pathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); -/* Matches the libc/libbsd function attribute so we declare this unconditionally: */ +#ifndef HAVE_STRLCPY extern size_t strlcpy(char *dest, const char *src, size_t size); +#endif #endif /* __PERF_CACHE_H */ diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index e3970e3..482f680 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -21,6 +21,12 @@ __thread struct callchain_cursor callchain_cursor; +#define chain_for_each_child(child, parent) \ + list_for_each_entry(child, &parent->children, siblings) + +#define chain_for_each_child_safe(child, next, parent) \ + list_for_each_entry_safe(child, next, &parent->children, siblings) + static void rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, enum chain_mode mode) @@ -65,16 +71,10 @@ static void __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, u64 min_hit) { - struct rb_node *n; struct callchain_node *child; - n = rb_first(&node->rb_root_in); - while (n) { - child = rb_entry(n, struct callchain_node, rb_node_in); - n = rb_next(n); - + chain_for_each_child(child, node) __sort_chain_flat(rb_root, child, min_hit); - } if (node->hit && node->hit >= min_hit) rb_insert_callchain(rb_root, node, CHAIN_FLAT); @@ -94,16 +94,11 @@ sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root, static void __sort_chain_graph_abs(struct callchain_node *node, u64 min_hit) { - struct rb_node *n; struct callchain_node *child; node->rb_root = RB_ROOT; - n = rb_first(&node->rb_root_in); - - while (n) { - child = rb_entry(n, struct callchain_node, rb_node_in); - n = rb_next(n); + chain_for_each_child(child, node) { __sort_chain_graph_abs(child, min_hit); if (callchain_cumul_hits(child) >= min_hit) rb_insert_callchain(&node->rb_root, child, @@ -122,18 +117,13 @@ sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root, static void __sort_chain_graph_rel(struct callchain_node *node, double min_percent) { - struct rb_node *n; struct callchain_node *child; u64 min_hit; node->rb_root = RB_ROOT; min_hit = ceil(node->children_hit * min_percent); - n = rb_first(&node->rb_root_in); - while (n) { - child = rb_entry(n, struct callchain_node, rb_node_in); - n = rb_next(n); - + chain_for_each_child(child, node) { __sort_chain_graph_rel(child, min_percent); if (callchain_cumul_hits(child) >= min_hit) rb_insert_callchain(&node->rb_root, child, @@ -183,26 +173,19 @@ create_child(struct callchain_node *parent, bool inherit_children) return NULL; } new->parent = parent; + INIT_LIST_HEAD(&new->children); INIT_LIST_HEAD(&new->val); if (inherit_children) { - struct rb_node *n; - struct callchain_node *child; - - new->rb_root_in = parent->rb_root_in; - parent->rb_root_in = RB_ROOT; + struct callchain_node *next; - n = rb_first(&new->rb_root_in); - while (n) { - child = rb_entry(n, struct callchain_node, rb_node_in); - child->parent = new; - n = rb_next(n); - } + list_splice(&parent->children, &new->children); + INIT_LIST_HEAD(&parent->children); - /* make it the first child */ - rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node); - rb_insert_color(&new->rb_node_in, &parent->rb_root_in); + chain_for_each_child(next, new) + next->parent = new; } + list_add_tail(&new->siblings, &parent->children); return new; } @@ -240,7 +223,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor) } } -static struct callchain_node * +static void add_child(struct callchain_node *parent, struct callchain_cursor *cursor, u64 period) @@ -252,19 +235,6 @@ add_child(struct callchain_node *parent, new->children_hit = 0; new->hit = period; - return new; -} - -static s64 match_chain(struct callchain_cursor_node *node, - struct callchain_list *cnode) -{ - struct symbol *sym = node->sym; - - if (cnode->ms.sym && sym && - callchain_param.key == CCKEY_FUNCTION) - return cnode->ms.sym->start - sym->start; - else - return cnode->ip - node->ip; } /* @@ -302,33 +272,9 @@ split_add_child(struct callchain_node *parent, /* create a new child for the new branch if any */ if (idx_total < cursor->nr) { - struct callchain_node *first; - struct callchain_list *cnode; - struct callchain_cursor_node *node; - struct rb_node *p, **pp; - parent->hit = 0; + add_child(parent, cursor, period); parent->children_hit += period; - - node = callchain_cursor_current(cursor); - new = add_child(parent, cursor, period); - - /* - * This is second child since we moved parent's children - * to new (first) child above. - */ - p = parent->rb_root_in.rb_node; - first = rb_entry(p, struct callchain_node, rb_node_in); - cnode = list_first_entry(&first->val, struct callchain_list, - list); - - if (match_chain(node, cnode) < 0) - pp = &p->rb_left; - else - pp = &p->rb_right; - - rb_link_node(&new->rb_node_in, p, pp); - rb_insert_color(&new->rb_node_in, &parent->rb_root_in); } else { parent->hit = period; } @@ -345,40 +291,16 @@ append_chain_children(struct callchain_node *root, u64 period) { struct callchain_node *rnode; - struct callchain_cursor_node *node; - struct rb_node **p = &root->rb_root_in.rb_node; - struct rb_node *parent = NULL; - - node = callchain_cursor_current(cursor); - if (!node) - return; /* lookup in childrens */ - while (*p) { - s64 ret; - struct callchain_list *cnode; + chain_for_each_child(rnode, root) { + unsigned int ret = append_chain(rnode, cursor, period); - parent = *p; - rnode = rb_entry(parent, struct callchain_node, rb_node_in); - cnode = list_first_entry(&rnode->val, struct callchain_list, - list); - - /* just check first entry */ - ret = match_chain(node, cnode); - if (ret == 0) { - append_chain(rnode, cursor, period); + if (!ret) goto inc_children_hit; - } - - if (ret < 0) - p = &parent->rb_left; - else - p = &parent->rb_right; } /* nothing in children, add to the current node */ - rnode = add_child(root, cursor, period); - rb_link_node(&rnode->rb_node_in, parent, p); - rb_insert_color(&rnode->rb_node_in, &root->rb_root_in); + add_child(root, cursor, period); inc_children_hit: root->children_hit += period; @@ -403,20 +325,28 @@ append_chain(struct callchain_node *root, */ list_for_each_entry(cnode, &root->val, list) { struct callchain_cursor_node *node; + struct symbol *sym; node = callchain_cursor_current(cursor); if (!node) break; - if (match_chain(node, cnode) != 0) + sym = node->sym; + + if (cnode->ms.sym && sym && + callchain_param.key == CCKEY_FUNCTION) { + if (cnode->ms.sym->start != sym->start) + break; + } else if (cnode->ip != node->ip) break; - found = true; + if (!found) + found = true; callchain_cursor_advance(cursor); } - /* matches not, relay no the parent */ + /* matches not, relay on the parent */ if (!found) { cursor->curr = curr_snap; cursor->pos = start; @@ -465,9 +395,8 @@ merge_chain_branch(struct callchain_cursor *cursor, struct callchain_node *dst, struct callchain_node *src) { struct callchain_cursor_node **old_last = cursor->last; - struct callchain_node *child; + struct callchain_node *child, *next_child; struct callchain_list *list, *next_list; - struct rb_node *n; int old_pos = cursor->nr; int err = 0; @@ -483,16 +412,12 @@ merge_chain_branch(struct callchain_cursor *cursor, append_chain_children(dst, cursor, src->hit); } - n = rb_first(&src->rb_root_in); - while (n) { - child = container_of(n, struct callchain_node, rb_node_in); - n = rb_next(n); - rb_erase(&child->rb_node_in, &src->rb_root_in); - + chain_for_each_child_safe(child, next_child, src) { err = merge_chain_branch(cursor, dst, child); if (err) break; + list_del(&child->siblings); free(child); } diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 4f7f989..9e99060 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -21,11 +21,11 @@ enum chain_order { struct callchain_node { struct callchain_node *parent; + struct list_head siblings; + struct list_head children; struct list_head val; - struct rb_node rb_node_in; /* to insert nodes in an rbtree */ - struct rb_node rb_node; /* to sort nodes in an output tree */ - struct rb_root rb_root_in; /* input tree of children */ - struct rb_root rb_root; /* sorted output tree of children */ + struct rb_node rb_node; /* to sort nodes in an rbtree */ + struct rb_root rb_root; /* sorted tree of children */ unsigned int val_nr; u64 hit; u64 children_hit; @@ -86,12 +86,13 @@ extern __thread struct callchain_cursor callchain_cursor; static inline void callchain_init(struct callchain_root *root) { + INIT_LIST_HEAD(&root->node.siblings); + INIT_LIST_HEAD(&root->node.children); INIT_LIST_HEAD(&root->node.val); root->node.parent = NULL; root->node.hit = 0; root->node.children_hit = 0; - root->node.rb_root_in = RB_ROOT; root->max_depth = 0; } diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 66e44a5..11e46da 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c @@ -318,15 +318,8 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent) return r; } -int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) +int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent) { - va_list args; - double percent; - const char *color; - - va_start(args, fmt); - percent = va_arg(args, double); - va_end(args); - color = get_percent_color(percent); + const char *color = get_percent_color(percent); return color_snprintf(bf, size, color, fmt, percent); } diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h index fced384..dea082b 100644 --- a/tools/perf/util/color.h +++ b/tools/perf/util/color.h @@ -39,7 +39,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); -int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); +int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent); int percent_color_fprintf(FILE *fp, const char *fmt, double percent); const char *get_percent_color(double percent); diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c deleted file mode 100644 index ee0df0e..0000000 --- a/tools/perf/util/comm.c +++ /dev/null @@ -1,121 +0,0 @@ -#include "comm.h" -#include "util.h" -#include <stdlib.h> -#include <stdio.h> - -struct comm_str { - char *str; - struct rb_node rb_node; - int ref; -}; - -/* Should perhaps be moved to struct machine */ -static struct rb_root comm_str_root; - -static void comm_str__get(struct comm_str *cs) -{ - cs->ref++; -} - -static void comm_str__put(struct comm_str *cs) -{ - if (!--cs->ref) { - rb_erase(&cs->rb_node, &comm_str_root); - free(cs->str); - free(cs); - } -} - -static struct comm_str *comm_str__alloc(const char *str) -{ - struct comm_str *cs; - - cs = zalloc(sizeof(*cs)); - if (!cs) - return NULL; - - cs->str = strdup(str); - if (!cs->str) { - free(cs); - return NULL; - } - - return cs; -} - -static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root) -{ - struct rb_node **p = &root->rb_node; - struct rb_node *parent = NULL; - struct comm_str *iter, *new; - int cmp; - - while (*p != NULL) { - parent = *p; - iter = rb_entry(parent, struct comm_str, rb_node); - - cmp = strcmp(str, iter->str); - if (!cmp) - return iter; - - if (cmp < 0) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; - } - - new = comm_str__alloc(str); - if (!new) - return NULL; - - rb_link_node(&new->rb_node, parent, p); - rb_insert_color(&new->rb_node, root); - - return new; -} - -struct comm *comm__new(const char *str, u64 timestamp) -{ - struct comm *comm = zalloc(sizeof(*comm)); - - if (!comm) - return NULL; - - comm->start = timestamp; - - comm->comm_str = comm_str__findnew(str, &comm_str_root); - if (!comm->comm_str) { - free(comm); - return NULL; - } - - comm_str__get(comm->comm_str); - - return comm; -} - -void comm__override(struct comm *comm, const char *str, u64 timestamp) -{ - struct comm_str *old = comm->comm_str; - - comm->comm_str = comm_str__findnew(str, &comm_str_root); - if (!comm->comm_str) { - comm->comm_str = old; - return; - } - - comm->start = timestamp; - comm_str__get(comm->comm_str); - comm_str__put(old); -} - -void comm__free(struct comm *comm) -{ - comm_str__put(comm->comm_str); - free(comm); -} - -const char *comm__str(const struct comm *comm) -{ - return comm->comm_str->str; -} diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h deleted file mode 100644 index 7a86e56..0000000 --- a/tools/perf/util/comm.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __PERF_COMM_H -#define __PERF_COMM_H - -#include "../perf.h" -#include <linux/rbtree.h> -#include <linux/list.h> - -struct comm_str; - -struct comm { - struct comm_str *comm_str; - u64 start; - struct list_head list; -}; - -void comm__free(struct comm *comm); -struct comm *comm__new(const char *str, u64 timestamp); -const char *comm__str(const struct comm *comm); -void comm__override(struct comm *comm, const char *str, u64 timestamp); - -#endif /* __PERF_COMM_H */ diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index a9b48c4..beb8cf9 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -1,5 +1,5 @@ #include "util.h" -#include "fs.h" +#include "sysfs.h" #include "../perf.h" #include "cpumap.h" #include <assert.h> @@ -216,7 +216,7 @@ int cpu_map__get_socket(struct cpu_map *map, int idx) cpu = map->map[idx]; - mnt = sysfs__mountpoint(); + mnt = sysfs_find_mountpoint(); if (!mnt) return -1; @@ -279,7 +279,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx) cpu = map->map[idx]; - mnt = sysfs__mountpoint(); + mnt = sysfs_find_mountpoint(); if (!mnt) return -1; diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c deleted file mode 100644 index 7d09faf..0000000 --- a/tools/perf/util/data.c +++ /dev/null @@ -1,120 +0,0 @@ -#include <linux/compiler.h> -#include <linux/kernel.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> - -#include "data.h" -#include "util.h" - -static bool check_pipe(struct perf_data_file *file) -{ - struct stat st; - bool is_pipe = false; - int fd = perf_data_file__is_read(file) ? - STDIN_FILENO : STDOUT_FILENO; - - if (!file->path) { - if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) - is_pipe = true; - } else { - if (!strcmp(file->path, "-")) - is_pipe = true; - } - - if (is_pipe) - file->fd = fd; - - return file->is_pipe = is_pipe; -} - -static int check_backup(struct perf_data_file *file) -{ - struct stat st; - - if (!stat(file->path, &st) && st.st_size) { - /* TODO check errors properly */ - char oldname[PATH_MAX]; - snprintf(oldname, sizeof(oldname), "%s.old", - file->path); - unlink(oldname); - rename(file->path, oldname); - } - - return 0; -} - -static int open_file_read(struct perf_data_file *file) -{ - struct stat st; - int fd; - - fd = open(file->path, O_RDONLY); - if (fd < 0) { - int err = errno; - - pr_err("failed to open %s: %s", file->path, strerror(err)); - if (err == ENOENT && !strcmp(file->path, "perf.data")) - pr_err(" (try 'perf record' first)"); - pr_err("\n"); - return -err; - } - - if (fstat(fd, &st) < 0) - goto out_close; - - if (!file->force && st.st_uid && (st.st_uid != geteuid())) { - pr_err("file %s not owned by current user or root\n", - file->path); - goto out_close; - } - - if (!st.st_size) { - pr_info("zero-sized file (%s), nothing to do!\n", - file->path); - goto out_close; - } - - file->size = st.st_size; - return fd; - - out_close: - close(fd); - return -1; -} - -static int open_file_write(struct perf_data_file *file) -{ - if (check_backup(file)) - return -1; - - return open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); -} - -static int open_file(struct perf_data_file *file) -{ - int fd; - - fd = perf_data_file__is_read(file) ? - open_file_read(file) : open_file_write(file); - - file->fd = fd; - return fd < 0 ? -1 : 0; -} - -int perf_data_file__open(struct perf_data_file *file) -{ - if (check_pipe(file)) - return 0; - - if (!file->path) - file->path = "perf.data"; - - return open_file(file); -} - -void perf_data_file__close(struct perf_data_file *file) -{ - close(file->fd); -} diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h deleted file mode 100644 index 8c2df80..0000000 --- a/tools/perf/util/data.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __PERF_DATA_H -#define __PERF_DATA_H - -#include <stdbool.h> - -enum perf_data_mode { - PERF_DATA_MODE_WRITE, - PERF_DATA_MODE_READ, -}; - -struct perf_data_file { - const char *path; - int fd; - bool is_pipe; - bool force; - unsigned long size; - enum perf_data_mode mode; -}; - -static inline bool perf_data_file__is_read(struct perf_data_file *file) -{ - return file->mode == PERF_DATA_MODE_READ; -} - -static inline bool perf_data_file__is_write(struct perf_data_file *file) -{ - return file->mode == PERF_DATA_MODE_WRITE; -} - -static inline int perf_data_file__is_pipe(struct perf_data_file *file) -{ - return file->is_pipe; -} - -static inline int perf_data_file__fd(struct perf_data_file *file) -{ - return file->fd; -} - -static inline unsigned long perf_data_file__size(struct perf_data_file *file) -{ - return file->size; -} - -int perf_data_file__open(struct perf_data_file *file); -void perf_data_file__close(struct perf_data_file *file); - -#endif /* __PERF_DATA_H */ diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index af4c687c..e3c1ff8 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -7,20 +7,19 @@ char dso__symtab_origin(const struct dso *dso) { static const char origin[] = { - [DSO_BINARY_TYPE__KALLSYMS] = 'k', - [DSO_BINARY_TYPE__VMLINUX] = 'v', - [DSO_BINARY_TYPE__JAVA_JIT] = 'j', - [DSO_BINARY_TYPE__DEBUGLINK] = 'l', - [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', - [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f', - [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u', - [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o', - [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', - [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', - [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', - [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', - [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', - [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', + [DSO_BINARY_TYPE__KALLSYMS] = 'k', + [DSO_BINARY_TYPE__VMLINUX] = 'v', + [DSO_BINARY_TYPE__JAVA_JIT] = 'j', + [DSO_BINARY_TYPE__DEBUGLINK] = 'l', + [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', + [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f', + [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u', + [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', + [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', + [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', + [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', + [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', + [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', }; if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND) @@ -65,28 +64,6 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, symbol_conf.symfs, dso->long_name); break; - case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: - { - char *last_slash; - size_t len; - size_t dir_size; - - last_slash = dso->long_name + dso->long_name_len; - while (last_slash != dso->long_name && *last_slash != '/') - last_slash--; - - len = scnprintf(file, size, "%s", symbol_conf.symfs); - dir_size = last_slash - dso->long_name + 2; - if (dir_size > (size - len)) { - ret = -1; - break; - } - len += scnprintf(file + len, dir_size, "%s", dso->long_name); - len += scnprintf(file + len , size - len, ".debug%s", - last_slash); - break; - } - case DSO_BINARY_TYPE__BUILDID_DEBUGINFO: if (!dso->has_build_id) { ret = -1; @@ -450,7 +427,6 @@ struct dso *dso__new(const char *name) dso->rel = 0; dso->sorted_by_name = 0; dso->has_build_id = 0; - dso->has_srcline = 1; dso->kernel = DSO_TYPE_USER; dso->needs_swap = DSO_SWAP__UNSET; INIT_LIST_HEAD(&dso->node); diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 9ac666a..b793053 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -6,7 +6,6 @@ #include <stdbool.h> #include "types.h" #include "map.h" -#include "build-id.h" enum dso_binary_type { DSO_BINARY_TYPE__KALLSYMS = 0, @@ -24,7 +23,6 @@ enum dso_binary_type { DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, DSO_BINARY_TYPE__KCORE, DSO_BINARY_TYPE__GUEST_KCORE, - DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, DSO_BINARY_TYPE__NOT_FOUND, }; @@ -83,7 +81,6 @@ struct dso { enum dso_binary_type data_type; u8 adjust_symbols:1; u8 has_build_id:1; - u8 has_srcline:1; u8 hit:1; u8 annotate_warned:1; u8 sname_alloc:1; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index bb788c1..49096ea 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -170,8 +170,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, union perf_event *event, pid_t pid, pid_t tgid, perf_event__handler_t process, - struct machine *machine, - bool mmap_data) + struct machine *machine) { char filename[PATH_MAX]; FILE *fp; @@ -189,6 +188,10 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, } event->header.type = PERF_RECORD_MMAP; + /* + * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c + */ + event->header.misc = PERF_RECORD_MISC_USER; while (1) { char bf[BUFSIZ]; @@ -209,22 +212,12 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, &event->mmap.start, &event->mmap.len, prot, &event->mmap.pgoff, execname); - /* - * Anon maps don't have the execname. - */ - if (n < 4) - continue; - /* - * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c - */ - event->header.misc = PERF_RECORD_MISC_USER; - if (prot[2] != 'x') { - if (!mmap_data || prot[0] != 'r') - continue; + if (n != 5) + continue; - event->header.misc |= PERF_RECORD_MISC_MMAP_DATA; - } + if (prot[2] != 'x') + continue; if (!strcmp(execname, "")) strcpy(execname, anonstr); @@ -311,21 +304,20 @@ static int __event__synthesize_thread(union perf_event *comm_event, pid_t pid, int full, perf_event__handler_t process, struct perf_tool *tool, - struct machine *machine, bool mmap_data) + struct machine *machine) { pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full, process, machine); if (tgid == -1) return -1; return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, - process, machine, mmap_data); + process, machine); } int perf_event__synthesize_thread_map(struct perf_tool *tool, struct thread_map *threads, perf_event__handler_t process, - struct machine *machine, - bool mmap_data) + struct machine *machine) { union perf_event *comm_event, *mmap_event; int err = -1, thread, j; @@ -342,8 +334,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, for (thread = 0; thread < threads->nr; ++thread) { if (__event__synthesize_thread(comm_event, mmap_event, threads->map[thread], 0, - process, tool, machine, - mmap_data)) { + process, tool, machine)) { err = -1; break; } @@ -365,10 +356,10 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, /* if not, generate events for it */ if (need_leader && - __event__synthesize_thread(comm_event, mmap_event, - comm_event->comm.pid, 0, - process, tool, machine, - mmap_data)) { + __event__synthesize_thread(comm_event, + mmap_event, + comm_event->comm.pid, 0, + process, tool, machine)) { err = -1; break; } @@ -383,7 +374,7 @@ out: int perf_event__synthesize_threads(struct perf_tool *tool, perf_event__handler_t process, - struct machine *machine, bool mmap_data) + struct machine *machine) { DIR *proc; struct dirent dirent, *next; @@ -413,7 +404,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, * one thread couldn't be synthesized. */ __event__synthesize_thread(comm_event, mmap_event, pid, 1, - process, tool, machine, mmap_data); + process, tool, machine); } err = 0; @@ -521,55 +512,52 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp) int perf_event__process_comm(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample, + struct perf_sample *sample __maybe_unused, struct machine *machine) { - return machine__process_comm_event(machine, event, sample); + return machine__process_comm_event(machine, event); } int perf_event__process_lost(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample, + struct perf_sample *sample __maybe_unused, struct machine *machine) { - return machine__process_lost_event(machine, event, sample); + return machine__process_lost_event(machine, event); } size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) { - return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", + return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", event->mmap.pid, event->mmap.tid, event->mmap.start, - event->mmap.len, event->mmap.pgoff, - (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', - event->mmap.filename); + event->mmap.len, event->mmap.pgoff, event->mmap.filename); } size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) { return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 - " %02x:%02x %"PRIu64" %"PRIu64"]: %c %s\n", + " %02x:%02x %"PRIu64" %"PRIu64"]: %s\n", event->mmap2.pid, event->mmap2.tid, event->mmap2.start, event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, event->mmap2.min, event->mmap2.ino, event->mmap2.ino_generation, - (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', event->mmap2.filename); } int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample, + struct perf_sample *sample __maybe_unused, struct machine *machine) { - return machine__process_mmap_event(machine, event, sample); + return machine__process_mmap_event(machine, event); } int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample, + struct perf_sample *sample __maybe_unused, struct machine *machine) { - return machine__process_mmap2_event(machine, event, sample); + return machine__process_mmap2_event(machine, event); } size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) @@ -581,18 +569,18 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) int perf_event__process_fork(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample, + struct perf_sample *sample __maybe_unused, struct machine *machine) { - return machine__process_fork_event(machine, event, sample); + return machine__process_fork_event(machine, event); } int perf_event__process_exit(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample, + struct perf_sample *sample __maybe_unused, struct machine *machine) { - return machine__process_exit_event(machine, event, sample); + return machine__process_exit_event(machine, event); } size_t perf_event__fprintf(union perf_event *event, FILE *fp) @@ -623,21 +611,21 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp) int perf_event__process(struct perf_tool *tool __maybe_unused, union perf_event *event, - struct perf_sample *sample, + struct perf_sample *sample __maybe_unused, struct machine *machine) { - return machine__process_event(machine, event, sample); + return machine__process_event(machine, event); } -void thread__find_addr_map(struct thread *thread, +void thread__find_addr_map(struct thread *self, struct machine *machine, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al) { - struct map_groups *mg = &thread->mg; + struct map_groups *mg = &self->mg; bool load_map = false; - al->thread = thread; + al->thread = self; al->addr = addr; al->cpumode = cpumode; al->filtered = false; @@ -733,10 +721,10 @@ int perf_event__preprocess_sample(const union perf_event *event, return -1; if (symbol_conf.comm_list && - !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) + !strlist__has_entry(symbol_conf.comm_list, thread->comm)) goto out_filtered; - dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); + dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid); /* * Have we already created the kernel maps for this machine? * diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 30fec99..c67ecc4 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -61,12 +61,6 @@ struct read_event { u64 id; }; -struct throttle_event { - struct perf_event_header header; - u64 time; - u64 id; - u64 stream_id; -}; #define PERF_SAMPLE_MASK \ (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ @@ -75,9 +69,6 @@ struct throttle_event { PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \ PERF_SAMPLE_IDENTIFIER) -/* perf sample has 16 bits size limit */ -#define PERF_SAMPLE_MAX_SIZE (1 << 16) - struct sample_event { struct perf_event_header header; u64 array[]; @@ -120,7 +111,6 @@ struct perf_sample { u64 stream_id; u64 period; u64 weight; - u64 transaction; u32 cpu; u32 raw_size; u64 data_src; @@ -187,7 +177,6 @@ union perf_event { struct fork_event fork; struct lost_event lost; struct read_event read; - struct throttle_event throttle; struct sample_event sample; struct attr_event attr; struct event_type_event event_type; @@ -208,10 +197,10 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool, int perf_event__synthesize_thread_map(struct perf_tool *tool, struct thread_map *threads, perf_event__handler_t process, - struct machine *machine, bool mmap_data); + struct machine *machine); int perf_event__synthesize_threads(struct perf_tool *tool, perf_event__handler_t process, - struct machine *machine, bool mmap_data); + struct machine *machine); int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, perf_event__handler_t process, struct machine *machine, @@ -251,8 +240,7 @@ int perf_event__process(struct perf_tool *tool, struct machine *machine); struct addr_location; - -int perf_event__preprocess_sample(const union perf_event *event, +int perf_event__preprocess_sample(const union perf_event *self, struct machine *machine, struct addr_location *al, struct perf_sample *sample); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index bbc746a..e584cd3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -18,7 +18,6 @@ #include <unistd.h> #include "parse-events.h" -#include "parse-options.h" #include <sys/mman.h> @@ -50,18 +49,6 @@ struct perf_evlist *perf_evlist__new(void) return evlist; } -struct perf_evlist *perf_evlist__new_default(void) -{ - struct perf_evlist *evlist = perf_evlist__new(); - - if (evlist && perf_evlist__add_default(evlist)) { - perf_evlist__delete(evlist); - evlist = NULL; - } - - return evlist; -} - /** * perf_evlist__set_id_pos - set the positions of event ids. * @evlist: selected event list @@ -117,8 +104,6 @@ void perf_evlist__delete(struct perf_evlist *evlist) void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) { list_add_tail(&entry->node, &evlist->entries); - entry->idx = evlist->nr_entries; - if (!evlist->nr_entries++) perf_evlist__set_id_pos(evlist); } @@ -167,7 +152,7 @@ int perf_evlist__add_default(struct perf_evlist *evlist) event_attr_init(&attr); - evsel = perf_evsel__new(&attr); + evsel = perf_evsel__new(&attr, 0); if (evsel == NULL) goto error; @@ -192,7 +177,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist, size_t i; for (i = 0; i < nr_attrs; i++) { - evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i); + evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i); if (evsel == NULL) goto out_delete_partial_list; list_add_tail(&evsel->node, &head); @@ -251,12 +236,13 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, int perf_evlist__add_newtp(struct perf_evlist *evlist, const char *sys, const char *name, void *handler) { - struct perf_evsel *evsel = perf_evsel__newtp(sys, name); + struct perf_evsel *evsel; + evsel = perf_evsel__newtp(sys, name, evlist->nr_entries); if (evsel == NULL) return -1; - evsel->handler = handler; + evsel->handler.func = handler; perf_evlist__add(evlist, evsel); return 0; } @@ -541,7 +527,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) if ((old & md->mask) + size != ((old + size) & md->mask)) { unsigned int offset = old; unsigned int len = min(sizeof(*event), size), cpy; - void *dst = md->event_copy; + void *dst = &md->event_copy; do { cpy = min(md->mask + 1 - (offset & md->mask), len); @@ -551,7 +537,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) len -= cpy; } while (len); - event = (union perf_event *) md->event_copy; + event = &md->event_copy; } old += size; @@ -608,8 +594,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, MAP_SHARED, fd, 0); if (evlist->mmap[idx].base == MAP_FAILED) { - pr_debug2("failed to mmap perf event ring buffer, error %d\n", - errno); evlist->mmap[idx].base = NULL; return -1; } @@ -618,36 +602,9 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, return 0; } -static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, - int prot, int mask, int cpu, int thread, - int *output) +static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask) { struct perf_evsel *evsel; - - list_for_each_entry(evsel, &evlist->entries, node) { - int fd = FD(evsel, cpu, thread); - - if (*output == -1) { - *output = fd; - if (__perf_evlist__mmap(evlist, idx, prot, mask, - *output) < 0) - return -1; - } else { - if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) - return -1; - } - - if ((evsel->attr.read_format & PERF_FORMAT_ID) && - perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) - return -1; - } - - return 0; -} - -static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, - int mask) -{ int cpu, thread; int nr_cpus = cpu_map__nr(evlist->cpus); int nr_threads = thread_map__nr(evlist->threads); @@ -657,9 +614,23 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int output = -1; for (thread = 0; thread < nr_threads; thread++) { - if (perf_evlist__mmap_per_evsel(evlist, cpu, prot, mask, - cpu, thread, &output)) - goto out_unmap; + list_for_each_entry(evsel, &evlist->entries, node) { + int fd = FD(evsel, cpu, thread); + + if (output == -1) { + output = fd; + if (__perf_evlist__mmap(evlist, cpu, + prot, mask, output) < 0) + goto out_unmap; + } else { + if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0) + goto out_unmap; + } + + if ((evsel->attr.read_format & PERF_FORMAT_ID) && + perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) + goto out_unmap; + } } } @@ -671,9 +642,9 @@ out_unmap: return -1; } -static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, - int mask) +static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask) { + struct perf_evsel *evsel; int thread; int nr_threads = thread_map__nr(evlist->threads); @@ -681,9 +652,23 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, for (thread = 0; thread < nr_threads; thread++) { int output = -1; - if (perf_evlist__mmap_per_evsel(evlist, thread, prot, mask, 0, - thread, &output)) - goto out_unmap; + list_for_each_entry(evsel, &evlist->entries, node) { + int fd = FD(evsel, 0, thread); + + if (output == -1) { + output = fd; + if (__perf_evlist__mmap(evlist, thread, + prot, mask, output) < 0) + goto out_unmap; + } else { + if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0) + goto out_unmap; + } + + if ((evsel->attr.read_format & PERF_FORMAT_ID) && + perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0) + goto out_unmap; + } } return 0; @@ -694,90 +679,20 @@ out_unmap: return -1; } -static size_t perf_evlist__mmap_size(unsigned long pages) -{ - /* 512 kiB: default amount of unprivileged mlocked memory */ - if (pages == UINT_MAX) - pages = (512 * 1024) / page_size; - else if (!is_power_of_2(pages)) - return 0; - - return (pages + 1) * page_size; -} - -static long parse_pages_arg(const char *str, unsigned long min, - unsigned long max) -{ - unsigned long pages, val; - static struct parse_tag tags[] = { - { .tag = 'B', .mult = 1 }, - { .tag = 'K', .mult = 1 << 10 }, - { .tag = 'M', .mult = 1 << 20 }, - { .tag = 'G', .mult = 1 << 30 }, - { .tag = 0 }, - }; - - if (str == NULL) - return -EINVAL; - - val = parse_tag_value(str, tags); - if (val != (unsigned long) -1) { - /* we got file size value */ - pages = PERF_ALIGN(val, page_size) / page_size; - } else { - /* we got pages count value */ - char *eptr; - pages = strtoul(str, &eptr, 10); - if (*eptr != '\0') - return -EINVAL; - } - - if ((pages == 0) && (min == 0)) { - /* leave number of pages at 0 */ - } else if (pages < (1UL << 31) && !is_power_of_2(pages)) { - /* round pages up to next power of 2 */ - pages = next_pow2(pages); - pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", - pages * page_size, pages); - } - - if (pages > max) - return -EINVAL; - - return pages; -} - -int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str, - int unset __maybe_unused) -{ - unsigned int *mmap_pages = opt->value; - unsigned long max = UINT_MAX; - long pages; - - if (max < SIZE_MAX / page_size) - max = SIZE_MAX / page_size; - - pages = parse_pages_arg(str, 1, max); - if (pages < 0) { - pr_err("Invalid argument for --mmap_pages/-m\n"); - return -1; - } - - *mmap_pages = pages; - return 0; -} - -/** - * perf_evlist__mmap - Create mmaps to receive events. - * @evlist: list of events - * @pages: map length in pages - * @overwrite: overwrite older events? +/** perf_evlist__mmap - Create per cpu maps to receive events + * + * @evlist - list of events + * @pages - map length in pages + * @overwrite - overwrite older events? * - * If @overwrite is %false the user needs to signal event consumption using - * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this - * automatically. + * If overwrite is false the user needs to signal event consuption using: * - * Return: %0 on success, negative error code otherwise. + * struct perf_mmap *m = &evlist->mmap[cpu]; + * unsigned int head = perf_mmap__read_head(m); + * + * perf_mmap__write_tail(m, head) + * + * Using perf_evlist__read_on_cpu does this automatically. */ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, bool overwrite) @@ -787,6 +702,14 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, const struct thread_map *threads = evlist->threads; int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; + /* 512 kiB: default amount of unprivileged mlocked memory */ + if (pages == UINT_MAX) + pages = (512 * 1024) / page_size; + else if (!is_power_of_2(pages)) + return -EINVAL; + + mask = pages * page_size - 1; + if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) return -ENOMEM; @@ -794,9 +717,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, return -ENOMEM; evlist->overwrite = overwrite; - evlist->mmap_len = perf_evlist__mmap_size(pages); - pr_debug("mmap size %zuB\n", evlist->mmap_len); - mask = evlist->mmap_len - page_size - 1; + evlist->mmap_len = (pages + 1) * page_size; list_for_each_entry(evsel, &evlist->entries, node) { if ((evsel->attr.read_format & PERF_FORMAT_ID) && @@ -811,7 +732,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, return perf_evlist__mmap_per_cpu(evlist, prot, mask); } -int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) +int perf_evlist__create_maps(struct perf_evlist *evlist, + struct perf_target *target) { evlist->threads = thread_map__new_str(target->pid, target->tid, target->uid); @@ -819,11 +741,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) if (evlist->threads == NULL) return -1; - if (target->force_per_cpu) - evlist->cpus = cpu_map__new(target->cpu_list); - else if (target__has_task(target)) + if (perf_target__has_task(target)) evlist->cpus = cpu_map__dummy_new(); - else if (!target__has_cpu(target) && !target->uses_mmap) + else if (!perf_target__has_cpu(target) && !target->uses_mmap) evlist->cpus = cpu_map__dummy_new(); else evlist->cpus = cpu_map__new(target->cpu_list); @@ -1032,7 +952,8 @@ out_err: return err; } -int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, +int perf_evlist__prepare_workload(struct perf_evlist *evlist, + struct perf_target *target, const char *argv[], bool pipe_output, bool want_signal) { @@ -1084,7 +1005,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar exit(-1); } - if (target__none(target)) + if (perf_target__none(target)) evlist->threads->map[0] = evlist->workload.pid; close(child_ready_pipe[1]); @@ -1150,68 +1071,5 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) perf_evsel__name(evsel)); } - return printed + fprintf(fp, "\n"); -} - -int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused, - int err, char *buf, size_t size) -{ - char sbuf[128]; - - switch (err) { - case ENOENT: - scnprintf(buf, size, "%s", - "Error:\tUnable to find debugfs\n" - "Hint:\tWas your kernel was compiled with debugfs support?\n" - "Hint:\tIs the debugfs filesystem mounted?\n" - "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); - break; - case EACCES: - scnprintf(buf, size, - "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n" - "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n", - debugfs_mountpoint, debugfs_mountpoint); - break; - default: - scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf))); - break; - } - - return 0; -} - -int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, - int err, char *buf, size_t size) -{ - int printed, value; - char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); - - switch (err) { - case EACCES: - case EPERM: - printed = scnprintf(buf, size, - "Error:\t%s.\n" - "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); - - if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value)) - break; - - printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); - - if (value >= 2) { - printed += scnprintf(buf + printed, size - printed, - "For your workloads it needs to be <= 1\nHint:\t"); - } - printed += scnprintf(buf + printed, size - printed, - "For system wide tracing it needs to be set to -1"); - - printed += scnprintf(buf + printed, size - printed, - ".\nHint:\tThe current value is %d.", value); - break; - default: - scnprintf(buf, size, "%s", emsg); - break; - } - - return 0; + return printed + fprintf(fp, "\n");; } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 649d6ea..206d093 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -21,7 +21,7 @@ struct perf_mmap { void *base; int mask; unsigned int prev; - char event_copy[PERF_SAMPLE_MAX_SIZE]; + union perf_event event_copy; }; struct perf_evlist { @@ -31,7 +31,7 @@ struct perf_evlist { int nr_groups; int nr_fds; int nr_mmaps; - size_t mmap_len; + int mmap_len; int id_pos; int is_pos; u64 combined_sample_type; @@ -53,7 +53,6 @@ struct perf_evsel_str_handler { }; struct perf_evlist *perf_evlist__new(void); -struct perf_evlist *perf_evlist__new_default(void); void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, struct thread_map *threads); void perf_evlist__exit(struct perf_evlist *evlist); @@ -88,7 +87,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); -union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); +union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); @@ -99,18 +98,13 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist); bool perf_can_sample_identifier(void); void perf_evlist__config(struct perf_evlist *evlist, struct perf_record_opts *opts); -int perf_record_opts__config(struct perf_record_opts *opts); int perf_evlist__prepare_workload(struct perf_evlist *evlist, - struct target *target, + struct perf_target *target, const char *argv[], bool pipe_output, bool want_signal); int perf_evlist__start_workload(struct perf_evlist *evlist); -int perf_evlist__parse_mmap_pages(const struct option *opt, - const char *str, - int unset); - int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, bool overwrite); void perf_evlist__munmap(struct perf_evlist *evlist); @@ -134,7 +128,8 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist, evlist->threads = threads; } -int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); +int perf_evlist__create_maps(struct perf_evlist *evlist, + struct perf_target *target); void perf_evlist__delete_maps(struct perf_evlist *evlist); int perf_evlist__apply_filters(struct perf_evlist *evlist); @@ -170,13 +165,10 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist) size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); -int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size); -int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); - static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) { struct perf_event_mmap_page *pc = mm->base; - int head = ACCESS_ONCE(pc->data_head); + int head = pc->data_head; rmb(); return head; } @@ -189,7 +181,7 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md, /* * ensure all reads are done before we write the tail out. */ - mb(); + /* mb(); */ pc->data_tail = tail; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 46dd4c2..9f1ef9b 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -168,7 +168,7 @@ void perf_evsel__init(struct perf_evsel *evsel, perf_evsel__calc_id_pos(evsel); } -struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) +struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) { struct perf_evsel *evsel = zalloc(sizeof(*evsel)); @@ -219,7 +219,7 @@ out: return format; } -struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) +struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx) { struct perf_evsel *evsel = zalloc(sizeof(*evsel)); @@ -645,7 +645,7 @@ void perf_evsel__config(struct perf_evsel *evsel, } } - if (target__has_cpu(&opts->target) || opts->target.force_per_cpu) + if (perf_target__has_cpu(&opts->target)) perf_evsel__set_sample_bit(evsel, CPU); if (opts->period) @@ -653,7 +653,7 @@ void perf_evsel__config(struct perf_evsel *evsel, if (!perf_missing_features.sample_id_all && (opts->sample_time || !opts->no_inherit || - target__has_cpu(&opts->target) || opts->target.force_per_cpu)) + perf_target__has_cpu(&opts->target))) perf_evsel__set_sample_bit(evsel, TIME); if (opts->raw_samples) { @@ -663,7 +663,7 @@ void perf_evsel__config(struct perf_evsel *evsel, } if (opts->sample_address) - perf_evsel__set_sample_bit(evsel, DATA_SRC); + attr->sample_type |= PERF_SAMPLE_DATA_SRC; if (opts->no_delay) { attr->watermark = 0; @@ -675,14 +675,11 @@ void perf_evsel__config(struct perf_evsel *evsel, } if (opts->sample_weight) - perf_evsel__set_sample_bit(evsel, WEIGHT); + attr->sample_type |= PERF_SAMPLE_WEIGHT; attr->mmap = track; attr->comm = track; - if (opts->sample_transaction) - perf_evsel__set_sample_bit(evsel, TRANSACTION); - /* * XXX see the function comment above * @@ -696,7 +693,7 @@ void perf_evsel__config(struct perf_evsel *evsel, * Setting enable_on_exec for independent events and * group leaders for traced executed by perf. */ - if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel)) + if (perf_target__none(&opts->target) && perf_evsel__is_group_leader(evsel)) attr->enable_on_exec = 1; } @@ -985,7 +982,6 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) 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(mmap2); ret += PRINT_ATTR_U32(wakeup_events); ret += PRINT_ATTR_U32(wakeup_watermark); @@ -1051,8 +1047,6 @@ retry_open: group_fd, flags); if (FD(evsel, cpu, thread) < 0) { err = -errno; - pr_debug2("perf_event_open failed, error %d\n", - err); goto try_fallback; } set_rlimit = NO_CHANGE; @@ -1219,7 +1213,6 @@ static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel, sample->pid = u.val32[0]; sample->tid = u.val32[1]; - array--; } return 0; @@ -1459,9 +1452,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, array = (void *)array + sz; OVERFLOW_CHECK_u64(array); data->user_stack.size = *array++; - if (WARN_ONCE(data->user_stack.size > sz, - "user stack dump failure\n")) - return -EFAULT; } } @@ -1479,13 +1469,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, array++; } - data->transaction = 0; - if (type & PERF_SAMPLE_TRANSACTION) { - OVERFLOW_CHECK_u64(array); - data->transaction = *array; - array++; - } - return 0; } @@ -1578,9 +1561,6 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, if (type & PERF_SAMPLE_DATA_SRC) result += sizeof(u64); - if (type & PERF_SAMPLE_TRANSACTION) - result += sizeof(u64); - return result; } @@ -1754,11 +1734,6 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, array++; } - if (type & PERF_SAMPLE_TRANSACTION) { - *array = sample->transaction; - array++; - } - return 0; } @@ -2006,7 +1981,8 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err, return false; } -int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, +int perf_evsel__open_strerror(struct perf_evsel *evsel, + struct perf_target *target, int err, char *msg, size_t size) { switch (err) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1ea7c92..4a7bdc7 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -74,7 +74,10 @@ struct perf_evsel { off_t id_offset; }; struct cgroup_sel *cgrp; - void *handler; + struct { + void *func; + void *data; + } handler; struct cpu_map *cpus; unsigned int sample_size; int id_pos; @@ -96,19 +99,8 @@ struct thread_map; struct perf_evlist; struct perf_record_opts; -struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); - -static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) -{ - return perf_evsel__new_idx(attr, 0); -} - -struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx); - -static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name) -{ - return perf_evsel__newtp_idx(sys, name, 0); -} +struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); +struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx); struct event_format *event_format__new(const char *sys, const char *name); @@ -205,12 +197,6 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1, (e1->attr.config == e2->attr.config); } -#define perf_evsel__cmp(a, b) \ - ((a) && \ - (b) && \ - (a)->attr.type == (b)->attr.type && \ - (a)->attr.config == (b)->attr.config) - int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, int cpu, int thread, bool scale); @@ -279,11 +265,6 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel) return list_entry(evsel->node.next, struct perf_evsel, node); } -static inline struct perf_evsel *perf_evsel__prev(struct perf_evsel *evsel) -{ - return list_entry(evsel->node.prev, struct perf_evsel, node); -} - /** * perf_evsel__is_group_leader - Return whether given evsel is a leader event * @@ -323,7 +304,8 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize); -int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, +int perf_evsel__open_strerror(struct perf_evsel *evsel, + struct perf_target *target, int err, char *msg, size_t size); static inline int perf_evsel__group_idx(struct perf_evsel *evsel) diff --git a/tools/perf/util/fs.c b/tools/perf/util/fs.c deleted file mode 100644 index f5be1f2..0000000 --- a/tools/perf/util/fs.c +++ /dev/null @@ -1,119 +0,0 @@ - -/* TODO merge/factor into tools/lib/lk/debugfs.c */ - -#include "util.h" -#include "util/fs.h" - -static const char * const sysfs__fs_known_mountpoints[] = { - "/sys", - 0, -}; - -static const char * const procfs__known_mountpoints[] = { - "/proc", - 0, -}; - -struct fs { - const char *name; - const char * const *mounts; - char path[PATH_MAX + 1]; - bool found; - long magic; -}; - -enum { - FS__SYSFS = 0, - FS__PROCFS = 1, -}; - -static struct fs fs__entries[] = { - [FS__SYSFS] = { - .name = "sysfs", - .mounts = sysfs__fs_known_mountpoints, - .magic = SYSFS_MAGIC, - }, - [FS__PROCFS] = { - .name = "proc", - .mounts = procfs__known_mountpoints, - .magic = PROC_SUPER_MAGIC, - }, -}; - -static bool fs__read_mounts(struct fs *fs) -{ - bool found = false; - char type[100]; - FILE *fp; - - fp = fopen("/proc/mounts", "r"); - if (fp == NULL) - return NULL; - - while (!found && - fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n", - fs->path, type) == 2) { - - if (strcmp(type, fs->name) == 0) - found = true; - } - - fclose(fp); - return fs->found = found; -} - -static int fs__valid_mount(const char *fs, long magic) -{ - struct statfs st_fs; - - if (statfs(fs, &st_fs) < 0) - return -ENOENT; - else if (st_fs.f_type != magic) - return -ENOENT; - - return 0; -} - -static bool fs__check_mounts(struct fs *fs) -{ - const char * const *ptr; - - ptr = fs->mounts; - while (*ptr) { - if (fs__valid_mount(*ptr, fs->magic) == 0) { - fs->found = true; - strcpy(fs->path, *ptr); - return true; - } - ptr++; - } - - return false; -} - -static const char *fs__get_mountpoint(struct fs *fs) -{ - if (fs__check_mounts(fs)) - return fs->path; - - return fs__read_mounts(fs) ? fs->path : NULL; -} - -static const char *fs__mountpoint(int idx) -{ - struct fs *fs = &fs__entries[idx]; - - if (fs->found) - return (const char *)fs->path; - - return fs__get_mountpoint(fs); -} - -#define FS__MOUNTPOINT(name, idx) \ -const char *name##__mountpoint(void) \ -{ \ - return fs__mountpoint(idx); \ -} - -FS__MOUNTPOINT(sysfs, FS__SYSFS); -FS__MOUNTPOINT(procfs, FS__PROCFS); diff --git a/tools/perf/util/fs.h b/tools/perf/util/fs.h deleted file mode 100644 index 5e09ce1..0000000 --- a/tools/perf/util/fs.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __PERF_FS -#define __PERF_FS - -const char *sysfs__mountpoint(void); -const char *procfs__mountpoint(void); - -#endif /* __PERF_FS */ diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh index 36a885d..3ac3803 100755 --- a/tools/perf/util/generate-cmdlist.sh +++ b/tools/perf/util/generate-cmdlist.sh @@ -22,7 +22,7 @@ do }' "Documentation/perf-$cmd.txt" done -echo "#ifdef HAVE_LIBELF_SUPPORT" +echo "#ifdef LIBELF_SUPPORT" sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt | sort | while read cmd @@ -35,5 +35,5 @@ do p }' "Documentation/perf-$cmd.txt" done -echo "#endif /* HAVE_LIBELF_SUPPORT */" +echo "#endif /* LIBELF_SUPPORT */" echo "};" diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 1cd0357..c3e5a3b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -22,7 +22,6 @@ #include "vdso.h" #include "strbuf.h" #include "build-id.h" -#include "data.h" static bool no_buildid_cache = false; @@ -2078,10 +2077,8 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused, if (evsel->idx == (int) desc[i].leader_idx) { evsel->leader = evsel; /* {anon_group} is a dummy name */ - if (strcmp(desc[i].name, "{anon_group}")) { + if (strcmp(desc[i].name, "{anon_group}")) evsel->group_name = desc[i].name; - desc[i].name = NULL; - } evsel->nr_members = desc[i].nr_members; if (i >= nr_groups || nr > 0) { @@ -2107,7 +2104,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused, ret = 0; out_free: - for (i = 0; i < nr_groups; i++) + while ((int) --i >= 0) free(desc[i].name); free(desc); @@ -2192,7 +2189,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full) { struct header_print_data hd; struct perf_header *header = &session->header; - int fd = perf_data_file__fd(session->file); + int fd = session->fd; hd.fp = fp; hd.full = full; @@ -2653,8 +2650,7 @@ static int perf_header__read_pipe(struct perf_session *session) struct perf_header *header = &session->header; struct perf_pipe_file_header f_header; - if (perf_file_header__read_pipe(&f_header, header, - perf_data_file__fd(session->file), + if (perf_file_header__read_pipe(&f_header, header, session->fd, session->repipe) < 0) { pr_debug("incompatible file format\n"); return -EINVAL; @@ -2755,19 +2751,18 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, int perf_session__read_header(struct perf_session *session) { - struct perf_data_file *file = session->file; struct perf_header *header = &session->header; struct perf_file_header f_header; struct perf_file_attr f_attr; u64 f_id; int nr_attrs, nr_ids, i, j; - int fd = perf_data_file__fd(file); + int fd = session->fd; session->evlist = perf_evlist__new(); if (session->evlist == NULL) return -ENOMEM; - if (perf_data_file__is_pipe(file)) + if (session->fd_pipe) return perf_header__read_pipe(session); if (perf_file_header__read(&f_header, header, fd) < 0) @@ -2782,7 +2777,7 @@ int perf_session__read_header(struct perf_session *session) if (f_header.data.size == 0) { pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n" "Was the 'perf record' command properly terminated?\n", - file->path); + session->filename); } nr_attrs = f_header.attrs.size / f_header.attr_size; @@ -2799,7 +2794,7 @@ int perf_session__read_header(struct perf_session *session) perf_event__attr_swap(&f_attr.attr); tmp = lseek(fd, 0, SEEK_CUR); - evsel = perf_evsel__new(&f_attr.attr); + evsel = perf_evsel__new(&f_attr.attr, i); if (evsel == NULL) goto out_delete_evlist; @@ -2918,7 +2913,7 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused, return -ENOMEM; } - evsel = perf_evsel__new(&event->attr.attr); + evsel = perf_evsel__new(&event->attr.attr, evlist->nr_entries); if (evsel == NULL) return -ENOMEM; @@ -2995,19 +2990,18 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, struct perf_session *session) { ssize_t size_read, padding, size = event->tracing_data.size; - int fd = perf_data_file__fd(session->file); - off_t offset = lseek(fd, 0, SEEK_CUR); + off_t offset = lseek(session->fd, 0, SEEK_CUR); char buf[BUFSIZ]; /* setup for reading amidst mmap */ - lseek(fd, offset + sizeof(struct tracing_data_event), + lseek(session->fd, offset + sizeof(struct tracing_data_event), SEEK_SET); - size_read = trace_report(fd, &session->pevent, + size_read = trace_report(session->fd, &session->pevent, session->repipe); padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; - if (readn(fd, buf, padding) < 0) { + if (readn(session->fd, buf, padding) < 0) { pr_err("%s: reading input file", __func__); return -1; } diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 822903e..9ff6cf3 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -160,10 +160,6 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3); hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); - - if (h->transaction) - hists__new_col_len(hists, HISTC_TRANSACTION, - hist_entry__transaction_len()); } void hists__output_recalc_col_len(struct hists *hists, int max_rows) @@ -350,7 +346,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, struct rb_node **p; struct rb_node *parent = NULL; struct hist_entry *he; - int64_t cmp; + int cmp; p = &hists->entries_in->rb_node; @@ -399,7 +395,6 @@ static struct hist_entry *add_hist_entry(struct hists *hists, if (!he) return NULL; - hists->nr_entries++; rb_link_node(&he->rb_node_in, parent, p); rb_insert_color(&he->rb_node_in, hists->entries_in); out: @@ -407,37 +402,94 @@ out: return he; } -struct hist_entry *__hists__add_entry(struct hists *hists, - struct addr_location *al, - struct symbol *sym_parent, - struct branch_info *bi, - struct mem_info *mi, - u64 period, u64 weight, u64 transaction) +struct hist_entry *__hists__add_mem_entry(struct hists *self, + struct addr_location *al, + struct symbol *sym_parent, + struct mem_info *mi, + u64 period, + u64 weight) { struct hist_entry entry = { .thread = al->thread, - .comm = thread__comm(al->thread), .ms = { .map = al->map, .sym = al->sym, }, + .stat = { + .period = period, + .weight = weight, + .nr_events = 1, + }, .cpu = al->cpu, .ip = al->addr, .level = al->level, + .parent = sym_parent, + .filtered = symbol__parent_filter(sym_parent), + .hists = self, + .mem_info = mi, + .branch_info = NULL, + }; + return add_hist_entry(self, &entry, al, period, weight); +} + +struct hist_entry *__hists__add_branch_entry(struct hists *self, + struct addr_location *al, + struct symbol *sym_parent, + struct branch_info *bi, + u64 period, + u64 weight) +{ + struct hist_entry entry = { + .thread = al->thread, + .ms = { + .map = bi->to.map, + .sym = bi->to.sym, + }, + .cpu = al->cpu, + .ip = bi->to.addr, + .level = al->level, .stat = { - .nr_events = 1, .period = period, + .nr_events = 1, .weight = weight, }, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent), - .hists = hists, .branch_info = bi, - .mem_info = mi, - .transaction = transaction, + .hists = self, + .mem_info = NULL, }; - return add_hist_entry(hists, &entry, al, period, weight); + return add_hist_entry(self, &entry, al, period, weight); +} + +struct hist_entry *__hists__add_entry(struct hists *self, + struct addr_location *al, + struct symbol *sym_parent, u64 period, + u64 weight) +{ + struct hist_entry entry = { + .thread = al->thread, + .ms = { + .map = al->map, + .sym = al->sym, + }, + .cpu = al->cpu, + .ip = al->addr, + .level = al->level, + .stat = { + .period = period, + .nr_events = 1, + .weight = weight, + }, + .parent = sym_parent, + .filtered = symbol__parent_filter(sym_parent), + .hists = self, + .branch_info = NULL, + .mem_info = NULL, + }; + + return add_hist_entry(self, &entry, al, period, weight); } int64_t @@ -478,7 +530,6 @@ void hist_entry__free(struct hist_entry *he) { free(he->branch_info); free(he->mem_info); - free_srcline(he->srcline); free(he); } @@ -547,7 +598,7 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he) hists__filter_entry_by_symbol(hists, he); } -void hists__collapse_resort(struct hists *hists, struct ui_progress *prog) +void hists__collapse_resort(struct hists *hists) { struct rb_root *root; struct rb_node *next; @@ -574,8 +625,6 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog) */ hists__apply_filters(hists, n); } - if (prog) - ui_progress__update(prog, 1); } } @@ -835,7 +884,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, struct rb_node **p; struct rb_node *parent = NULL; struct hist_entry *he; - int64_t cmp; + int cmp; if (sort__need_collapse) root = &hists->entries_collapsed; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b621347a..ce8dc61 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -6,7 +6,6 @@ #include "callchain.h" #include "header.h" #include "color.h" -#include "ui/progress.h" extern struct callchain_param callchain_param; @@ -47,8 +46,6 @@ enum hist_column { HISTC_CPU, HISTC_SRCLINE, HISTC_MISPREDICT, - HISTC_IN_TX, - HISTC_ABORT, HISTC_SYMBOL_FROM, HISTC_SYMBOL_TO, HISTC_DSO_FROM, @@ -61,7 +58,6 @@ enum hist_column { HISTC_MEM_TLB, HISTC_MEM_LVL, HISTC_MEM_SNOOP, - HISTC_TRANSACTION, HISTC_NR_COLS, /* Last entry */ }; @@ -84,43 +80,54 @@ struct hists { u16 col_len[HISTC_NR_COLS]; }; -struct hist_entry *__hists__add_entry(struct hists *hists, +struct hist_entry *__hists__add_entry(struct hists *self, struct addr_location *al, - struct symbol *parent, - struct branch_info *bi, - struct mem_info *mi, u64 period, - u64 weight, u64 transaction); + struct symbol *parent, u64 period, + u64 weight); int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); -int hist_entry__transaction_len(void); -int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, +int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size, struct hists *hists); void hist_entry__free(struct hist_entry *); -void hists__output_resort(struct hists *hists); -void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); +struct hist_entry *__hists__add_branch_entry(struct hists *self, + struct addr_location *al, + struct symbol *sym_parent, + struct branch_info *bi, + u64 period, + u64 weight); + +struct hist_entry *__hists__add_mem_entry(struct hists *self, + struct addr_location *al, + struct symbol *sym_parent, + struct mem_info *mi, + u64 period, + u64 weight); + +void hists__output_resort(struct hists *self); +void hists__collapse_resort(struct hists *self); void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); void hists__output_recalc_col_len(struct hists *hists, int max_rows); void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); -void hists__inc_nr_events(struct hists *hists, u32 type); +void hists__inc_nr_events(struct hists *self, u32 type); void events_stats__inc(struct events_stats *stats, u32 type); size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); -size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, +size_t hists__fprintf(struct hists *self, bool show_header, int max_rows, int max_cols, float min_pcnt, FILE *fp); -int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); -int hist_entry__annotate(struct hist_entry *he, size_t privsize); +int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); +int hist_entry__annotate(struct hist_entry *self, size_t privsize); void hists__filter_by_dso(struct hists *hists); void hists__filter_by_thread(struct hists *hists); void hists__filter_by_symbol(struct hists *hists); -u16 hists__col_len(struct hists *hists, enum hist_column col); -void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len); -bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len); +u16 hists__col_len(struct hists *self, enum hist_column col); +void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); +bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); void hists__reset_col_len(struct hists *hists); void hists__calc_col_len(struct hists *hists, struct hist_entry *he); @@ -189,7 +196,7 @@ struct hist_browser_timer { int refresh; }; -#ifdef HAVE_SLANG_SUPPORT +#ifdef SLANG_SUPPORT #include "../ui/keysyms.h" int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, struct hist_browser_timer *hbt); @@ -210,9 +217,12 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, return 0; } -static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, - struct perf_evsel *evsel __maybe_unused, - struct hist_browser_timer *hbt __maybe_unused) +static inline int hist_entry__tui_annotate(struct hist_entry *self + __maybe_unused, + struct perf_evsel *evsel + __maybe_unused, + struct hist_browser_timer *hbt + __maybe_unused) { return 0; } @@ -227,5 +237,20 @@ static inline int script_browse(const char *script_opt __maybe_unused) #define K_SWITCH_INPUT_DATA -3000 #endif -unsigned int hists__sort_list_width(struct hists *hists); +#ifdef GTK2_SUPPORT +int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, + struct hist_browser_timer *hbt __maybe_unused, + float min_pcnt); +#else +static inline +int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, + const char *help __maybe_unused, + struct hist_browser_timer *hbt __maybe_unused, + float min_pcnt __maybe_unused) +{ + return 0; +} +#endif + +unsigned int hists__sort_list_width(struct hists *self); #endif /* __PERF_HIST_H */ diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h index 8f14965..cf6727e 100644 --- a/tools/perf/util/include/dwarf-regs.h +++ b/tools/perf/util/include/dwarf-regs.h @@ -1,7 +1,7 @@ #ifndef _PERF_DWARF_REGS_H_ #define _PERF_DWARF_REGS_H_ -#ifdef HAVE_DWARF_SUPPORT +#ifdef DWARF_SUPPORT const char *get_arch_regstr(unsigned int n); #endif diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h index b003ad7..96b919d 100644 --- a/tools/perf/util/include/linux/compiler.h +++ b/tools/perf/util/include/linux/compiler.h @@ -2,29 +2,20 @@ #define _PERF_LINUX_COMPILER_H_ #ifndef __always_inline -# define __always_inline inline __attribute__((always_inline)) +#define __always_inline inline #endif - #define __user - #ifndef __attribute_const__ -# define __attribute_const__ +#define __attribute_const__ #endif #ifndef __maybe_unused -# define __maybe_unused __attribute__((unused)) -#endif - -#ifndef __packed -# define __packed __attribute__((__packed__)) +#define __maybe_unused __attribute__((unused)) #endif +#define __packed __attribute__((__packed__)) #ifndef __force -# define __force -#endif - -#ifndef __weak -# define __weak __attribute__((weak)) +#define __force #endif #endif diff --git a/tools/perf/util/include/linux/magic.h b/tools/perf/util/include/linux/magic.h index 07d63cf..58b64ed 100644 --- a/tools/perf/util/include/linux/magic.h +++ b/tools/perf/util/include/linux/magic.h @@ -9,8 +9,4 @@ #define SYSFS_MAGIC 0x62656572 #endif -#ifndef PROC_SUPER_MAGIC -#define PROC_SUPER_MAGIC 0x9fa0 -#endif - #endif diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c index 89715b6..11a8d86 100644 --- a/tools/perf/util/intlist.c +++ b/tools/perf/util/intlist.c @@ -20,7 +20,6 @@ static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused, if (node != NULL) { node->i = i; - node->priv = NULL; rc = &node->rb_node; } @@ -58,36 +57,22 @@ void intlist__remove(struct intlist *ilist, struct int_node *node) rblist__remove_node(&ilist->rblist, &node->rb_node); } -static struct int_node *__intlist__findnew(struct intlist *ilist, - int i, bool create) +struct int_node *intlist__find(struct intlist *ilist, int i) { - struct int_node *node = NULL; + struct int_node *node; struct rb_node *rb_node; if (ilist == NULL) return NULL; - if (create) - rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i)); - else - rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); - + node = NULL; + rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); if (rb_node) node = container_of(rb_node, struct int_node, rb_node); return node; } -struct int_node *intlist__find(struct intlist *ilist, int i) -{ - return __intlist__findnew(ilist, i, false); -} - -struct int_node *intlist__findnew(struct intlist *ilist, int i) -{ - return __intlist__findnew(ilist, i, true); -} - static int intlist__parse_list(struct intlist *ilist, const char *s) { char *sep; diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h index aa6877d..62351da 100644 --- a/tools/perf/util/intlist.h +++ b/tools/perf/util/intlist.h @@ -9,7 +9,6 @@ struct int_node { struct rb_node rb_node; int i; - void *priv; }; struct intlist { @@ -24,7 +23,6 @@ int intlist__add(struct intlist *ilist, int i); struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx); struct int_node *intlist__find(struct intlist *ilist, int i); -struct int_node *intlist__findnew(struct intlist *ilist, int i); static inline bool intlist__has_entry(struct intlist *ilist, int i) { diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 84cdb07..6188d28 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -40,29 +40,12 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) return -ENOMEM; snprintf(comm, sizeof(comm), "[guest/%d]", pid); - thread__set_comm(thread, comm, 0); + thread__set_comm(thread, comm); } return 0; } -struct machine *machine__new_host(void) -{ - struct machine *machine = malloc(sizeof(*machine)); - - if (machine != NULL) { - machine__init(machine, "", HOST_KERNEL_ID); - - if (machine__create_kernel_maps(machine) < 0) - goto out_delete; - } - - return machine; -out_delete: - free(machine); - return NULL; -} - static void dsos__delete(struct list_head *dsos) { struct dso *pos, *n; @@ -331,8 +314,7 @@ struct thread *machine__find_thread(struct machine *machine, pid_t tid) return __machine__findnew_thread(machine, 0, tid, false); } -int machine__process_comm_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample) +int machine__process_comm_event(struct machine *machine, union perf_event *event) { struct thread *thread = machine__findnew_thread(machine, event->comm.pid, @@ -341,7 +323,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event if (dump_trace) perf_event__fprintf_comm(event, stdout); - if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) { + if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); return -1; } @@ -350,7 +332,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event } int machine__process_lost_event(struct machine *machine __maybe_unused, - union perf_event *event, struct perf_sample *sample __maybe_unused) + union perf_event *event) { dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", event->lost.id, event->lost.lost); @@ -794,44 +776,75 @@ static int machine__set_modules_path(struct machine *machine) return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); } -static int machine__create_module(void *arg, const char *name, u64 start) -{ - struct machine *machine = arg; - struct map *map; - - map = machine__new_module(machine, start, name); - if (map == NULL) - return -1; - - dso__kernel_module_get_build_id(map->dso, machine->root_dir); - - return 0; -} - static int machine__create_modules(struct machine *machine) { + char *line = NULL; + size_t n; + FILE *file; + struct map *map; const char *modules; char path[PATH_MAX]; - if (machine__is_default_guest(machine)) { + if (machine__is_default_guest(machine)) modules = symbol_conf.default_guest_modules; - } else { - snprintf(path, PATH_MAX, "%s/proc/modules", machine->root_dir); + else { + sprintf(path, "%s/proc/modules", machine->root_dir); modules = path; } if (symbol__restricted_filename(modules, "/proc/modules")) return -1; - if (modules__parse(modules, machine, machine__create_module)) + file = fopen(modules, "r"); + if (file == NULL) return -1; - if (!machine__set_modules_path(machine)) - return 0; + while (!feof(file)) { + char name[PATH_MAX]; + u64 start; + char *sep; + int line_len; + + line_len = getline(&line, &n, file); + if (line_len < 0) + break; + + if (!line) + goto out_failure; + + line[--line_len] = '\0'; /* \n */ + + sep = strrchr(line, 'x'); + if (sep == NULL) + continue; + + hex2u64(sep + 1, &start); + + sep = strchr(line, ' '); + if (sep == NULL) + continue; + + *sep = '\0'; + + snprintf(name, sizeof(name), "[%s]", line); + map = machine__new_module(machine, start, name); + if (map == NULL) + goto out_delete_line; + dso__kernel_module_get_build_id(map->dso, machine->root_dir); + } - pr_debug("Problems setting modules path maps, continuing anyway...\n"); + free(line); + fclose(file); + if (machine__set_modules_path(machine) < 0) { + pr_debug("Problems setting modules path maps, continuing anyway...\n"); + } return 0; + +out_delete_line: + free(line); +out_failure: + return -1; } int machine__create_kernel_maps(struct machine *machine) @@ -985,8 +998,7 @@ out_problem: } int machine__process_mmap2_event(struct machine *machine, - union perf_event *event, - struct perf_sample *sample __maybe_unused) + union perf_event *event) { u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; struct thread *thread; @@ -1033,8 +1045,7 @@ out_problem: return 0; } -int machine__process_mmap_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample __maybe_unused) +int machine__process_mmap_event(struct machine *machine, union perf_event *event) { u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; struct thread *thread; @@ -1091,8 +1102,7 @@ static void machine__remove_thread(struct machine *machine, struct thread *th) list_add_tail(&th->node, &machine->dead_threads); } -int machine__process_fork_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample) +int machine__process_fork_event(struct machine *machine, union perf_event *event) { struct thread *thread = machine__find_thread(machine, event->fork.tid); struct thread *parent = machine__findnew_thread(machine, @@ -1109,7 +1119,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event perf_event__fprintf_task(event, stdout); if (thread == NULL || parent == NULL || - thread__fork(thread, parent, sample->time) < 0) { + thread__fork(thread, parent) < 0) { dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); return -1; } @@ -1117,8 +1127,8 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event return 0; } -int machine__process_exit_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample __maybe_unused) +int machine__process_exit_event(struct machine *machine __maybe_unused, + union perf_event *event) { struct thread *thread = machine__find_thread(machine, event->fork.tid); @@ -1131,24 +1141,23 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event return 0; } -int machine__process_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample) +int machine__process_event(struct machine *machine, union perf_event *event) { int ret; switch (event->header.type) { case PERF_RECORD_COMM: - ret = machine__process_comm_event(machine, event, sample); break; + ret = machine__process_comm_event(machine, event); break; case PERF_RECORD_MMAP: - ret = machine__process_mmap_event(machine, event, sample); break; + ret = machine__process_mmap_event(machine, event); break; case PERF_RECORD_MMAP2: - ret = machine__process_mmap2_event(machine, event, sample); break; + ret = machine__process_mmap2_event(machine, event); break; case PERF_RECORD_FORK: - ret = machine__process_fork_event(machine, event, sample); break; + ret = machine__process_fork_event(machine, event); break; case PERF_RECORD_EXIT: - ret = machine__process_exit_event(machine, event, sample); break; + ret = machine__process_exit_event(machine, event); break; case PERF_RECORD_LOST: - ret = machine__process_lost_event(machine, event, sample); break; + ret = machine__process_lost_event(machine, event); break; default: ret = -1; break; @@ -1258,12 +1267,10 @@ static int machine__resolve_callchain_sample(struct machine *machine, struct thread *thread, struct ip_callchain *chain, struct symbol **parent, - struct addr_location *root_al, - int max_stack) + struct addr_location *root_al) { u8 cpumode = PERF_RECORD_MISC_USER; - int chain_nr = min(max_stack, (int)chain->nr); - int i; + unsigned int i; int err; callchain_cursor_reset(&callchain_cursor); @@ -1273,7 +1280,7 @@ static int machine__resolve_callchain_sample(struct machine *machine, return 0; } - for (i = 0; i < chain_nr; i++) { + for (i = 0; i < chain->nr; i++) { u64 ip; struct addr_location al; @@ -1345,14 +1352,12 @@ int machine__resolve_callchain(struct machine *machine, struct thread *thread, struct perf_sample *sample, struct symbol **parent, - struct addr_location *root_al, - int max_stack) + struct addr_location *root_al) { int ret; ret = machine__resolve_callchain_sample(machine, thread, - sample->callchain, parent, - root_al, max_stack); + sample->callchain, parent, root_al); if (ret) return ret; @@ -1368,41 +1373,6 @@ int machine__resolve_callchain(struct machine *machine, return unwind__get_entries(unwind_entry, &callchain_cursor, machine, thread, evsel->attr.sample_regs_user, - sample, max_stack); + sample); } - -int machine__for_each_thread(struct machine *machine, - int (*fn)(struct thread *thread, void *p), - void *priv) -{ - struct rb_node *nd; - struct thread *thread; - int rc = 0; - - for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) { - thread = rb_entry(nd, struct thread, rb_node); - rc = fn(thread, priv); - if (rc != 0) - return rc; - } - - list_for_each_entry(thread, &machine->dead_threads, node) { - rc = fn(thread, priv); - if (rc != 0) - return rc; - } - return rc; -} - -int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct target *target, struct thread_map *threads, - perf_event__handler_t process, bool data_mmap) -{ - if (target__has_task(target)) - return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap); - else if (target__has_cpu(target)) - return perf_event__synthesize_threads(tool, process, machine, data_mmap); - /* command specified */ - return 0; -} diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 4771330..58a6be1 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -4,7 +4,6 @@ #include <sys/types.h> #include <linux/rbtree.h> #include "map.h" -#include "event.h" struct addr_location; struct branch_stack; @@ -41,20 +40,13 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type) struct thread *machine__find_thread(struct machine *machine, pid_t tid); -int machine__process_comm_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample); -int machine__process_exit_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample); -int machine__process_fork_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample); -int machine__process_lost_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample); -int machine__process_mmap_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample); -int machine__process_mmap2_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample); -int machine__process_event(struct machine *machine, union perf_event *event, - struct perf_sample *sample); +int machine__process_comm_event(struct machine *machine, union perf_event *event); +int machine__process_exit_event(struct machine *machine, union perf_event *event); +int machine__process_fork_event(struct machine *machine, union perf_event *event); +int machine__process_lost_event(struct machine *machine, union perf_event *event); +int machine__process_mmap_event(struct machine *machine, union perf_event *event); +int machine__process_mmap2_event(struct machine *machine, union perf_event *event); +int machine__process_event(struct machine *machine, union perf_event *event); typedef void (*machine__process_t)(struct machine *machine, void *data); @@ -82,7 +74,6 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size); void machines__set_symbol_filter(struct machines *machines, symbol_filter_t symbol_filter); -struct machine *machine__new_host(void); int machine__init(struct machine *machine, const char *root_dir, pid_t pid); void machine__exit(struct machine *machine); void machine__delete_dead_threads(struct machine *machine); @@ -100,8 +91,7 @@ int machine__resolve_callchain(struct machine *machine, struct thread *thread, struct perf_sample *sample, struct symbol **parent, - struct addr_location *root_al, - int max_stack); + struct addr_location *root_al); /* * Default guest kernel is defined by parameter --guestkallsyms @@ -175,19 +165,4 @@ void machines__destroy_kernel_maps(struct machines *machines); size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); -int machine__for_each_thread(struct machine *machine, - int (*fn)(struct thread *thread, void *p), - void *priv); - -int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool, - struct target *target, struct thread_map *threads, - perf_event__handler_t process, bool data_mmap); -static inline -int machine__synthesize_threads(struct machine *machine, struct target *target, - struct thread_map *threads, bool data_mmap) -{ - return __machine__synthesize_threads(machine, NULL, target, threads, - perf_event__process, data_mmap); -} - #endif /* __PERF_MACHINE_H */ diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index ef5bc91..4f6680d 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -172,7 +172,7 @@ int map__load(struct map *map, symbol_filter_t filter) pr_warning(", continuing without symbols\n"); return -1; } else if (nr == 0) { -#ifdef HAVE_LIBELF_SUPPORT +#ifdef LIBELF_SUPPORT const size_t len = strlen(name); const size_t real_len = len - sizeof(DSO__DELETED); @@ -252,16 +252,10 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp) return fprintf(fp, "%s", dsoname); } -/** - * map__rip_2objdump - convert symbol start address to objdump address. - * @map: memory map - * @rip: symbol start address - * +/* * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is * relative to section start. - * - * Return: Address suitable for passing to "objdump --start-address=" */ u64 map__rip_2objdump(struct map *map, u64 rip) { @@ -274,29 +268,6 @@ u64 map__rip_2objdump(struct map *map, u64 rip) return map->unmap_ip(map, rip); } -/** - * map__objdump_2mem - convert objdump address to a memory address. - * @map: memory map - * @ip: objdump address - * - * Closely related to map__rip_2objdump(), this function takes an address from - * objdump and converts it to a memory address. Note this assumes that @map - * contains the address. To be sure the result is valid, check it forwards - * e.g. map__rip_2objdump(map->map_ip(map, map__objdump_2mem(map, ip))) == ip - * - * Return: Memory address. - */ -u64 map__objdump_2mem(struct map *map, u64 ip) -{ - if (!map->dso->adjust_symbols) - return map->unmap_ip(map, ip); - - if (map->dso->rel) - return map->unmap_ip(map, ip + map->pgoff); - - return ip; -} - void map_groups__init(struct map_groups *mg) { int i; @@ -400,23 +371,6 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, return NULL; } -int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) -{ - if (ams->addr < ams->map->start || ams->addr > ams->map->end) { - if (ams->map->groups == NULL) - return -1; - ams->map = map_groups__find(ams->map->groups, ams->map->type, - ams->addr); - if (ams->map == NULL) - return -1; - } - - ams->al_addr = ams->map->map_ip(ams->map, ams->addr); - ams->sym = map__find_symbol(ams->map, ams->al_addr, filter); - - return ams->sym ? 0 : -1; -} - size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, int verbose, FILE *fp) { diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index e4e259c..4886ca2 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -84,9 +84,6 @@ static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip) /* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ u64 map__rip_2objdump(struct map *map, u64 rip); -/* objdump address -> memory address */ -u64 map__objdump_2mem(struct map *map, u64 ip); - struct symbol; typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); @@ -170,10 +167,6 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, struct map **mapp, symbol_filter_t filter); -struct addr_map_symbol; - -int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter); - static inline struct symbol *map_groups__find_function_by_name(struct map_groups *mg, const char *name, struct map **mapp, diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6de6f89..9812531 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -277,7 +277,7 @@ static int __add_event(struct list_head *list, int *idx, event_attr_init(attr); - evsel = perf_evsel__new_idx(attr, (*idx)++); + evsel = perf_evsel__new(attr, (*idx)++); if (!evsel) return -ENOMEM; @@ -378,7 +378,7 @@ static int add_tracepoint(struct list_head *list, int *idx, { struct perf_evsel *evsel; - evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); + evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++); if (!evsel) return -ENOMEM; @@ -998,10 +998,8 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, char evt_path[MAXPATHLEN]; char dir_path[MAXPATHLEN]; - if (debugfs_valid_mountpoint(tracing_events_path)) { - printf(" [ Tracepoints not available: %s ]\n", strerror(errno)); + if (debugfs_valid_mountpoint(tracing_events_path)) return; - } sys_dir = opendir(tracing_events_path); if (!sys_dir) @@ -1097,7 +1095,7 @@ static bool is_event_supported(u8 type, unsigned config) .threads = { 0 }, }; - evsel = perf_evsel__new(&attr); + evsel = perf_evsel__new(&attr, 0); if (evsel) { ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0; perf_evsel__delete(evsel); diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 3432995..91346b7 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -126,37 +126,6 @@ modifier_bp [rwx]{1,3} } -<config>{ -config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } -config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); } -config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } -name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } -period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } -branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } -, { return ','; } -"/" { BEGIN(INITIAL); return '/'; } -{name_minus} { return str(yyscanner, PE_NAME); } -} - -<mem>{ -{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } -: { return ':'; } -{num_dec} { return value(yyscanner, 10); } -{num_hex} { return value(yyscanner, 16); } - /* - * We need to separate 'mem:' scanner part, in order to get specific - * modifier bits parsed out. Otherwise we would need to handle PE_NAME - * and we'd need to parse it manually. During the escape from <mem> - * state we need to put the escaping char back, so we dont miss it. - */ -. { unput(*yytext); BEGIN(INITIAL); } - /* - * We destroy the scanner after reaching EOF, - * but anyway just to be sure get back to INIT state. - */ -<<EOF>> { BEGIN(INITIAL); } -} - cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } @@ -193,6 +162,18 @@ speculative-read|speculative-load | refs|Reference|ops|access | misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); } +<config>{ +config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } +config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); } +config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } +name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } +period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } +branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } +, { return ','; } +"/" { BEGIN(INITIAL); return '/'; } +{name_minus} { return str(yyscanner, PE_NAME); } +} + mem: { BEGIN(mem); return PE_PREFIX_MEM; } r{num_raw_hex} { return raw(yyscanner); } {num_dec} { return value(yyscanner, 10); } @@ -208,7 +189,25 @@ r{num_raw_hex} { return raw(yyscanner); } "}" { return '}'; } = { return '='; } \n { } -. { } + +<mem>{ +{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } +: { return ':'; } +{num_dec} { return value(yyscanner, 10); } +{num_hex} { return value(yyscanner, 16); } + /* + * We need to separate 'mem:' scanner part, in order to get specific + * modifier bits parsed out. Otherwise we would need to handle PE_NAME + * and we'd need to parse it manually. During the escape from <mem> + * state we need to put the escaping char back, so we dont miss it. + */ +. { unput(*yytext); BEGIN(INITIAL); } + /* + * We destroy the scanner after reaching EOF, + * but anyway just to be sure get back to INIT state. + */ +<<EOF>> { BEGIN(INITIAL); } +} %% diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 31f404a..2bc9e70 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -339,10 +339,10 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, if (arg[1] != '-') { ctx->opt = arg + 1; if (internal_help && *ctx->opt == 'h') - return usage_with_options_internal(usagestr, options, 0); + return parse_options_usage(usagestr, options); switch (parse_short_opt(ctx, options)) { case -1: - return parse_options_usage(usagestr, options, arg + 1, 1); + return parse_options_usage(usagestr, options); case -2: goto unknown; default: @@ -352,11 +352,10 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, check_typos(arg + 1, options); while (ctx->opt) { if (internal_help && *ctx->opt == 'h') - return usage_with_options_internal(usagestr, options, 0); - arg = ctx->opt; + return parse_options_usage(usagestr, options); switch (parse_short_opt(ctx, options)) { case -1: - return parse_options_usage(usagestr, options, arg, 1); + return parse_options_usage(usagestr, options); case -2: /* fake a short option thing to hide the fact that we may have * started to parse aggregated stuff @@ -384,12 +383,12 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, if (internal_help && !strcmp(arg + 2, "help-all")) return usage_with_options_internal(usagestr, options, 1); if (internal_help && !strcmp(arg + 2, "help")) - return usage_with_options_internal(usagestr, options, 0); + return parse_options_usage(usagestr, options); if (!strcmp(arg + 2, "list-opts")) return PARSE_OPT_LIST; switch (parse_long_opt(ctx, arg + 2, options)) { case -1: - return parse_options_usage(usagestr, options, arg + 2, 0); + return parse_options_usage(usagestr, options); case -2: goto unknown; default: @@ -446,89 +445,6 @@ int parse_options(int argc, const char **argv, const struct option *options, #define USAGE_OPTS_WIDTH 24 #define USAGE_GAP 2 -static void print_option_help(const struct option *opts, int full) -{ - size_t pos; - int pad; - - if (opts->type == OPTION_GROUP) { - fputc('\n', stderr); - if (*opts->help) - fprintf(stderr, "%s\n", opts->help); - return; - } - if (!full && (opts->flags & PARSE_OPT_HIDDEN)) - return; - - pos = fprintf(stderr, " "); - if (opts->short_name) - pos += fprintf(stderr, "-%c", opts->short_name); - else - pos += fprintf(stderr, " "); - - if (opts->long_name && opts->short_name) - pos += fprintf(stderr, ", "); - if (opts->long_name) - pos += fprintf(stderr, "--%s", opts->long_name); - - switch (opts->type) { - case OPTION_ARGUMENT: - break; - case OPTION_LONG: - case OPTION_U64: - case OPTION_INTEGER: - case OPTION_UINTEGER: - if (opts->flags & PARSE_OPT_OPTARG) - if (opts->long_name) - pos += fprintf(stderr, "[=<n>]"); - else - pos += fprintf(stderr, "[<n>]"); - else - pos += fprintf(stderr, " <n>"); - break; - case OPTION_CALLBACK: - if (opts->flags & PARSE_OPT_NOARG) - break; - /* FALLTHROUGH */ - case OPTION_STRING: - if (opts->argh) { - if (opts->flags & PARSE_OPT_OPTARG) - if (opts->long_name) - pos += fprintf(stderr, "[=<%s>]", opts->argh); - else - pos += fprintf(stderr, "[<%s>]", opts->argh); - else - pos += fprintf(stderr, " <%s>", opts->argh); - } else { - if (opts->flags & PARSE_OPT_OPTARG) - if (opts->long_name) - pos += fprintf(stderr, "[=...]"); - else - pos += fprintf(stderr, "[...]"); - else - pos += fprintf(stderr, " ..."); - } - break; - default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ - case OPTION_END: - case OPTION_GROUP: - case OPTION_BIT: - case OPTION_BOOLEAN: - case OPTION_INCR: - case OPTION_SET_UINT: - case OPTION_SET_PTR: - break; - } - - if (pos <= USAGE_OPTS_WIDTH) - pad = USAGE_OPTS_WIDTH - pos; - else { - fputc('\n', stderr); - pad = USAGE_OPTS_WIDTH; - } - fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); -} - int usage_with_options_internal(const char * const *usagestr, const struct option *opts, int full) { @@ -548,9 +464,87 @@ int usage_with_options_internal(const char * const *usagestr, if (opts->type != OPTION_GROUP) fputc('\n', stderr); - for ( ; opts->type != OPTION_END; opts++) - print_option_help(opts, full); + for (; opts->type != OPTION_END; opts++) { + size_t pos; + int pad; + + if (opts->type == OPTION_GROUP) { + fputc('\n', stderr); + if (*opts->help) + fprintf(stderr, "%s\n", opts->help); + continue; + } + if (!full && (opts->flags & PARSE_OPT_HIDDEN)) + continue; + + pos = fprintf(stderr, " "); + if (opts->short_name) + pos += fprintf(stderr, "-%c", opts->short_name); + else + pos += fprintf(stderr, " "); + + if (opts->long_name && opts->short_name) + pos += fprintf(stderr, ", "); + if (opts->long_name) + pos += fprintf(stderr, "--%s", opts->long_name); + + switch (opts->type) { + case OPTION_ARGUMENT: + break; + case OPTION_LONG: + case OPTION_U64: + case OPTION_INTEGER: + case OPTION_UINTEGER: + if (opts->flags & PARSE_OPT_OPTARG) + if (opts->long_name) + pos += fprintf(stderr, "[=<n>]"); + else + pos += fprintf(stderr, "[<n>]"); + else + pos += fprintf(stderr, " <n>"); + break; + case OPTION_CALLBACK: + if (opts->flags & PARSE_OPT_NOARG) + break; + /* FALLTHROUGH */ + case OPTION_STRING: + if (opts->argh) { + if (opts->flags & PARSE_OPT_OPTARG) + if (opts->long_name) + pos += fprintf(stderr, "[=<%s>]", opts->argh); + else + pos += fprintf(stderr, "[<%s>]", opts->argh); + else + pos += fprintf(stderr, " <%s>", opts->argh); + } else { + if (opts->flags & PARSE_OPT_OPTARG) + if (opts->long_name) + pos += fprintf(stderr, "[=...]"); + else + pos += fprintf(stderr, "[...]"); + else + pos += fprintf(stderr, " ..."); + } + break; + default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ + case OPTION_END: + case OPTION_GROUP: + case OPTION_BIT: + case OPTION_BOOLEAN: + case OPTION_INCR: + case OPTION_SET_UINT: + case OPTION_SET_PTR: + break; + } + if (pos <= USAGE_OPTS_WIDTH) + pad = USAGE_OPTS_WIDTH - pos; + else { + fputc('\n', stderr); + pad = USAGE_OPTS_WIDTH; + } + fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); + } fputc('\n', stderr); return PARSE_OPT_HELP; @@ -565,45 +559,9 @@ void usage_with_options(const char * const *usagestr, } int parse_options_usage(const char * const *usagestr, - const struct option *opts, - const char *optstr, bool short_opt) + const struct option *opts) { - if (!usagestr) - goto opt; - - fprintf(stderr, "\n usage: %s\n", *usagestr++); - while (*usagestr && **usagestr) - fprintf(stderr, " or: %s\n", *usagestr++); - while (*usagestr) { - fprintf(stderr, "%s%s\n", - **usagestr ? " " : "", - *usagestr); - usagestr++; - } - fputc('\n', stderr); - -opt: - for ( ; opts->type != OPTION_END; opts++) { - if (short_opt) { - if (opts->short_name == *optstr) - 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 (opts->type != OPTION_END) - print_option_help(opts, 0); - - return PARSE_OPT_HELP; + return usage_with_options_internal(usagestr, opts, 0); } diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index b0241e2..7bb5999 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -158,9 +158,7 @@ struct parse_opt_ctx_t { }; extern int parse_options_usage(const char * const *usagestr, - const struct option *opts, - const char *optstr, - bool short_opt); + const struct option *opts); extern void parse_options_start(struct parse_opt_ctx_t *ctx, int argc, const char **argv, int flags); diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c index 5d13cb4..a8c4954 100644 --- a/tools/perf/util/path.c +++ b/tools/perf/util/path.c @@ -22,23 +22,19 @@ static const char *get_perf_dir(void) return "."; } -/* - * If libc has strlcpy() then that version will override this - * implementation: - */ -size_t __weak strlcpy(char *dest, const char *src, size_t size) +#ifndef HAVE_STRLCPY +size_t strlcpy(char *dest, const char *src, size_t size) { size_t ret = strlen(src); if (size) { size_t len = (ret >= size) ? size - 1 : ret; - memcpy(dest, src, len); dest[len] = '\0'; } - return ret; } +#endif static char *get_pathname(void) { diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index a3d42cd..5a4f2b6f 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h @@ -1,7 +1,7 @@ #ifndef __PERF_REGS_H #define __PERF_REGS_H -#ifdef HAVE_PERF_REGS_SUPPORT +#ifdef HAVE_PERF_REGS #include <perf_regs.h> #else #define PERF_REGS_MASK 0 @@ -10,5 +10,5 @@ static inline const char *perf_reg_name(int id __maybe_unused) { return NULL; } -#endif /* HAVE_PERF_REGS_SUPPORT */ +#endif /* HAVE_PERF_REGS */ #endif /* __PERF_REGS_H */ diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index c232d8d..bc9d806 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -4,7 +4,7 @@ #include <unistd.h> #include <stdio.h> #include <dirent.h> -#include "fs.h" +#include "sysfs.h" #include "util.h" #include "pmu.h" #include "parse-events.h" @@ -77,8 +77,9 @@ static int pmu_format(const char *name, struct list_head *format) { struct stat st; char path[PATH_MAX]; - const char *sysfs = sysfs__mountpoint(); + const char *sysfs; + sysfs = sysfs_find_mountpoint(); if (!sysfs) return -1; @@ -165,8 +166,9 @@ static int pmu_aliases(const char *name, struct list_head *head) { struct stat st; char path[PATH_MAX]; - const char *sysfs = sysfs__mountpoint(); + const char *sysfs; + sysfs = sysfs_find_mountpoint(); if (!sysfs) return -1; @@ -210,10 +212,11 @@ static int pmu_type(const char *name, __u32 *type) { struct stat st; char path[PATH_MAX]; + const char *sysfs; FILE *file; int ret = 0; - const char *sysfs = sysfs__mountpoint(); + sysfs = sysfs_find_mountpoint(); if (!sysfs) return -1; @@ -238,10 +241,11 @@ static int pmu_type(const char *name, __u32 *type) static void pmu_read_sysfs(void) { char path[PATH_MAX]; + const char *sysfs; DIR *dir; struct dirent *dent; - const char *sysfs = sysfs__mountpoint(); + sysfs = sysfs_find_mountpoint(); if (!sysfs) return; @@ -266,10 +270,11 @@ static struct cpu_map *pmu_cpumask(const char *name) { struct stat st; char path[PATH_MAX]; + const char *sysfs; FILE *file; struct cpu_map *cpus; - const char *sysfs = sysfs__mountpoint(); + sysfs = sysfs_find_mountpoint(); if (!sysfs) return NULL; @@ -632,19 +637,3 @@ void print_pmu_events(const char *event_glob, bool name_only) printf("\n"); free(aliases); } - -bool pmu_have_event(const char *pname, const char *name) -{ - struct perf_pmu *pmu; - struct perf_pmu_alias *alias; - - pmu = NULL; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { - if (strcmp(pname, pmu->name)) - continue; - list_for_each_entry(alias, &pmu->aliases, list) - if (!strcmp(alias->name, name)) - return true; - } - return false; -} diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 1179b26..6b2cbe2 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -42,7 +42,6 @@ int perf_pmu__format_parse(char *dir, struct list_head *head); struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); void print_pmu_events(const char *event_glob, bool name_only); -bool pmu_have_event(const char *pname, const char *name); int perf_pmu__test(void); #endif /* __PMU_H */ diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 9c6989c..aa04bf9 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -47,6 +47,7 @@ #include "session.h" #define MAX_CMDLEN 256 +#define MAX_PROBE_ARGS 128 #define PERFPROBE_GROUP "probe" bool probe_event_dry_run; /* Dry run flag */ @@ -200,7 +201,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp, return 0; } -#ifdef HAVE_DWARF_SUPPORT +#ifdef DWARF_SUPPORT /* Open new debuginfo of given module */ static struct debuginfo *open_debuginfo(const char *module) { @@ -629,7 +630,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, return ret; } -#else /* !HAVE_DWARF_SUPPORT */ +#else /* !DWARF_SUPPORT */ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, struct perf_probe_point *pp) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index ffb657f..f069273 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -115,7 +115,7 @@ static const Dwfl_Callbacks offline_callbacks = { }; /* Get a Dwarf from offline image */ -static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, +static int debuginfo__init_offline_dwarf(struct debuginfo *self, const char *path) { int fd; @@ -124,25 +124,25 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, if (fd < 0) return fd; - dbg->dwfl = dwfl_begin(&offline_callbacks); - if (!dbg->dwfl) + self->dwfl = dwfl_begin(&offline_callbacks); + if (!self->dwfl) goto error; - dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); - if (!dbg->mod) + self->mod = dwfl_report_offline(self->dwfl, "", "", fd); + if (!self->mod) goto error; - dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias); - if (!dbg->dbg) + self->dbg = dwfl_module_getdwarf(self->mod, &self->bias); + if (!self->dbg) goto error; return 0; error: - if (dbg->dwfl) - dwfl_end(dbg->dwfl); + if (self->dwfl) + dwfl_end(self->dwfl); else close(fd); - memset(dbg, 0, sizeof(*dbg)); + memset(self, 0, sizeof(*self)); return -ENOENT; } @@ -180,24 +180,24 @@ static const Dwfl_Callbacks kernel_callbacks = { }; /* Get a Dwarf from live kernel image */ -static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg, +static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, Dwarf_Addr addr) { - dbg->dwfl = dwfl_begin(&kernel_callbacks); - if (!dbg->dwfl) + self->dwfl = dwfl_begin(&kernel_callbacks); + if (!self->dwfl) return -EINVAL; /* Load the kernel dwarves: Don't care the result here */ - dwfl_linux_kernel_report_kernel(dbg->dwfl); - dwfl_linux_kernel_report_modules(dbg->dwfl); + dwfl_linux_kernel_report_kernel(self->dwfl); + dwfl_linux_kernel_report_modules(self->dwfl); - dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias); + self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias); /* Here, check whether we could get a real dwarf */ - if (!dbg->dbg) { + if (!self->dbg) { pr_debug("Failed to find kernel dwarf at %lx\n", (unsigned long)addr); - dwfl_end(dbg->dwfl); - memset(dbg, 0, sizeof(*dbg)); + dwfl_end(self->dwfl); + memset(self, 0, sizeof(*self)); return -ENOENT; } @@ -205,7 +205,7 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg, } #else /* With older elfutils, this just support kernel module... */ -static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg, +static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, Dwarf_Addr addr __maybe_unused) { const char *path = kernel_get_module_path("kernel"); @@ -216,45 +216,44 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg, } pr_debug2("Use file %s for debuginfo\n", path); - return debuginfo__init_offline_dwarf(dbg, path); + return debuginfo__init_offline_dwarf(self, path); } #endif struct debuginfo *debuginfo__new(const char *path) { - struct debuginfo *dbg = zalloc(sizeof(*dbg)); - if (!dbg) + struct debuginfo *self = zalloc(sizeof(struct debuginfo)); + if (!self) return NULL; - if (debuginfo__init_offline_dwarf(dbg, path) < 0) { - free(dbg); - dbg = NULL; + if (debuginfo__init_offline_dwarf(self, path) < 0) { + free(self); + self = NULL; } - return dbg; + return self; } struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) { - struct debuginfo *dbg = zalloc(sizeof(*dbg)); - - if (!dbg) + struct debuginfo *self = zalloc(sizeof(struct debuginfo)); + if (!self) return NULL; - if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) { - free(dbg); - dbg = NULL; + if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) { + free(self); + self = NULL; } - return dbg; + return self; } -void debuginfo__delete(struct debuginfo *dbg) +void debuginfo__delete(struct debuginfo *self) { - if (dbg) { - if (dbg->dwfl) - dwfl_end(dbg->dwfl); - free(dbg); + if (self) { + if (self->dwfl) + dwfl_end(self->dwfl); + free(self); } } @@ -274,15 +273,12 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs) /* * Convert a location into trace_arg. * If tvar == NULL, this just checks variable can be converted. - * If fentry == true and vr_die is a parameter, do huristic search - * for the location fuzzed by function entry mcount. */ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, - Dwarf_Op *fb_ops, Dwarf_Die *sp_die, + Dwarf_Op *fb_ops, struct probe_trace_arg *tvar) { Dwarf_Attribute attr; - Dwarf_Addr tmp = 0; Dwarf_Op *op; size_t nops; unsigned int regn; @@ -295,29 +291,12 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, goto static_var; /* TODO: handle more than 1 exprs */ - if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) - return -EINVAL; /* Broken DIE ? */ - if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) { - ret = dwarf_entrypc(sp_die, &tmp); - if (ret || addr != tmp || - dwarf_tag(vr_die) != DW_TAG_formal_parameter || - dwarf_highpc(sp_die, &tmp)) - return -ENOENT; - /* - * This is fuzzed by fentry mcount. We try to find the - * parameter location at the earliest address. - */ - for (addr += 1; addr <= tmp; addr++) { - if (dwarf_getlocation_addr(&attr, addr, &op, - &nops, 1) > 0) - goto found; - } - return -ENOENT; - } -found: - if (nops == 0) + if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL || + dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 || + nops == 0) { /* TODO: Support const_value */ return -ENOENT; + } if (op->atom == DW_OP_addr) { static_var: @@ -584,7 +563,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, } if (die_find_member(&type, field->name, die_mem) == NULL) { - pr_warning("%s(type:%s) has no member %s.\n", varname, + pr_warning("%s(tyep:%s) has no member %s.\n", varname, dwarf_diename(&type), field->name); return -EINVAL; } @@ -621,7 +600,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) dwarf_diename(vr_die)); ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, - &pf->sp_die, pf->tvar); + pf->tvar); if (ret == -ENOENT) pr_err("Failed to find the location of %s at this address.\n" " Perhaps, it has been optimized out.\n", pf->pvar->var); @@ -1084,7 +1063,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) } /* Find probe points from debuginfo */ -static int debuginfo__find_probes(struct debuginfo *dbg, +static int debuginfo__find_probes(struct debuginfo *self, struct probe_finder *pf) { struct perf_probe_point *pp = &pf->pev->point; @@ -1095,7 +1074,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg, #if _ELFUTILS_PREREQ(0, 142) /* Get the call frame information from this dwarf */ - pf->cfi = dwarf_getcfi(dbg->dbg); + pf->cfi = dwarf_getcfi(self->dbg); #endif off = 0; @@ -1114,7 +1093,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg, .data = pf, }; - dwarf_getpubnames(dbg->dbg, pubname_search_cb, + dwarf_getpubnames(self->dbg, pubname_search_cb, &pubname_param, 0); if (pubname_param.found) { ret = probe_point_search_cb(&pf->sp_die, &probe_param); @@ -1124,9 +1103,9 @@ static int debuginfo__find_probes(struct debuginfo *dbg, } /* Loop on CUs (Compilation Unit) */ - while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { + while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { /* Get the DIE(Debugging Information Entry) of this CU */ - diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die); + diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die); if (!diep) continue; @@ -1157,80 +1136,12 @@ found: return ret; } -struct local_vars_finder { - struct probe_finder *pf; - struct perf_probe_arg *args; - int max_args; - int nargs; - int ret; -}; - -/* Collect available variables in this scope */ -static int copy_variables_cb(Dwarf_Die *die_mem, void *data) -{ - struct local_vars_finder *vf = data; - struct probe_finder *pf = vf->pf; - int tag; - - tag = dwarf_tag(die_mem); - if (tag == DW_TAG_formal_parameter || - tag == DW_TAG_variable) { - if (convert_variable_location(die_mem, vf->pf->addr, - vf->pf->fb_ops, &pf->sp_die, - NULL) == 0) { - vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem); - if (vf->args[vf->nargs].var == NULL) { - vf->ret = -ENOMEM; - return DIE_FIND_CB_END; - } - pr_debug(" %s", vf->args[vf->nargs].var); - vf->nargs++; - } - } - - if (dwarf_haspc(die_mem, vf->pf->addr)) - return DIE_FIND_CB_CONTINUE; - else - return DIE_FIND_CB_SIBLING; -} - -static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf, - struct perf_probe_arg *args) -{ - Dwarf_Die die_mem; - int i; - int n = 0; - struct local_vars_finder vf = {.pf = pf, .args = args, - .max_args = MAX_PROBE_ARGS, .ret = 0}; - - for (i = 0; i < pf->pev->nargs; i++) { - /* var never be NULL */ - if (strcmp(pf->pev->args[i].var, "$vars") == 0) { - pr_debug("Expanding $vars into:"); - vf.nargs = n; - /* Special local variables */ - die_find_child(sc_die, copy_variables_cb, (void *)&vf, - &die_mem); - pr_debug(" (%d)\n", vf.nargs - n); - if (vf.ret < 0) - return vf.ret; - n = vf.nargs; - } else { - /* Copy normal argument */ - args[n] = pf->pev->args[i]; - n++; - } - } - return n; -} - /* Add a found probe point into trace event list */ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) { struct trace_event_finder *tf = container_of(pf, struct trace_event_finder, pf); struct probe_trace_event *tev; - struct perf_probe_arg *args; int ret, i; /* Check number of tevs */ @@ -1250,45 +1161,31 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, tev->point.offset); - /* Expand special probe argument if exist */ - args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); - if (args == NULL) - return -ENOMEM; - - ret = expand_probe_args(sc_die, pf, args); - if (ret < 0) - goto end; - - tev->nargs = ret; - tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); - if (tev->args == NULL) { - ret = -ENOMEM; - goto end; - } - /* Find each argument */ - for (i = 0; i < tev->nargs; i++) { - pf->pvar = &args[i]; + tev->nargs = pf->pev->nargs; + tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); + if (tev->args == NULL) + return -ENOMEM; + for (i = 0; i < pf->pev->nargs; i++) { + pf->pvar = &pf->pev->args[i]; pf->tvar = &tev->args[i]; /* Variable should be found from scope DIE */ ret = find_variable(sc_die, pf); if (ret != 0) - break; + return ret; } -end: - free(args); - return ret; + return 0; } /* Find probe_trace_events specified by perf_probe_event from debuginfo */ -int debuginfo__find_trace_events(struct debuginfo *dbg, +int debuginfo__find_trace_events(struct debuginfo *self, struct perf_probe_event *pev, struct probe_trace_event **tevs, int max_tevs) { struct trace_event_finder tf = { .pf = {.pev = pev, .callback = add_probe_trace_event}, - .mod = dbg->mod, .max_tevs = max_tevs}; + .mod = self->mod, .max_tevs = max_tevs}; int ret; /* Allocate result tevs array */ @@ -1299,7 +1196,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, tf.tevs = *tevs; tf.ntevs = 0; - ret = debuginfo__find_probes(dbg, &tf.pf); + ret = debuginfo__find_probes(self, &tf.pf); if (ret < 0) { free(*tevs); *tevs = NULL; @@ -1325,8 +1222,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) if (tag == DW_TAG_formal_parameter || tag == DW_TAG_variable) { ret = convert_variable_location(die_mem, af->pf.addr, - af->pf.fb_ops, &af->pf.sp_die, - NULL); + af->pf.fb_ops, NULL); if (ret == 0) { ret = die_get_varname(die_mem, buf, MAX_VAR_LEN); pr_debug2("Add new var: %s\n", buf); @@ -1390,14 +1286,14 @@ out: } /* Find available variables at given probe point */ -int debuginfo__find_available_vars_at(struct debuginfo *dbg, +int debuginfo__find_available_vars_at(struct debuginfo *self, struct perf_probe_event *pev, struct variable_list **vls, int max_vls, bool externs) { struct available_var_finder af = { .pf = {.pev = pev, .callback = add_available_vars}, - .mod = dbg->mod, + .mod = self->mod, .max_vls = max_vls, .externs = externs}; int ret; @@ -1409,7 +1305,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, af.vls = *vls; af.nvls = 0; - ret = debuginfo__find_probes(dbg, &af.pf); + ret = debuginfo__find_probes(self, &af.pf); if (ret < 0) { /* Free vlist for error */ while (af.nvls--) { @@ -1427,7 +1323,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, } /* Reverse search */ -int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, +int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr, struct perf_probe_point *ppt) { Dwarf_Die cudie, spdie, indie; @@ -1436,10 +1332,10 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, int baseline = 0, lineno = 0, ret = 0; /* Adjust address with bias */ - addr += dbg->bias; + addr += self->bias; /* Find cu die */ - if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) { + if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) { pr_warning("Failed to find debug information for address %lx\n", addr); ret = -EINVAL; @@ -1640,7 +1536,7 @@ static int find_line_range_by_func(struct line_finder *lf) return param.retval; } -int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr) +int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr) { struct line_finder lf = {.lr = lr, .found = 0}; int ret = 0; @@ -1657,7 +1553,7 @@ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr) struct dwarf_callback_param line_range_param = { .data = (void *)&lf, .retval = 0}; - dwarf_getpubnames(dbg->dbg, pubname_search_cb, + dwarf_getpubnames(self->dbg, pubname_search_cb, &pubname_param, 0); if (pubname_param.found) { line_range_search_cb(&lf.sp_die, &line_range_param); @@ -1668,12 +1564,12 @@ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr) /* Loop on CUs (Compilation Unit) */ while (!lf.found && ret >= 0) { - if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, + if (dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) break; /* Get the DIE(Debugging Information Entry) of this CU */ - diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die); + diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die); if (!diep) continue; diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index ffc33cd..3b7d630 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -7,7 +7,6 @@ #define MAX_PROBE_BUFFER 1024 #define MAX_PROBES 128 -#define MAX_PROBE_ARGS 128 static inline int is_c_varname(const char *name) { @@ -15,7 +14,7 @@ static inline int is_c_varname(const char *name) return isalpha(name[0]) || name[0] == '_'; } -#ifdef HAVE_DWARF_SUPPORT +#ifdef DWARF_SUPPORT #include "dwarf-aux.h" @@ -31,25 +30,25 @@ struct debuginfo { extern struct debuginfo *debuginfo__new(const char *path); extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr); -extern void debuginfo__delete(struct debuginfo *dbg); +extern void debuginfo__delete(struct debuginfo *self); /* Find probe_trace_events specified by perf_probe_event from debuginfo */ -extern int debuginfo__find_trace_events(struct debuginfo *dbg, +extern int debuginfo__find_trace_events(struct debuginfo *self, struct perf_probe_event *pev, struct probe_trace_event **tevs, int max_tevs); /* Find a perf_probe_point from debuginfo */ -extern int debuginfo__find_probe_point(struct debuginfo *dbg, +extern int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr, struct perf_probe_point *ppt); /* Find a line range */ -extern int debuginfo__find_line_range(struct debuginfo *dbg, +extern int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr); /* Find available variables */ -extern int debuginfo__find_available_vars_at(struct debuginfo *dbg, +extern int debuginfo__find_available_vars_at(struct debuginfo *self, struct perf_probe_event *pev, struct variable_list **vls, int max_points, bool externs); @@ -106,6 +105,6 @@ struct line_finder { int found; }; -#endif /* HAVE_DWARF_SUPPORT */ +#endif /* DWARF_SUPPORT */ #endif /*_PROBE_FINDER_H */ diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h index c3cb658..4cedea5 100644 --- a/tools/perf/util/pstack.h +++ b/tools/perf/util/pstack.h @@ -5,10 +5,10 @@ struct pstack; struct pstack *pstack__new(unsigned short max_nr_entries); -void pstack__delete(struct pstack *pstack); -bool pstack__empty(const struct pstack *pstack); -void pstack__remove(struct pstack *pstack, void *key); -void pstack__push(struct pstack *pstack, void *key); -void *pstack__pop(struct pstack *pstack); +void pstack__delete(struct pstack *self); +bool pstack__empty(const struct pstack *self); +void pstack__remove(struct pstack *self, void *key); +void pstack__push(struct pstack *self, void *key); +void *pstack__pop(struct pstack *self); #endif /* _PERF_PSTACK_ */ diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 239036f..f75ae1b 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -17,5 +17,5 @@ util/xyarray.c util/cgroup.c util/rblist.c util/strlist.c -util/fs.c +util/sysfs.c ../../lib/rbtree.c diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 4bf8ace..2ac4bc9 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -33,6 +33,13 @@ int eprintf(int level, const char *fmt, ...) # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, #endif +struct throttle_event { + struct perf_event_header header; + u64 time; + u64 id; + u64 stream_id; +}; + PyMODINIT_FUNC initperf(void); #define member_def(type, member, ptype, help) \ @@ -1031,7 +1038,6 @@ PyMODINIT_FUNC initperf(void) pyrf_cpu_map__setup_types() < 0) return; - /* The page_size is placed in util object. */ page_size = sysconf(_SC_PAGE_SIZE); Py_INCREF(&pyrf_evlist__type); diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c index 0dfe27d..a16cdd2 100644 --- a/tools/perf/util/rblist.c +++ b/tools/perf/util/rblist.c @@ -48,12 +48,10 @@ void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node) rblist->node_delete(rblist, rb_node); } -static struct rb_node *__rblist__findnew(struct rblist *rblist, - const void *entry, - bool create) +struct rb_node *rblist__find(struct rblist *rblist, const void *entry) { struct rb_node **p = &rblist->entries.rb_node; - struct rb_node *parent = NULL, *new_node = NULL; + struct rb_node *parent = NULL; while (*p != NULL) { int rc; @@ -69,26 +67,7 @@ static struct rb_node *__rblist__findnew(struct rblist *rblist, return parent; } - if (create) { - new_node = rblist->node_new(rblist, entry); - if (new_node) { - rb_link_node(new_node, parent, p); - rb_insert_color(new_node, &rblist->entries); - ++rblist->nr_entries; - } - } - - return new_node; -} - -struct rb_node *rblist__find(struct rblist *rblist, const void *entry) -{ - return __rblist__findnew(rblist, entry, false); -} - -struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry) -{ - return __rblist__findnew(rblist, entry, true); + return NULL; } void rblist__init(struct rblist *rblist) diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h index ff9913b..6d0cae5 100644 --- a/tools/perf/util/rblist.h +++ b/tools/perf/util/rblist.h @@ -32,7 +32,6 @@ void rblist__delete(struct rblist *rblist); int rblist__add_node(struct rblist *rblist, const void *new_entry); void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node); struct rb_node *rblist__find(struct rblist *rblist, const void *entry); -struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry); struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx); static inline bool rblist__empty(const struct rblist *rblist) diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index c8845b1..18d73aa 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -2,8 +2,6 @@ #include "evsel.h" #include "cpumap.h" #include "parse-events.h" -#include "fs.h" -#include "util.h" typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); @@ -108,72 +106,3 @@ void perf_evlist__config(struct perf_evlist *evlist, perf_evlist__set_id_pos(evlist); } - -static int get_max_rate(unsigned int *rate) -{ - char path[PATH_MAX]; - const char *procfs = procfs__mountpoint(); - - if (!procfs) - return -1; - - snprintf(path, PATH_MAX, - "%s/sys/kernel/perf_event_max_sample_rate", procfs); - - return filename__read_int(path, (int *) rate); -} - -static int perf_record_opts__config_freq(struct perf_record_opts *opts) -{ - bool user_freq = opts->user_freq != UINT_MAX; - unsigned int max_rate; - - if (opts->user_interval != ULLONG_MAX) - opts->default_interval = opts->user_interval; - if (user_freq) - opts->freq = opts->user_freq; - - /* - * User specified count overrides default frequency. - */ - if (opts->default_interval) - opts->freq = 0; - else if (opts->freq) { - opts->default_interval = opts->freq; - } else { - pr_err("frequency and count are zero, aborting\n"); - return -1; - } - - if (get_max_rate(&max_rate)) - return 0; - - /* - * User specified frequency is over current maximum. - */ - if (user_freq && (max_rate < opts->freq)) { - pr_err("Maximum frequency rate (%u) reached.\n" - "Please use -F freq option with lower value or consider\n" - "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n", - max_rate); - return -1; - } - - /* - * Default frequency is over current maximum. - */ - if (max_rate < opts->freq) { - pr_warning("Lowering default frequency rate to %u.\n" - "Please consider tweaking " - "/proc/sys/kernel/perf_event_max_sample_rate.\n", - max_rate); - opts->freq = max_rate; - } - - return 0; -} - -int perf_record_opts__config(struct perf_record_opts *opts) -{ - return perf_record_opts__config_freq(opts); -} diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index d5e5969..c0c9795 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -273,7 +273,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; - const char *comm = thread__comm_str(thread); + char *comm = thread->comm; dSP; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 53c20e7..95d91a0 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -250,7 +250,7 @@ static void python_process_tracepoint(union perf_event *perf_event int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; - const char *comm = thread__comm_str(thread); + char *comm = thread->comm; t = PyTuple_New(MAX_FIELDS); if (!t) @@ -389,7 +389,7 @@ static void python_process_general_event(union perf_event *perf_event pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( (const char *)sample->raw_data, sample->raw_size)); pydict_set_item_string_decref(dict, "comm", - PyString_FromString(thread__comm_str(thread))); + PyString_FromString(thread->comm)); if (al->map) { pydict_set_item_string_decref(dict, "dso", PyString_FromString(al->map->dso->name)); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f36d24a..568b750 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -16,34 +16,73 @@ #include "perf_regs.h" #include "vdso.h" -static int perf_session__open(struct perf_session *session) +static int perf_session__open(struct perf_session *self, bool force) { - struct perf_data_file *file = session->file; + struct stat input_stat; - if (perf_session__read_header(session) < 0) { - pr_err("incompatible file format (rerun with -v to learn more)"); - return -1; - } + if (!strcmp(self->filename, "-")) { + self->fd_pipe = true; + self->fd = STDIN_FILENO; + + if (perf_session__read_header(self) < 0) + pr_err("incompatible file format (rerun with -v to learn more)"); - if (perf_data_file__is_pipe(file)) return 0; + } + + self->fd = open(self->filename, O_RDONLY); + if (self->fd < 0) { + int err = errno; + + pr_err("failed to open %s: %s", self->filename, strerror(err)); + if (err == ENOENT && !strcmp(self->filename, "perf.data")) + pr_err(" (try 'perf record' first)"); + pr_err("\n"); + return -errno; + } + + if (fstat(self->fd, &input_stat) < 0) + goto out_close; + + if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { + pr_err("file %s not owned by current user or root\n", + self->filename); + goto out_close; + } + + if (!input_stat.st_size) { + pr_info("zero-sized file (%s), nothing to do!\n", + self->filename); + goto out_close; + } - if (!perf_evlist__valid_sample_type(session->evlist)) { + if (perf_session__read_header(self) < 0) { + pr_err("incompatible file format (rerun with -v to learn more)"); + goto out_close; + } + + if (!perf_evlist__valid_sample_type(self->evlist)) { pr_err("non matching sample_type"); - return -1; + goto out_close; } - if (!perf_evlist__valid_sample_id_all(session->evlist)) { + if (!perf_evlist__valid_sample_id_all(self->evlist)) { pr_err("non matching sample_id_all"); - return -1; + goto out_close; } - if (!perf_evlist__valid_read_format(session->evlist)) { + if (!perf_evlist__valid_read_format(self->evlist)) { pr_err("non matching read_format"); - return -1; + goto out_close; } + self->size = input_stat.st_size; return 0; + +out_close: + close(self->fd); + self->fd = -1; + return -1; } void perf_session__set_id_hdr_size(struct perf_session *session) @@ -53,70 +92,71 @@ void perf_session__set_id_hdr_size(struct perf_session *session) machines__set_id_hdr_size(&session->machines, id_hdr_size); } -int perf_session__create_kernel_maps(struct perf_session *session) +int perf_session__create_kernel_maps(struct perf_session *self) { - int ret = machine__create_kernel_maps(&session->machines.host); + int ret = machine__create_kernel_maps(&self->machines.host); if (ret >= 0) - ret = machines__create_guest_kernel_maps(&session->machines); + ret = machines__create_guest_kernel_maps(&self->machines); return ret; } -static void perf_session__destroy_kernel_maps(struct perf_session *session) +static void perf_session__destroy_kernel_maps(struct perf_session *self) { - machines__destroy_kernel_maps(&session->machines); + machines__destroy_kernel_maps(&self->machines); } -struct perf_session *perf_session__new(struct perf_data_file *file, - bool repipe, struct perf_tool *tool) +struct perf_session *perf_session__new(const char *filename, int mode, + bool force, bool repipe, + struct perf_tool *tool) { - struct perf_session *session = zalloc(sizeof(*session)); - - if (!session) - goto out; - - session->repipe = repipe; - INIT_LIST_HEAD(&session->ordered_samples.samples); - INIT_LIST_HEAD(&session->ordered_samples.sample_cache); - INIT_LIST_HEAD(&session->ordered_samples.to_free); - machines__init(&session->machines); + struct perf_session *self; + struct stat st; + size_t len; - if (file) { - if (perf_data_file__open(file)) - goto out_delete; + if (!filename || !strlen(filename)) { + if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) + filename = "-"; + else + filename = "perf.data"; + } - session->file = file; + len = strlen(filename); + self = zalloc(sizeof(*self) + len); - if (perf_data_file__is_read(file)) { - if (perf_session__open(session) < 0) - goto out_close; + if (self == NULL) + goto out; - perf_session__set_id_hdr_size(session); - } - } + memcpy(self->filename, filename, len); + self->repipe = repipe; + INIT_LIST_HEAD(&self->ordered_samples.samples); + INIT_LIST_HEAD(&self->ordered_samples.sample_cache); + INIT_LIST_HEAD(&self->ordered_samples.to_free); + machines__init(&self->machines); - if (!file || perf_data_file__is_write(file)) { + if (mode == O_RDONLY) { + if (perf_session__open(self, force) < 0) + goto out_delete; + perf_session__set_id_hdr_size(self); + } else if (mode == O_WRONLY) { /* * In O_RDONLY mode this will be performed when reading the * kernel MMAP event, in perf_event__process_mmap(). */ - if (perf_session__create_kernel_maps(session) < 0) + if (perf_session__create_kernel_maps(self) < 0) goto out_delete; } if (tool && tool->ordering_requires_timestamps && - tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) { + tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_samples = false; } - return session; - - out_close: - perf_data_file__close(file); - out_delete: - perf_session__delete(session); - out: +out: + return self; +out_delete: + perf_session__delete(self); return NULL; } @@ -146,16 +186,15 @@ static void perf_session_env__delete(struct perf_session_env *env) free(env->pmu_mappings); } -void perf_session__delete(struct perf_session *session) +void perf_session__delete(struct perf_session *self) { - perf_session__destroy_kernel_maps(session); - perf_session__delete_dead_threads(session); - perf_session__delete_threads(session); - perf_session_env__delete(&session->header.env); - machines__exit(&session->machines); - if (session->file) - perf_data_file__close(session->file); - free(session); + perf_session__destroy_kernel_maps(self); + perf_session__delete_dead_threads(self); + perf_session__delete_threads(self); + perf_session_env__delete(&self->header.env); + machines__exit(&self->machines); + close(self->fd); + free(self); vdso__exit(); } @@ -358,17 +397,6 @@ static void perf_event__read_swap(union perf_event *event, bool sample_id_all) swap_sample_id_all(event, &event->read + 1); } -static void perf_event__throttle_swap(union perf_event *event, - bool sample_id_all) -{ - event->throttle.time = bswap_64(event->throttle.time); - event->throttle.id = bswap_64(event->throttle.id); - event->throttle.stream_id = bswap_64(event->throttle.stream_id); - - if (sample_id_all) - swap_sample_id_all(event, &event->throttle + 1); -} - static u8 revbyte(u8 b) { int rev = (b >> 4) | ((b & 0xf) << 4); @@ -414,9 +442,6 @@ void perf_event__attr_swap(struct perf_event_attr *attr) attr->bp_type = bswap_32(attr->bp_type); attr->bp_addr = bswap_64(attr->bp_addr); attr->bp_len = bswap_64(attr->bp_len); - attr->branch_sample_type = bswap_64(attr->branch_sample_type); - attr->sample_regs_user = bswap_64(attr->sample_regs_user); - attr->sample_stack_user = bswap_32(attr->sample_stack_user); swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); } @@ -457,8 +482,6 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_EXIT] = perf_event__task_swap, [PERF_RECORD_LOST] = perf_event__all64_swap, [PERF_RECORD_READ] = perf_event__read_swap, - [PERF_RECORD_THROTTLE] = perf_event__throttle_swap, - [PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap, [PERF_RECORD_SAMPLE] = perf_event__all64_swap, [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, @@ -502,16 +525,13 @@ static int flush_sample_queue(struct perf_session *s, struct perf_sample sample; u64 limit = os->next_flush; u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; + unsigned idx = 0, progress_next = os->nr_samples / 16; bool show_progress = limit == ULLONG_MAX; - struct ui_progress prog; int ret; if (!tool->ordered_samples || !limit) return 0; - if (show_progress) - ui_progress__init(&prog, os->nr_samples, "Processing time ordered events..."); - list_for_each_entry_safe(iter, tmp, head, list) { if (session_done()) return 0; @@ -532,9 +552,11 @@ static int flush_sample_queue(struct perf_session *s, os->last_flush = iter->timestamp; list_del(&iter->list); list_add(&iter->list, &os->sample_cache); - - if (show_progress) - ui_progress__update(&prog, 1); + if (show_progress && (++idx >= progress_next)) { + progress_next += os->nr_samples / 16; + ui_progress__update(idx, os->nr_samples, + "Processing time ordered events..."); + } } if (list_empty(head)) { @@ -838,9 +860,6 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, if (sample_type & PERF_SAMPLE_DATA_SRC) printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); - if (sample_type & PERF_SAMPLE_TRANSACTION) - printf("... transaction: %" PRIx64 "\n", sample->transaction); - if (sample_type & PERF_SAMPLE_READ) sample_read__printf(sample, evsel->attr.read_format); } @@ -1012,7 +1031,6 @@ static int perf_session_deliver_event(struct perf_session *session, static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, struct perf_tool *tool, u64 file_offset) { - int fd = perf_data_file__fd(session->file); int err; dump_event(session, event, file_offset, NULL); @@ -1026,7 +1044,7 @@ static int perf_session__process_user_event(struct perf_session *session, union return err; case PERF_RECORD_HEADER_TRACING_DATA: /* setup for reading amidst mmap */ - lseek(fd, file_offset, SEEK_SET); + lseek(session->fd, file_offset, SEEK_SET); return tool->tracing_data(tool, event, session); case PERF_RECORD_HEADER_BUILD_ID: return tool->build_id(tool, event, session); @@ -1083,11 +1101,11 @@ static int perf_session__process_event(struct perf_session *session, file_offset); } -void perf_event_header__bswap(struct perf_event_header *hdr) +void perf_event_header__bswap(struct perf_event_header *self) { - hdr->type = bswap_32(hdr->type); - hdr->misc = bswap_16(hdr->misc); - hdr->size = bswap_16(hdr->size); + self->type = bswap_32(self->type); + self->misc = bswap_16(self->misc); + self->size = bswap_16(self->size); } struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) @@ -1095,11 +1113,11 @@ struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) return machine__findnew_thread(&session->machines.host, 0, pid); } -static struct thread *perf_session__register_idle_thread(struct perf_session *session) +static struct thread *perf_session__register_idle_thread(struct perf_session *self) { - struct thread *thread = perf_session__findnew(session, 0); + struct thread *thread = perf_session__findnew(self, 0); - if (thread == NULL || thread__set_comm(thread, "swapper", 0)) { + if (thread == NULL || thread__set_comm(thread, "swapper")) { pr_err("problem inserting idle task.\n"); thread = NULL; } @@ -1149,10 +1167,9 @@ static void perf_session__warn_about_errors(const struct perf_session *session, volatile int session_done; -static int __perf_session__process_pipe_events(struct perf_session *session, +static int __perf_session__process_pipe_events(struct perf_session *self, struct perf_tool *tool) { - int fd = perf_data_file__fd(session->file); union perf_event *event; uint32_t size, cur_size = 0; void *buf = NULL; @@ -1171,7 +1188,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session, return -errno; more: event = buf; - err = readn(fd, event, sizeof(struct perf_event_header)); + err = readn(self->fd, event, sizeof(struct perf_event_header)); if (err <= 0) { if (err == 0) goto done; @@ -1180,7 +1197,7 @@ more: goto out_err; } - if (session->header.needs_swap) + if (self->header.needs_swap) perf_event_header__bswap(&event->header); size = event->header.size; @@ -1203,7 +1220,7 @@ more: p += sizeof(struct perf_event_header); if (size - sizeof(struct perf_event_header)) { - err = readn(fd, p, size - sizeof(struct perf_event_header)); + err = readn(self->fd, p, size - sizeof(struct perf_event_header)); if (err <= 0) { if (err == 0) { pr_err("unexpected end of event stream\n"); @@ -1215,7 +1232,7 @@ more: } } - if ((skip = perf_session__process_event(session, event, tool, head)) < 0) { + if ((skip = perf_session__process_event(self, event, tool, head)) < 0) { pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", head, event->header.size, event->header.type); err = -EINVAL; @@ -1230,13 +1247,11 @@ more: if (!session_done()) goto more; done: - /* do the final flush for ordered samples */ - session->ordered_samples.next_flush = ULLONG_MAX; - err = flush_sample_queue(session, tool); + err = 0; out_err: free(buf); - perf_session__warn_about_errors(session, tool); - perf_session_free_sample_buffers(session); + perf_session__warn_about_errors(self, tool); + perf_session_free_sample_buffers(self); return err; } @@ -1284,14 +1299,12 @@ int __perf_session__process_events(struct perf_session *session, u64 data_offset, u64 data_size, u64 file_size, struct perf_tool *tool) { - int fd = perf_data_file__fd(session->file); - u64 head, page_offset, file_offset, file_pos; + u64 head, page_offset, file_offset, file_pos, progress_next; int err, mmap_prot, mmap_flags, map_idx = 0; size_t mmap_size; char *buf, *mmaps[NUM_MMAPS]; union perf_event *event; uint32_t size; - struct ui_progress prog; perf_tool__fill_defaults(tool); @@ -1302,7 +1315,7 @@ int __perf_session__process_events(struct perf_session *session, if (data_size && (data_offset + data_size < file_size)) file_size = data_offset + data_size; - ui_progress__init(&prog, file_size, "Processing events..."); + progress_next = file_size / 16; mmap_size = MMAP_SIZE; if (mmap_size > file_size) @@ -1318,7 +1331,7 @@ int __perf_session__process_events(struct perf_session *session, mmap_flags = MAP_PRIVATE; } remap: - buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, fd, + buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd, file_offset); if (buf == MAP_FAILED) { pr_err("failed to mmap file\n"); @@ -1357,15 +1370,19 @@ more: head += size; file_pos += size; - ui_progress__update(&prog, size); + if (file_pos >= progress_next) { + progress_next += file_size / 16; + ui_progress__update(file_pos, file_size, + "Processing events..."); + } + err = 0; if (session_done()) - goto out; + goto out_err; if (file_pos < file_size) goto more; -out: /* do the final flush for ordered samples */ session->ordered_samples.next_flush = ULLONG_MAX; err = flush_sample_queue(session, tool); @@ -1376,22 +1393,21 @@ out_err: return err; } -int perf_session__process_events(struct perf_session *session, +int perf_session__process_events(struct perf_session *self, struct perf_tool *tool) { - u64 size = perf_data_file__size(session->file); int err; - if (perf_session__register_idle_thread(session) == NULL) + if (perf_session__register_idle_thread(self) == NULL) return -ENOMEM; - if (!perf_data_file__is_pipe(session->file)) - err = __perf_session__process_events(session, - session->header.data_offset, - session->header.data_size, - size, tool); + if (!self->fd_pipe) + err = __perf_session__process_events(self, + self->header.data_offset, + self->header.data_size, + self->size, tool); else - err = __perf_session__process_pipe_events(session, tool); + err = __perf_session__process_pipe_events(self, tool); return err; } @@ -1440,15 +1456,15 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps, return 0; } -size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp) +size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) { - return machines__fprintf_dsos(&session->machines, fp); + return machines__fprintf_dsos(&self->machines, fp); } -size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp, +size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, bool (skip)(struct dso *dso, int parm), int parm) { - return machines__fprintf_dsos_buildid(&session->machines, fp, skip, parm); + return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm); } size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) @@ -1509,8 +1525,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, if (symbol_conf.use_callchain && sample->callchain) { if (machine__resolve_callchain(machine, evsel, al.thread, - sample, NULL, NULL, - PERF_MAX_STACK_DEPTH) != 0) { + sample, NULL, NULL) != 0) { if (verbose) error("Failed to resolve callchain. Skipping\n"); return; @@ -1614,14 +1629,13 @@ int perf_session__cpu_bitmap(struct perf_session *session, void perf_session__fprintf_info(struct perf_session *session, FILE *fp, bool full) { - int fd = perf_data_file__fd(session->file); struct stat st; int ret; if (session == NULL || fp == NULL) return; - ret = fstat(fd, &st); + ret = fstat(session->fd, &st); if (ret == -1) return; @@ -1650,9 +1664,9 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, continue; err = -EEXIST; - if (evsel->handler != NULL) + if (evsel->handler.func != NULL) goto out; - evsel->handler = assocs[i].handler; + evsel->handler.func = assocs[i].handler; } err = 0; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 50f6409..04bf737 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -7,7 +7,6 @@ #include "machine.h" #include "symbol.h" #include "thread.h" -#include "data.h" #include <linux/rbtree.h> #include <linux/perf_event.h> @@ -30,13 +29,16 @@ struct ordered_samples { struct perf_session { struct perf_header header; + unsigned long size; struct machines machines; struct perf_evlist *evlist; struct pevent *pevent; struct events_stats stats; + int fd; + bool fd_pipe; bool repipe; struct ordered_samples ordered_samples; - struct perf_data_file *file; + char filename[1]; }; #define PRINT_IP_OPT_IP (1<<0) @@ -47,16 +49,17 @@ struct perf_session { struct perf_tool; -struct perf_session *perf_session__new(struct perf_data_file *file, - bool repipe, struct perf_tool *tool); +struct perf_session *perf_session__new(const char *filename, int mode, + bool force, bool repipe, + struct perf_tool *tool); void perf_session__delete(struct perf_session *session); -void perf_event_header__bswap(struct perf_event_header *hdr); +void perf_event_header__bswap(struct perf_event_header *self); -int __perf_session__process_events(struct perf_session *session, +int __perf_session__process_events(struct perf_session *self, u64 data_offset, u64 data_size, u64 size, struct perf_tool *tool); -int perf_session__process_events(struct perf_session *session, +int perf_session__process_events(struct perf_session *self, struct perf_tool *tool); int perf_session_queue_event(struct perf_session *s, union perf_event *event, @@ -64,38 +67,37 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event, void perf_tool__fill_defaults(struct perf_tool *tool); -int perf_session__resolve_callchain(struct perf_session *session, - struct perf_evsel *evsel, +int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel, struct thread *thread, struct ip_callchain *chain, struct symbol **parent); -bool perf_session__has_traces(struct perf_session *session, const char *msg); +bool perf_session__has_traces(struct perf_session *self, const char *msg); void mem_bswap_64(void *src, int byte_size); void mem_bswap_32(void *src, int byte_size); void perf_event__attr_swap(struct perf_event_attr *attr); -int perf_session__create_kernel_maps(struct perf_session *session); +int perf_session__create_kernel_maps(struct perf_session *self); void perf_session__set_id_hdr_size(struct perf_session *session); static inline -struct machine *perf_session__find_machine(struct perf_session *session, pid_t pid) +struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid) { - return machines__find(&session->machines, pid); + return machines__find(&self->machines, pid); } static inline -struct machine *perf_session__findnew_machine(struct perf_session *session, pid_t pid) +struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid) { - return machines__findnew(&session->machines, pid); + return machines__findnew(&self->machines, pid); } -struct thread *perf_session__findnew(struct perf_session *session, pid_t pid); -size_t perf_session__fprintf(struct perf_session *session, FILE *fp); +struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); +size_t perf_session__fprintf(struct perf_session *self, FILE *fp); -size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp); +size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp, bool (fn)(struct dso *dso, int parm), int parm); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8b0bb1f..5f118a0 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1,6 +1,5 @@ #include "sort.h" #include "hist.h" -#include "comm.h" #include "symbol.h" regex_t parent_regex; @@ -43,7 +42,7 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) return n; } -static int64_t cmp_null(const void *l, const void *r) +static int64_t cmp_null(void *l, void *r) { if (!l && !r) return 0; @@ -61,12 +60,11 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) return right->thread->tid - left->thread->tid; } -static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - const char *comm = thread__comm_str(he->thread); return repsep_snprintf(bf, size, "%*s:%5d", width - 6, - comm ?: "", he->thread->tid); + self->thread->comm ?: "", self->thread->tid); } struct sort_entry sort_thread = { @@ -81,21 +79,25 @@ struct sort_entry sort_thread = { static int64_t sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) { - /* Compare the addr that should be unique among comm */ - return comm__str(right->comm) - comm__str(left->comm); + return right->thread->tid - left->thread->tid; } static int64_t sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) { - /* Compare the addr that should be unique among comm */ - return comm__str(right->comm) - comm__str(left->comm); + char *comm_l = left->thread->comm; + char *comm_r = right->thread->comm; + + if (!comm_l || !comm_r) + return cmp_null(comm_l, comm_r); + + return strcmp(comm_l, comm_r); } -static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm)); + return repsep_snprintf(bf, size, "%*s", width, self->thread->comm); } struct sort_entry sort_comm = { @@ -146,10 +148,10 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf, return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); } -static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return _hist_entry__dso_snprintf(he->ms.map, bf, size, width); + return _hist_entry__dso_snprintf(self->ms.map, bf, size, width); } struct sort_entry sort_dso = { @@ -180,19 +182,9 @@ static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) static int64_t sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) { - int64_t ret; - if (!left->ms.sym && !right->ms.sym) return right->level - left->level; - /* - * comparing symbol address alone is not enough since it's a - * relative address within a dso. - */ - ret = sort__dso_cmp(left, right); - if (ret != 0) - return ret; - return _sort__sym_cmp(left->ms.sym, right->ms.sym); } @@ -232,11 +224,11 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, return ret; } -static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip, - he->level, bf, size, width); + return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip, + self->level, bf, size, width); } struct sort_entry sort_sym = { @@ -251,32 +243,50 @@ struct sort_entry sort_sym = { static int64_t sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) { - if (!left->srcline) { - if (!left->ms.map) - left->srcline = SRCLINE_UNKNOWN; - else { - struct map *map = left->ms.map; - left->srcline = get_srcline(map->dso, - map__rip_2objdump(map, left->ip)); - } - } - if (!right->srcline) { - if (!right->ms.map) - right->srcline = SRCLINE_UNKNOWN; - else { - struct map *map = right->ms.map; - right->srcline = get_srcline(map->dso, - map__rip_2objdump(map, right->ip)); - } - } - return strcmp(left->srcline, right->srcline); + return (int64_t)(right->ip - left->ip); } -static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width __maybe_unused) { - return repsep_snprintf(bf, size, "%s", he->srcline); + FILE *fp = NULL; + char cmd[PATH_MAX + 2], *path = self->srcline, *nl; + size_t line_len; + + if (path != NULL) + goto out_path; + + if (!self->ms.map) + goto out_ip; + + if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10)) + goto out_ip; + + snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64, + self->ms.map->dso->long_name, self->ip); + fp = popen(cmd, "r"); + if (!fp) + goto out_ip; + + if (getline(&path, &line_len, fp) < 0 || !line_len) + goto out_ip; + self->srcline = strdup(path); + if (self->srcline == NULL) + goto out_ip; + + nl = strchr(self->srcline, '\n'); + if (nl != NULL) + *nl = '\0'; + path = self->srcline; +out_path: + if (fp) + pclose(fp); + return repsep_snprintf(bf, size, "%s", path); +out_ip: + if (fp) + pclose(fp); + return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip); } struct sort_entry sort_srcline = { @@ -300,11 +310,11 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) return strcmp(sym_l->name, sym_r->name); } -static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { return repsep_snprintf(bf, size, "%-*s", width, - he->parent ? he->parent->name : "[other]"); + self->parent ? self->parent->name : "[other]"); } struct sort_entry sort_parent = { @@ -322,10 +332,10 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) return right->cpu - left->cpu; } -static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) +static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%*d", width, he->cpu); + return repsep_snprintf(bf, size, "%*d", width, self->cpu); } struct sort_entry sort_cpu = { @@ -344,10 +354,10 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right) right->branch_info->from.map); } -static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__dso_from_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return _hist_entry__dso_snprintf(he->branch_info->from.map, + return _hist_entry__dso_snprintf(self->branch_info->from.map, bf, size, width); } @@ -358,10 +368,10 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right) right->branch_info->to.map); } -static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__dso_to_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return _hist_entry__dso_snprintf(he->branch_info->to.map, + return _hist_entry__dso_snprintf(self->branch_info->to.map, bf, size, width); } @@ -389,21 +399,21 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) return _sort__sym_cmp(to_l->sym, to_r->sym); } -static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - struct addr_map_symbol *from = &he->branch_info->from; + struct addr_map_symbol *from = &self->branch_info->from; return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, - he->level, bf, size, width); + self->level, bf, size, width); } -static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - struct addr_map_symbol *to = &he->branch_info->to; + struct addr_map_symbol *to = &self->branch_info->to; return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, - he->level, bf, size, width); + self->level, bf, size, width); } @@ -446,13 +456,13 @@ sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right) return mp || p; } -static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__mispredict_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width){ static const char *out = "N/A"; - if (he->branch_info->flags.predicted) + if (self->branch_info->flags.predicted) out = "N"; - else if (he->branch_info->flags.mispred) + else if (self->branch_info->flags.mispred) out = "Y"; return repsep_snprintf(bf, size, "%-*s", width, out); @@ -472,19 +482,19 @@ sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right) return (int64_t)(r - l); } -static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__daddr_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { uint64_t addr = 0; struct map *map = NULL; struct symbol *sym = NULL; - if (he->mem_info) { - addr = he->mem_info->daddr.addr; - map = he->mem_info->daddr.map; - sym = he->mem_info->daddr.sym; + if (self->mem_info) { + addr = self->mem_info->daddr.addr; + map = self->mem_info->daddr.map; + sym = self->mem_info->daddr.sym; } - return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, + return _hist_entry__sym_snprintf(map, sym, addr, self->level, bf, size, width); } @@ -502,13 +512,13 @@ sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) return _sort__dso_cmp(map_l, map_r); } -static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__dso_daddr_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { struct map *map = NULL; - if (he->mem_info) - map = he->mem_info->daddr.map; + if (self->mem_info) + map = self->mem_info->daddr.map; return _hist_entry__dso_snprintf(map, bf, size, width); } @@ -532,14 +542,14 @@ sort__locked_cmp(struct hist_entry *left, struct hist_entry *right) return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock); } -static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__locked_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { const char *out; u64 mask = PERF_MEM_LOCK_NA; - if (he->mem_info) - mask = he->mem_info->data_src.mem_lock; + if (self->mem_info) + mask = self->mem_info->data_src.mem_lock; if (mask & PERF_MEM_LOCK_NA) out = "N/A"; @@ -581,7 +591,7 @@ static const char * const tlb_access[] = { }; #define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *)) -static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__tlb_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { char out[64]; @@ -592,8 +602,8 @@ static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf, out[0] = '\0'; - if (he->mem_info) - m = he->mem_info->data_src.mem_dtlb; + if (self->mem_info) + m = self->mem_info->data_src.mem_dtlb; hit = m & PERF_MEM_TLB_HIT; miss = m & PERF_MEM_TLB_MISS; @@ -658,7 +668,7 @@ static const char * const mem_lvl[] = { }; #define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *)) -static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__lvl_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { char out[64]; @@ -667,8 +677,8 @@ static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf, u64 m = PERF_MEM_LVL_NA; u64 hit, miss; - if (he->mem_info) - m = he->mem_info->data_src.mem_lvl; + if (self->mem_info) + m = self->mem_info->data_src.mem_lvl; out[0] = '\0'; @@ -726,7 +736,7 @@ static const char * const snoop_access[] = { }; #define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *)) -static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__snoop_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { char out[64]; @@ -736,8 +746,8 @@ static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf, out[0] = '\0'; - if (he->mem_info) - m = he->mem_info->data_src.mem_snoop; + if (self->mem_info) + m = self->mem_info->data_src.mem_snoop; for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) { if (!(m & 0x1)) @@ -774,10 +784,10 @@ sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right) return he_weight(left) - he_weight(right); } -static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__local_weight_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he)); + return repsep_snprintf(bf, size, "%-*llu", width, he_weight(self)); } struct sort_entry sort_local_weight = { @@ -793,10 +803,10 @@ sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right) return left->stat.weight - right->stat.weight; } -static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf, +static int hist_entry__global_weight_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { - return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight); + return repsep_snprintf(bf, size, "%-*llu", width, self->stat.weight); } struct sort_entry sort_global_weight = { @@ -848,127 +858,6 @@ struct sort_entry sort_mem_snoop = { .se_width_idx = HISTC_MEM_SNOOP, }; -static int64_t -sort__abort_cmp(struct hist_entry *left, struct hist_entry *right) -{ - return left->branch_info->flags.abort != - right->branch_info->flags.abort; -} - -static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) -{ - static const char *out = "."; - - if (he->branch_info->flags.abort) - out = "A"; - return repsep_snprintf(bf, size, "%-*s", width, out); -} - -struct sort_entry sort_abort = { - .se_header = "Transaction abort", - .se_cmp = sort__abort_cmp, - .se_snprintf = hist_entry__abort_snprintf, - .se_width_idx = HISTC_ABORT, -}; - -static int64_t -sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right) -{ - return left->branch_info->flags.in_tx != - right->branch_info->flags.in_tx; -} - -static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) -{ - static const char *out = "."; - - if (he->branch_info->flags.in_tx) - out = "T"; - - return repsep_snprintf(bf, size, "%-*s", width, out); -} - -struct sort_entry sort_in_tx = { - .se_header = "Branch in transaction", - .se_cmp = sort__in_tx_cmp, - .se_snprintf = hist_entry__in_tx_snprintf, - .se_width_idx = HISTC_IN_TX, -}; - -static int64_t -sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right) -{ - return left->transaction - right->transaction; -} - -static inline char *add_str(char *p, const char *str) -{ - strcpy(p, str); - return p + strlen(str); -} - -static struct txbit { - unsigned flag; - const char *name; - int skip_for_len; -} txbits[] = { - { PERF_TXN_ELISION, "EL ", 0 }, - { PERF_TXN_TRANSACTION, "TX ", 1 }, - { PERF_TXN_SYNC, "SYNC ", 1 }, - { PERF_TXN_ASYNC, "ASYNC ", 0 }, - { PERF_TXN_RETRY, "RETRY ", 0 }, - { PERF_TXN_CONFLICT, "CON ", 0 }, - { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 }, - { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 }, - { 0, NULL, 0 } -}; - -int hist_entry__transaction_len(void) -{ - int i; - int len = 0; - - for (i = 0; txbits[i].name; i++) { - if (!txbits[i].skip_for_len) - len += strlen(txbits[i].name); - } - len += 4; /* :XX<space> */ - return len; -} - -static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf, - size_t size, unsigned int width) -{ - u64 t = he->transaction; - char buf[128]; - char *p = buf; - int i; - - buf[0] = 0; - for (i = 0; txbits[i].name; i++) - if (txbits[i].flag & t) - p = add_str(p, txbits[i].name); - if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC))) - p = add_str(p, "NEITHER "); - if (t & PERF_TXN_ABORT_MASK) { - sprintf(p, ":%" PRIx64, - (t & PERF_TXN_ABORT_MASK) >> - PERF_TXN_ABORT_SHIFT); - p += strlen(p); - } - - return repsep_snprintf(bf, size, "%-*s", width, buf); -} - -struct sort_entry sort_transaction = { - .se_header = "Transaction ", - .se_cmp = sort__transaction_cmp, - .se_snprintf = hist_entry__transaction_snprintf, - .se_width_idx = HISTC_TRANSACTION, -}; - struct sort_dimension { const char *name; struct sort_entry *entry; @@ -987,7 +876,6 @@ static struct sort_dimension common_sort_dimensions[] = { DIM(SORT_SRCLINE, "srcline", sort_srcline), DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), - DIM(SORT_TRANSACTION, "transaction", sort_transaction), }; #undef DIM @@ -1000,8 +888,6 @@ static struct sort_dimension bstack_sort_dimensions[] = { DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from), DIM(SORT_SYM_TO, "symbol_to", sort_sym_to), DIM(SORT_MISPREDICT, "mispredict", sort_mispredict), - DIM(SORT_IN_TX, "in_tx", sort_in_tx), - DIM(SORT_ABORT, "abort", sort_abort), }; #undef DIM @@ -1123,7 +1009,7 @@ int setup_sorting(void) return ret; } -static void sort_entry__setup_elide(struct sort_entry *se, +static void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, const char *list_name, FILE *fp) { @@ -1131,14 +1017,12 @@ static void sort_entry__setup_elide(struct sort_entry *se, if (fp != NULL) fprintf(fp, "# %s: %s\n", list_name, strlist__entry(list, 0)->s); - se->elide = true; + self->elide = true; } } void sort__setup_elide(FILE *output) { - struct sort_entry *se; - sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", output); sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, @@ -1174,15 +1058,4 @@ void sort__setup_elide(FILE *output) "snoop", output); } - /* - * It makes no sense to elide all of sort entries. - * Just revert them to show up again. - */ - list_for_each_entry(se, &hist_entry__sort_list, list) { - if (!se->elide) - return; - } - - list_for_each_entry(se, &hist_entry__sort_list, list) - se->elide = false; } diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 43e5ff4..4e80dbd 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -22,6 +22,7 @@ #include "parse-events.h" #include "thread.h" +#include "sort.h" extern regex_t parent_regex; extern const char *sort_order; @@ -83,9 +84,7 @@ struct hist_entry { struct he_stat stat; struct map_symbol ms; struct thread *thread; - struct comm *comm; u64 ip; - u64 transaction; s32 cpu; struct hist_entry_diff diff; @@ -146,7 +145,6 @@ enum sort_type { SORT_SRCLINE, SORT_LOCAL_WEIGHT, SORT_GLOBAL_WEIGHT, - SORT_TRANSACTION, /* branch stack specific sort keys */ __SORT_BRANCH_STACK, @@ -155,8 +153,6 @@ enum sort_type { SORT_SYM_FROM, SORT_SYM_TO, SORT_MISPREDICT, - SORT_ABORT, - SORT_IN_TX, /* memory mode specific sort keys */ __SORT_MEMORY_MODE, @@ -179,7 +175,7 @@ struct sort_entry { int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *); int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *); - int (*se_snprintf)(struct hist_entry *he, char *bf, size_t size, + int (*se_snprintf)(struct hist_entry *self, char *bf, size_t size, unsigned int width); u8 se_width_idx; bool elide; diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c deleted file mode 100644 index d11aefb..0000000 --- a/tools/perf/util/srcline.c +++ /dev/null @@ -1,265 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <linux/kernel.h> - -#include "util/dso.h" -#include "util/util.h" -#include "util/debug.h" - -#ifdef HAVE_LIBBFD_SUPPORT - -/* - * Implement addr2line using libbfd. - */ -#define PACKAGE "perf" -#include <bfd.h> - -struct a2l_data { - const char *input; - unsigned long addr; - - bool found; - const char *filename; - const char *funcname; - unsigned line; - - bfd *abfd; - asymbol **syms; -}; - -static int bfd_error(const char *string) -{ - const char *errmsg; - - errmsg = bfd_errmsg(bfd_get_error()); - fflush(stdout); - - if (string) - pr_debug("%s: %s\n", string, errmsg); - else - pr_debug("%s\n", errmsg); - - return -1; -} - -static int slurp_symtab(bfd *abfd, struct a2l_data *a2l) -{ - long storage; - long symcount; - asymbol **syms; - bfd_boolean dynamic = FALSE; - - if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0) - return bfd_error(bfd_get_filename(abfd)); - - storage = bfd_get_symtab_upper_bound(abfd); - if (storage == 0L) { - storage = bfd_get_dynamic_symtab_upper_bound(abfd); - dynamic = TRUE; - } - if (storage < 0L) - return bfd_error(bfd_get_filename(abfd)); - - syms = malloc(storage); - if (dynamic) - symcount = bfd_canonicalize_dynamic_symtab(abfd, syms); - else - symcount = bfd_canonicalize_symtab(abfd, syms); - - if (symcount < 0) { - free(syms); - return bfd_error(bfd_get_filename(abfd)); - } - - a2l->syms = syms; - return 0; -} - -static void find_address_in_section(bfd *abfd, asection *section, void *data) -{ - bfd_vma pc, vma; - bfd_size_type size; - struct a2l_data *a2l = data; - - if (a2l->found) - return; - - if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0) - return; - - pc = a2l->addr; - vma = bfd_get_section_vma(abfd, section); - size = bfd_get_section_size(section); - - if (pc < vma || pc >= vma + size) - return; - - a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma, - &a2l->filename, &a2l->funcname, - &a2l->line); -} - -static struct a2l_data *addr2line_init(const char *path) -{ - bfd *abfd; - struct a2l_data *a2l = NULL; - - abfd = bfd_openr(path, NULL); - if (abfd == NULL) - return NULL; - - if (!bfd_check_format(abfd, bfd_object)) - goto out; - - a2l = zalloc(sizeof(*a2l)); - if (a2l == NULL) - goto out; - - a2l->abfd = abfd; - a2l->input = strdup(path); - if (a2l->input == NULL) - goto out; - - if (slurp_symtab(abfd, a2l)) - goto out; - - return a2l; - -out: - if (a2l) { - free((void *)a2l->input); - free(a2l); - } - bfd_close(abfd); - return NULL; -} - -static void addr2line_cleanup(struct a2l_data *a2l) -{ - if (a2l->abfd) - bfd_close(a2l->abfd); - free((void *)a2l->input); - free(a2l->syms); - free(a2l); -} - -static int addr2line(const char *dso_name, unsigned long addr, - char **file, unsigned int *line) -{ - int ret = 0; - struct a2l_data *a2l; - - a2l = addr2line_init(dso_name); - if (a2l == NULL) { - pr_warning("addr2line_init failed for %s\n", dso_name); - return 0; - } - - a2l->addr = addr; - bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); - - if (a2l->found && a2l->filename) { - *file = strdup(a2l->filename); - *line = a2l->line; - - if (*file) - ret = 1; - } - - addr2line_cleanup(a2l); - return ret; -} - -#else /* HAVE_LIBBFD_SUPPORT */ - -static int addr2line(const char *dso_name, unsigned long addr, - char **file, unsigned int *line_nr) -{ - FILE *fp; - char cmd[PATH_MAX]; - char *filename = NULL; - size_t len; - char *sep; - int ret = 0; - - scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64, - dso_name, addr); - - fp = popen(cmd, "r"); - if (fp == NULL) { - pr_warning("popen failed for %s\n", dso_name); - return 0; - } - - if (getline(&filename, &len, fp) < 0 || !len) { - pr_warning("addr2line has no output for %s\n", dso_name); - goto out; - } - - sep = strchr(filename, '\n'); - if (sep) - *sep = '\0'; - - if (!strcmp(filename, "??:0")) { - pr_debug("no debugging info in %s\n", dso_name); - free(filename); - goto out; - } - - sep = strchr(filename, ':'); - if (sep) { - *sep++ = '\0'; - *file = filename; - *line_nr = strtoul(sep, NULL, 0); - ret = 1; - } -out: - pclose(fp); - return ret; -} -#endif /* HAVE_LIBBFD_SUPPORT */ - -char *get_srcline(struct dso *dso, unsigned long addr) -{ - char *file = NULL; - unsigned line = 0; - char *srcline; - char *dso_name = dso->long_name; - size_t size; - - if (!dso->has_srcline) - return SRCLINE_UNKNOWN; - - if (dso_name[0] == '[') - goto out; - - if (!strncmp(dso_name, "/tmp/perf-", 10)) - goto out; - - if (!addr2line(dso_name, addr, &file, &line)) - goto out; - - /* just calculate actual length */ - size = snprintf(NULL, 0, "%s:%u", file, line) + 1; - - srcline = malloc(size); - if (srcline) - snprintf(srcline, size, "%s:%u", file, line); - else - srcline = SRCLINE_UNKNOWN; - - free(file); - return srcline; - -out: - dso->has_srcline = 0; - return SRCLINE_UNKNOWN; -} - -void free_srcline(char *srcline) -{ - if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0) - free(srcline); -} diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c index 3edd053..834c8eb 100644 --- a/tools/perf/util/strfilter.c +++ b/tools/perf/util/strfilter.c @@ -10,22 +10,22 @@ static const char *OP_not = "!"; /* Logical NOT */ #define is_operator(c) ((c) == '|' || (c) == '&' || (c) == '!') #define is_separator(c) (is_operator(c) || (c) == '(' || (c) == ')') -static void strfilter_node__delete(struct strfilter_node *node) +static void strfilter_node__delete(struct strfilter_node *self) { - if (node) { - if (node->p && !is_operator(*node->p)) - free((char *)node->p); - strfilter_node__delete(node->l); - strfilter_node__delete(node->r); - free(node); + if (self) { + if (self->p && !is_operator(*self->p)) + free((char *)self->p); + strfilter_node__delete(self->l); + strfilter_node__delete(self->r); + free(self); } } -void strfilter__delete(struct strfilter *filter) +void strfilter__delete(struct strfilter *self) { - if (filter) { - strfilter_node__delete(filter->root); - free(filter); + if (self) { + strfilter_node__delete(self->root); + free(self); } } @@ -62,15 +62,15 @@ static struct strfilter_node *strfilter_node__alloc(const char *op, struct strfilter_node *l, struct strfilter_node *r) { - struct strfilter_node *node = zalloc(sizeof(*node)); + struct strfilter_node *ret = zalloc(sizeof(struct strfilter_node)); - if (node) { - node->p = op; - node->l = l; - node->r = r; + if (ret) { + ret->p = op; + ret->l = l; + ret->r = r; } - return node; + return ret; } static struct strfilter_node *strfilter_node__new(const char *s, @@ -154,46 +154,46 @@ error: */ struct strfilter *strfilter__new(const char *rules, const char **err) { - struct strfilter *filter = zalloc(sizeof(*filter)); + struct strfilter *ret = zalloc(sizeof(struct strfilter)); const char *ep = NULL; - if (filter) - filter->root = strfilter_node__new(rules, &ep); + if (ret) + ret->root = strfilter_node__new(rules, &ep); - if (!filter || !filter->root || *ep != '\0') { + if (!ret || !ret->root || *ep != '\0') { if (err) *err = ep; - strfilter__delete(filter); - filter = NULL; + strfilter__delete(ret); + ret = NULL; } - return filter; + return ret; } -static bool strfilter_node__compare(struct strfilter_node *node, +static bool strfilter_node__compare(struct strfilter_node *self, const char *str) { - if (!node || !node->p) + if (!self || !self->p) return false; - switch (*node->p) { + switch (*self->p) { case '|': /* OR */ - return strfilter_node__compare(node->l, str) || - strfilter_node__compare(node->r, str); + return strfilter_node__compare(self->l, str) || + strfilter_node__compare(self->r, str); case '&': /* AND */ - return strfilter_node__compare(node->l, str) && - strfilter_node__compare(node->r, str); + return strfilter_node__compare(self->l, str) && + strfilter_node__compare(self->r, str); case '!': /* NOT */ - return !strfilter_node__compare(node->r, str); + return !strfilter_node__compare(self->r, str); default: - return strglobmatch(str, node->p); + return strglobmatch(str, self->p); } } /* Return true if STR matches the filter rules */ -bool strfilter__compare(struct strfilter *filter, const char *str) +bool strfilter__compare(struct strfilter *self, const char *str) { - if (!filter) + if (!self) return false; - return strfilter_node__compare(filter->root, str); + return strfilter_node__compare(self->root, str); } diff --git a/tools/perf/util/strfilter.h b/tools/perf/util/strfilter.h index fe611f3..00f58a7 100644 --- a/tools/perf/util/strfilter.h +++ b/tools/perf/util/strfilter.h @@ -30,19 +30,19 @@ struct strfilter *strfilter__new(const char *rules, const char **err); /** * strfilter__compare - compare given string and a string filter - * @filter: String filter + * @self: String filter * @str: target string * - * Compare @str and @filter. Return true if the str match the rule + * Compare @str and @self. Return true if the str match the rule */ -bool strfilter__compare(struct strfilter *filter, const char *str); +bool strfilter__compare(struct strfilter *self, const char *str); /** * strfilter__delete - delete a string filter - * @filter: String filter to delete + * @self: String filter to delete * - * Delete @filter. + * Delete @self. */ -void strfilter__delete(struct strfilter *filter); +void strfilter__delete(struct strfilter *self); #endif diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index eed0b96..a9c829b 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -8,7 +8,7 @@ #include "symbol.h" #include "debug.h" -#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT +#ifndef HAVE_ELF_GETPHDRNUM static int elf_getphdrnum(Elf *elf, size_t *dst) { GElf_Ehdr gehdr; @@ -487,27 +487,27 @@ int filename__read_debuglink(const char *filename, char *debuglink, ek = elf_kind(elf); if (ek != ELF_K_ELF) - goto out_elf_end; + goto out_close; if (gelf_getehdr(elf, &ehdr) == NULL) { pr_err("%s: cannot get elf header.\n", __func__); - goto out_elf_end; + goto out_close; } sec = elf_section_by_name(elf, &ehdr, &shdr, ".gnu_debuglink", NULL); if (sec == NULL) - goto out_elf_end; + goto out_close; data = elf_getdata(sec, NULL); if (data == NULL) - goto out_elf_end; + goto out_close; /* the start of this section is a zero-terminated string */ strncpy(debuglink, data->d_buf, size); -out_elf_end: elf_end(elf); + out_close: close(fd); out: @@ -1018,601 +1018,6 @@ int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, return err; } -static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len) -{ - ssize_t r; - size_t n; - int err = -1; - char *buf = malloc(page_size); - - if (buf == NULL) - return -1; - - if (lseek(to, to_offs, SEEK_SET) != to_offs) - goto out; - - if (lseek(from, from_offs, SEEK_SET) != from_offs) - goto out; - - while (len) { - n = page_size; - if (len < n) - n = len; - /* Use read because mmap won't work on proc files */ - r = read(from, buf, n); - if (r < 0) - goto out; - if (!r) - break; - n = r; - r = write(to, buf, n); - if (r < 0) - goto out; - if ((size_t)r != n) - goto out; - len -= n; - } - - err = 0; -out: - free(buf); - return err; -} - -struct kcore { - int fd; - int elfclass; - Elf *elf; - GElf_Ehdr ehdr; -}; - -static int kcore__open(struct kcore *kcore, const char *filename) -{ - GElf_Ehdr *ehdr; - - kcore->fd = open(filename, O_RDONLY); - if (kcore->fd == -1) - return -1; - - kcore->elf = elf_begin(kcore->fd, ELF_C_READ, NULL); - if (!kcore->elf) - goto out_close; - - kcore->elfclass = gelf_getclass(kcore->elf); - if (kcore->elfclass == ELFCLASSNONE) - goto out_end; - - ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr); - if (!ehdr) - goto out_end; - - return 0; - -out_end: - elf_end(kcore->elf); -out_close: - close(kcore->fd); - return -1; -} - -static int kcore__init(struct kcore *kcore, char *filename, int elfclass, - bool temp) -{ - GElf_Ehdr *ehdr; - - kcore->elfclass = elfclass; - - if (temp) - kcore->fd = mkstemp(filename); - else - kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400); - if (kcore->fd == -1) - return -1; - - kcore->elf = elf_begin(kcore->fd, ELF_C_WRITE, NULL); - if (!kcore->elf) - goto out_close; - - if (!gelf_newehdr(kcore->elf, elfclass)) - goto out_end; - - ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr); - if (!ehdr) - goto out_end; - - return 0; - -out_end: - elf_end(kcore->elf); -out_close: - close(kcore->fd); - unlink(filename); - return -1; -} - -static void kcore__close(struct kcore *kcore) -{ - elf_end(kcore->elf); - close(kcore->fd); -} - -static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count) -{ - GElf_Ehdr *ehdr = &to->ehdr; - GElf_Ehdr *kehdr = &from->ehdr; - - memcpy(ehdr->e_ident, kehdr->e_ident, EI_NIDENT); - ehdr->e_type = kehdr->e_type; - ehdr->e_machine = kehdr->e_machine; - ehdr->e_version = kehdr->e_version; - ehdr->e_entry = 0; - ehdr->e_shoff = 0; - ehdr->e_flags = kehdr->e_flags; - ehdr->e_phnum = count; - ehdr->e_shentsize = 0; - ehdr->e_shnum = 0; - ehdr->e_shstrndx = 0; - - if (from->elfclass == ELFCLASS32) { - ehdr->e_phoff = sizeof(Elf32_Ehdr); - ehdr->e_ehsize = sizeof(Elf32_Ehdr); - ehdr->e_phentsize = sizeof(Elf32_Phdr); - } else { - ehdr->e_phoff = sizeof(Elf64_Ehdr); - ehdr->e_ehsize = sizeof(Elf64_Ehdr); - ehdr->e_phentsize = sizeof(Elf64_Phdr); - } - - if (!gelf_update_ehdr(to->elf, ehdr)) - return -1; - - if (!gelf_newphdr(to->elf, count)) - return -1; - - return 0; -} - -static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset, - u64 addr, u64 len) -{ - GElf_Phdr gphdr; - GElf_Phdr *phdr; - - phdr = gelf_getphdr(kcore->elf, idx, &gphdr); - if (!phdr) - return -1; - - phdr->p_type = PT_LOAD; - phdr->p_flags = PF_R | PF_W | PF_X; - phdr->p_offset = offset; - phdr->p_vaddr = addr; - phdr->p_paddr = 0; - phdr->p_filesz = len; - phdr->p_memsz = len; - phdr->p_align = page_size; - - if (!gelf_update_phdr(kcore->elf, idx, phdr)) - return -1; - - return 0; -} - -static off_t kcore__write(struct kcore *kcore) -{ - return elf_update(kcore->elf, ELF_C_WRITE); -} - -struct phdr_data { - off_t offset; - u64 addr; - u64 len; -}; - -struct kcore_copy_info { - u64 stext; - u64 etext; - u64 first_symbol; - u64 last_symbol; - u64 first_module; - u64 last_module_symbol; - struct phdr_data kernel_map; - struct phdr_data modules_map; -}; - -static int kcore_copy__process_kallsyms(void *arg, const char *name, char type, - u64 start) -{ - struct kcore_copy_info *kci = arg; - - if (!symbol_type__is_a(type, MAP__FUNCTION)) - return 0; - - if (strchr(name, '[')) { - if (start > kci->last_module_symbol) - kci->last_module_symbol = start; - return 0; - } - - if (!kci->first_symbol || start < kci->first_symbol) - kci->first_symbol = start; - - if (!kci->last_symbol || start > kci->last_symbol) - kci->last_symbol = start; - - if (!strcmp(name, "_stext")) { - kci->stext = start; - return 0; - } - - if (!strcmp(name, "_etext")) { - kci->etext = start; - return 0; - } - - return 0; -} - -static int kcore_copy__parse_kallsyms(struct kcore_copy_info *kci, - const char *dir) -{ - char kallsyms_filename[PATH_MAX]; - - scnprintf(kallsyms_filename, PATH_MAX, "%s/kallsyms", dir); - - if (symbol__restricted_filename(kallsyms_filename, "/proc/kallsyms")) - return -1; - - if (kallsyms__parse(kallsyms_filename, kci, - kcore_copy__process_kallsyms) < 0) - return -1; - - return 0; -} - -static int kcore_copy__process_modules(void *arg, - const char *name __maybe_unused, - u64 start) -{ - struct kcore_copy_info *kci = arg; - - if (!kci->first_module || start < kci->first_module) - kci->first_module = start; - - return 0; -} - -static int kcore_copy__parse_modules(struct kcore_copy_info *kci, - const char *dir) -{ - char modules_filename[PATH_MAX]; - - scnprintf(modules_filename, PATH_MAX, "%s/modules", dir); - - if (symbol__restricted_filename(modules_filename, "/proc/modules")) - return -1; - - if (modules__parse(modules_filename, kci, - kcore_copy__process_modules) < 0) - return -1; - - return 0; -} - -static void kcore_copy__map(struct phdr_data *p, u64 start, u64 end, u64 pgoff, - u64 s, u64 e) -{ - if (p->addr || s < start || s >= end) - return; - - p->addr = s; - p->offset = (s - start) + pgoff; - p->len = e < end ? e - s : end - s; -} - -static int kcore_copy__read_map(u64 start, u64 len, u64 pgoff, void *data) -{ - struct kcore_copy_info *kci = data; - u64 end = start + len; - - kcore_copy__map(&kci->kernel_map, start, end, pgoff, kci->stext, - kci->etext); - - kcore_copy__map(&kci->modules_map, start, end, pgoff, kci->first_module, - kci->last_module_symbol); - - return 0; -} - -static int kcore_copy__read_maps(struct kcore_copy_info *kci, Elf *elf) -{ - if (elf_read_maps(elf, true, kcore_copy__read_map, kci) < 0) - return -1; - - return 0; -} - -static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir, - Elf *elf) -{ - if (kcore_copy__parse_kallsyms(kci, dir)) - return -1; - - if (kcore_copy__parse_modules(kci, dir)) - return -1; - - if (kci->stext) - kci->stext = round_down(kci->stext, page_size); - else - kci->stext = round_down(kci->first_symbol, page_size); - - if (kci->etext) { - kci->etext = round_up(kci->etext, page_size); - } else if (kci->last_symbol) { - kci->etext = round_up(kci->last_symbol, page_size); - kci->etext += page_size; - } - - kci->first_module = round_down(kci->first_module, page_size); - - if (kci->last_module_symbol) { - kci->last_module_symbol = round_up(kci->last_module_symbol, - page_size); - kci->last_module_symbol += page_size; - } - - if (!kci->stext || !kci->etext) - return -1; - - if (kci->first_module && !kci->last_module_symbol) - return -1; - - return kcore_copy__read_maps(kci, elf); -} - -static int kcore_copy__copy_file(const char *from_dir, const char *to_dir, - const char *name) -{ - char from_filename[PATH_MAX]; - char to_filename[PATH_MAX]; - - scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name); - scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name); - - return copyfile_mode(from_filename, to_filename, 0400); -} - -static int kcore_copy__unlink(const char *dir, const char *name) -{ - char filename[PATH_MAX]; - - scnprintf(filename, PATH_MAX, "%s/%s", dir, name); - - return unlink(filename); -} - -static int kcore_copy__compare_fds(int from, int to) -{ - char *buf_from; - char *buf_to; - ssize_t ret; - size_t len; - int err = -1; - - buf_from = malloc(page_size); - buf_to = malloc(page_size); - if (!buf_from || !buf_to) - goto out; - - while (1) { - /* Use read because mmap won't work on proc files */ - ret = read(from, buf_from, page_size); - if (ret < 0) - goto out; - - if (!ret) - break; - - len = ret; - - if (readn(to, buf_to, len) != (int)len) - goto out; - - if (memcmp(buf_from, buf_to, len)) - goto out; - } - - err = 0; -out: - free(buf_to); - free(buf_from); - return err; -} - -static int kcore_copy__compare_files(const char *from_filename, - const char *to_filename) -{ - int from, to, err = -1; - - from = open(from_filename, O_RDONLY); - if (from < 0) - return -1; - - to = open(to_filename, O_RDONLY); - if (to < 0) - goto out_close_from; - - err = kcore_copy__compare_fds(from, to); - - close(to); -out_close_from: - close(from); - return err; -} - -static int kcore_copy__compare_file(const char *from_dir, const char *to_dir, - const char *name) -{ - char from_filename[PATH_MAX]; - char to_filename[PATH_MAX]; - - scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name); - scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name); - - return kcore_copy__compare_files(from_filename, to_filename); -} - -/** - * kcore_copy - copy kallsyms, modules and kcore from one directory to another. - * @from_dir: from directory - * @to_dir: to directory - * - * This function copies kallsyms, modules and kcore files from one directory to - * another. kallsyms and modules are copied entirely. Only code segments are - * copied from kcore. It is assumed that two segments suffice: one for the - * kernel proper and one for all the modules. The code segments are determined - * from kallsyms and modules files. The kernel map starts at _stext or the - * lowest function symbol, and ends at _etext or the highest function symbol. - * The module map starts at the lowest module address and ends at the highest - * module symbol. Start addresses are rounded down to the nearest page. End - * addresses are rounded up to the nearest page. An extra page is added to the - * highest kernel symbol and highest module symbol to, hopefully, encompass that - * symbol too. Because it contains only code sections, the resulting kcore is - * unusual. One significant peculiarity is that the mapping (start -> pgoff) - * is not the same for the kernel map and the modules map. That happens because - * the data is copied adjacently whereas the original kcore has gaps. Finally, - * kallsyms and modules files are compared with their copies to check that - * modules have not been loaded or unloaded while the copies were taking place. - * - * Return: %0 on success, %-1 on failure. - */ -int kcore_copy(const char *from_dir, const char *to_dir) -{ - struct kcore kcore; - struct kcore extract; - size_t count = 2; - int idx = 0, err = -1; - off_t offset = page_size, sz, modules_offset = 0; - struct kcore_copy_info kci = { .stext = 0, }; - char kcore_filename[PATH_MAX]; - char extract_filename[PATH_MAX]; - - if (kcore_copy__copy_file(from_dir, to_dir, "kallsyms")) - return -1; - - if (kcore_copy__copy_file(from_dir, to_dir, "modules")) - goto out_unlink_kallsyms; - - scnprintf(kcore_filename, PATH_MAX, "%s/kcore", from_dir); - scnprintf(extract_filename, PATH_MAX, "%s/kcore", to_dir); - - if (kcore__open(&kcore, kcore_filename)) - goto out_unlink_modules; - - if (kcore_copy__calc_maps(&kci, from_dir, kcore.elf)) - goto out_kcore_close; - - if (kcore__init(&extract, extract_filename, kcore.elfclass, false)) - goto out_kcore_close; - - if (!kci.modules_map.addr) - count -= 1; - - if (kcore__copy_hdr(&kcore, &extract, count)) - goto out_extract_close; - - if (kcore__add_phdr(&extract, idx++, offset, kci.kernel_map.addr, - kci.kernel_map.len)) - goto out_extract_close; - - if (kci.modules_map.addr) { - modules_offset = offset + kci.kernel_map.len; - if (kcore__add_phdr(&extract, idx, modules_offset, - kci.modules_map.addr, kci.modules_map.len)) - goto out_extract_close; - } - - sz = kcore__write(&extract); - if (sz < 0 || sz > offset) - goto out_extract_close; - - if (copy_bytes(kcore.fd, kci.kernel_map.offset, extract.fd, offset, - kci.kernel_map.len)) - goto out_extract_close; - - if (modules_offset && copy_bytes(kcore.fd, kci.modules_map.offset, - extract.fd, modules_offset, - kci.modules_map.len)) - goto out_extract_close; - - if (kcore_copy__compare_file(from_dir, to_dir, "modules")) - goto out_extract_close; - - if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms")) - goto out_extract_close; - - err = 0; - -out_extract_close: - kcore__close(&extract); - if (err) - unlink(extract_filename); -out_kcore_close: - kcore__close(&kcore); -out_unlink_modules: - if (err) - kcore_copy__unlink(to_dir, "modules"); -out_unlink_kallsyms: - if (err) - kcore_copy__unlink(to_dir, "kallsyms"); - - return err; -} - -int kcore_extract__create(struct kcore_extract *kce) -{ - struct kcore kcore; - struct kcore extract; - size_t count = 1; - int idx = 0, err = -1; - off_t offset = page_size, sz; - - if (kcore__open(&kcore, kce->kcore_filename)) - return -1; - - strcpy(kce->extract_filename, PERF_KCORE_EXTRACT); - if (kcore__init(&extract, kce->extract_filename, kcore.elfclass, true)) - goto out_kcore_close; - - if (kcore__copy_hdr(&kcore, &extract, count)) - goto out_extract_close; - - if (kcore__add_phdr(&extract, idx, offset, kce->addr, kce->len)) - goto out_extract_close; - - sz = kcore__write(&extract); - if (sz < 0 || sz > offset) - goto out_extract_close; - - if (copy_bytes(kcore.fd, kce->offs, extract.fd, offset, kce->len)) - goto out_extract_close; - - err = 0; - -out_extract_close: - kcore__close(&extract); - if (err) - unlink(kce->extract_filename); -out_kcore_close: - kcore__close(&kcore); - - return err; -} - -void kcore_extract__delete(struct kcore_extract *kce) -{ - unlink(kce->extract_filename); -} - void symbol__elf_init(void) { elf_version(EV_CURRENT); diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 2d2dd05..3a802c3 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c @@ -308,21 +308,6 @@ int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused, return -1; } -int kcore_extract__create(struct kcore_extract *kce __maybe_unused) -{ - return -1; -} - -void kcore_extract__delete(struct kcore_extract *kce __maybe_unused) -{ -} - -int kcore_copy(const char *from_dir __maybe_unused, - const char *to_dir __maybe_unused) -{ - return -1; -} - void symbol__elf_init(void) { } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index c0c3696..7eb0362 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -51,7 +51,6 @@ static enum dso_binary_type binary_type_symtab[] = { DSO_BINARY_TYPE__SYSTEM_PATH_DSO, DSO_BINARY_TYPE__GUEST_KMODULE, DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, - DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, DSO_BINARY_TYPE__NOT_FOUND, }; @@ -160,12 +159,10 @@ again: if (choose_best_symbol(curr, next) == SYMBOL_A) { rb_erase(&next->rb_node, symbols); - symbol__delete(next); goto again; } else { nd = rb_next(&curr->rb_node); rb_erase(&curr->rb_node, symbols); - symbol__delete(curr); } } } @@ -502,64 +499,6 @@ out_failure: return -1; } -int modules__parse(const char *filename, void *arg, - int (*process_module)(void *arg, const char *name, - u64 start)) -{ - char *line = NULL; - size_t n; - FILE *file; - int err = 0; - - file = fopen(filename, "r"); - if (file == NULL) - return -1; - - while (1) { - char name[PATH_MAX]; - u64 start; - char *sep; - ssize_t line_len; - - line_len = getline(&line, &n, file); - if (line_len < 0) { - if (feof(file)) - break; - err = -1; - goto out; - } - - if (!line) { - err = -1; - goto out; - } - - line[--line_len] = '\0'; /* \n */ - - sep = strrchr(line, 'x'); - if (sep == NULL) - continue; - - hex2u64(sep + 1, &start); - - sep = strchr(line, ' '); - if (sep == NULL) - continue; - - *sep = '\0'; - - scnprintf(name, sizeof(name), "[%s]", line); - - err = process_module(arg, name, start); - if (err) - break; - } -out: - free(line); - fclose(file); - return err; -} - struct process_kallsyms_args { struct map *map; struct dso *dso; @@ -800,242 +739,51 @@ bool symbol__restricted_filename(const char *filename, return restricted; } -struct module_info { - struct rb_node rb_node; - char *name; - u64 start; +struct kcore_mapfn_data { + struct dso *dso; + enum map_type type; + struct list_head maps; }; -static void add_module(struct module_info *mi, struct rb_root *modules) -{ - struct rb_node **p = &modules->rb_node; - struct rb_node *parent = NULL; - struct module_info *m; - - while (*p != NULL) { - parent = *p; - m = rb_entry(parent, struct module_info, rb_node); - if (strcmp(mi->name, m->name) < 0) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; - } - rb_link_node(&mi->rb_node, parent, p); - rb_insert_color(&mi->rb_node, modules); -} - -static void delete_modules(struct rb_root *modules) -{ - struct module_info *mi; - struct rb_node *next = rb_first(modules); - - while (next) { - mi = rb_entry(next, struct module_info, rb_node); - next = rb_next(&mi->rb_node); - rb_erase(&mi->rb_node, modules); - free(mi->name); - free(mi); - } -} - -static struct module_info *find_module(const char *name, - struct rb_root *modules) -{ - struct rb_node *n = modules->rb_node; - - while (n) { - struct module_info *m; - int cmp; - - m = rb_entry(n, struct module_info, rb_node); - cmp = strcmp(name, m->name); - if (cmp < 0) - n = n->rb_left; - else if (cmp > 0) - n = n->rb_right; - else - return m; - } - - return NULL; -} - -static int __read_proc_modules(void *arg, const char *name, u64 start) +static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) { - struct rb_root *modules = arg; - struct module_info *mi; - - mi = zalloc(sizeof(struct module_info)); - if (!mi) - return -ENOMEM; - - mi->name = strdup(name); - mi->start = start; + struct kcore_mapfn_data *md = data; + struct map *map; - if (!mi->name) { - free(mi); + map = map__new2(start, md->dso, md->type); + if (map == NULL) return -ENOMEM; - } - - add_module(mi, modules); - - return 0; -} -static int read_proc_modules(const char *filename, struct rb_root *modules) -{ - if (symbol__restricted_filename(filename, "/proc/modules")) - return -1; + map->end = map->start + len; + map->pgoff = pgoff; - if (modules__parse(filename, modules, __read_proc_modules)) { - delete_modules(modules); - return -1; - } + list_add(&map->node, &md->maps); return 0; } -int compare_proc_modules(const char *from, const char *to) -{ - struct rb_root from_modules = RB_ROOT; - struct rb_root to_modules = RB_ROOT; - struct rb_node *from_node, *to_node; - struct module_info *from_m, *to_m; - int ret = -1; - - if (read_proc_modules(from, &from_modules)) - return -1; - - if (read_proc_modules(to, &to_modules)) - goto out_delete_from; - - from_node = rb_first(&from_modules); - to_node = rb_first(&to_modules); - while (from_node) { - if (!to_node) - break; - - from_m = rb_entry(from_node, struct module_info, rb_node); - to_m = rb_entry(to_node, struct module_info, rb_node); - - if (from_m->start != to_m->start || - strcmp(from_m->name, to_m->name)) - break; - - from_node = rb_next(from_node); - to_node = rb_next(to_node); - } - - if (!from_node && !to_node) - ret = 0; - - delete_modules(&to_modules); -out_delete_from: - delete_modules(&from_modules); - - return ret; -} - -static int do_validate_kcore_modules(const char *filename, struct map *map, - struct map_groups *kmaps) -{ - struct rb_root modules = RB_ROOT; - struct map *old_map; - int err; - - err = read_proc_modules(filename, &modules); - if (err) - return err; - - old_map = map_groups__first(kmaps, map->type); - while (old_map) { - struct map *next = map_groups__next(old_map); - struct module_info *mi; - - if (old_map == map || old_map->start == map->start) { - /* The kernel map */ - old_map = next; - continue; - } - - /* Module must be in memory at the same address */ - mi = find_module(old_map->dso->short_name, &modules); - if (!mi || mi->start != old_map->start) { - err = -EINVAL; - goto out; - } - - old_map = next; - } -out: - delete_modules(&modules); - return err; -} - /* - * If kallsyms is referenced by name then we look for filename in the same + * If kallsyms is referenced by name then we look for kcore in the same * directory. */ -static bool filename_from_kallsyms_filename(char *filename, - const char *base_name, - const char *kallsyms_filename) +static bool kcore_filename_from_kallsyms_filename(char *kcore_filename, + const char *kallsyms_filename) { char *name; - strcpy(filename, kallsyms_filename); - name = strrchr(filename, '/'); + strcpy(kcore_filename, kallsyms_filename); + name = strrchr(kcore_filename, '/'); if (!name) return false; - name += 1; - - if (!strcmp(name, "kallsyms")) { - strcpy(name, base_name); + if (!strcmp(name, "/kallsyms")) { + strcpy(name, "/kcore"); return true; } return false; } -static int validate_kcore_modules(const char *kallsyms_filename, - struct map *map) -{ - struct map_groups *kmaps = map__kmap(map)->kmaps; - char modules_filename[PATH_MAX]; - - if (!filename_from_kallsyms_filename(modules_filename, "modules", - kallsyms_filename)) - return -EINVAL; - - if (do_validate_kcore_modules(modules_filename, map, kmaps)) - return -EINVAL; - - return 0; -} - -struct kcore_mapfn_data { - struct dso *dso; - enum map_type type; - struct list_head maps; -}; - -static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) -{ - struct kcore_mapfn_data *md = data; - struct map *map; - - map = map__new2(start, md->dso, md->type); - if (map == NULL) - return -ENOMEM; - - map->end = map->start + len; - map->pgoff = pgoff; - - list_add(&map->node, &md->maps); - - return 0; -} - static int dso__load_kcore(struct dso *dso, struct map *map, const char *kallsyms_filename) { @@ -1052,12 +800,8 @@ static int dso__load_kcore(struct dso *dso, struct map *map, if (map != machine->vmlinux_maps[map->type]) return -EINVAL; - if (!filename_from_kallsyms_filename(kcore_filename, "kcore", - kallsyms_filename)) - return -EINVAL; - - /* All modules must be present at their original addresses */ - if (validate_kcore_modules(kallsyms_filename, map)) + if (!kcore_filename_from_kallsyms_filename(kcore_filename, + kallsyms_filename)) return -EINVAL; md.dso = dso; @@ -1444,105 +1188,6 @@ out: return err; } -static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz) -{ - char kallsyms_filename[PATH_MAX]; - struct dirent *dent; - int ret = -1; - DIR *d; - - d = opendir(dir); - if (!d) - return -1; - - while (1) { - dent = readdir(d); - if (!dent) - break; - if (dent->d_type != DT_DIR) - continue; - scnprintf(kallsyms_filename, sizeof(kallsyms_filename), - "%s/%s/kallsyms", dir, dent->d_name); - if (!validate_kcore_modules(kallsyms_filename, map)) { - strlcpy(dir, kallsyms_filename, dir_sz); - ret = 0; - break; - } - } - - closedir(d); - - return ret; -} - -static char *dso__find_kallsyms(struct dso *dso, struct map *map) -{ - u8 host_build_id[BUILD_ID_SIZE]; - char sbuild_id[BUILD_ID_SIZE * 2 + 1]; - bool is_host = false; - char path[PATH_MAX]; - - if (!dso->has_build_id) { - /* - * Last resort, if we don't have a build-id and couldn't find - * any vmlinux file, try the running kernel kallsyms table. - */ - goto proc_kallsyms; - } - - if (sysfs__read_build_id("/sys/kernel/notes", host_build_id, - sizeof(host_build_id)) == 0) - is_host = dso__build_id_equal(dso, host_build_id); - - build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); - - /* Use /proc/kallsyms if possible */ - if (is_host) { - DIR *d; - int fd; - - /* If no cached kcore go with /proc/kallsyms */ - scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", - buildid_dir, sbuild_id); - d = opendir(path); - if (!d) - goto proc_kallsyms; - closedir(d); - - /* - * Do not check the build-id cache, until we know we cannot use - * /proc/kcore. - */ - fd = open("/proc/kcore", O_RDONLY); - if (fd != -1) { - close(fd); - /* If module maps match go with /proc/kallsyms */ - if (!validate_kcore_modules("/proc/kallsyms", map)) - goto proc_kallsyms; - } - - /* Find kallsyms in build-id cache with kcore */ - if (!find_matching_kcore(map, path, sizeof(path))) - return strdup(path); - - goto proc_kallsyms; - } - - scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", - buildid_dir, sbuild_id); - - if (access(path, F_OK)) { - pr_err("No kallsyms or vmlinux with build-id %s was found\n", - sbuild_id); - return NULL; - } - - return strdup(path); - -proc_kallsyms: - return strdup("/proc/kallsyms"); -} - static int dso__load_kernel_sym(struct dso *dso, struct map *map, symbol_filter_t filter) { @@ -1569,7 +1214,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, goto do_kallsyms; } - if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { + if (symbol_conf.vmlinux_name != NULL) { err = dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name, filter); if (err > 0) { @@ -1581,7 +1226,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, return err; } - if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { + if (vmlinux_path != NULL) { err = dso__load_vmlinux_path(dso, map, filter); if (err > 0) return err; @@ -1591,11 +1236,51 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, if (symbol_conf.symfs[0] != 0) return -1; - kallsyms_allocated_filename = dso__find_kallsyms(dso, map); - if (!kallsyms_allocated_filename) - return -1; + /* + * Say the kernel DSO was created when processing the build-id header table, + * we have a build-id, so check if it is the same as the running kernel, + * using it if it is. + */ + if (dso->has_build_id) { + u8 kallsyms_build_id[BUILD_ID_SIZE]; + char sbuild_id[BUILD_ID_SIZE * 2 + 1]; + + if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id, + sizeof(kallsyms_build_id)) == 0) { + if (dso__build_id_equal(dso, kallsyms_build_id)) { + kallsyms_filename = "/proc/kallsyms"; + goto do_kallsyms; + } + } + /* + * Now look if we have it on the build-id cache in + * $HOME/.debug/[kernel.kallsyms]. + */ + build_id__sprintf(dso->build_id, sizeof(dso->build_id), + sbuild_id); - kallsyms_filename = kallsyms_allocated_filename; + if (asprintf(&kallsyms_allocated_filename, + "%s/.debug/[kernel.kallsyms]/%s", + getenv("HOME"), sbuild_id) == -1) { + pr_err("Not enough memory for kallsyms file lookup\n"); + return -1; + } + + kallsyms_filename = kallsyms_allocated_filename; + + if (access(kallsyms_filename, F_OK)) { + pr_err("No kallsyms or vmlinux with build-id %s " + "was found\n", sbuild_id); + free(kallsyms_allocated_filename); + return -1; + } + } else { + /* + * Last resort, if we don't have a build-id and couldn't find + * any vmlinux file, try the running kernel kallsyms table. + */ + kallsyms_filename = "/proc/kallsyms"; + } do_kallsyms: err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 07de8fe..fd5b70e 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -13,7 +13,7 @@ #include <libgen.h> #include "build-id.h" -#ifdef HAVE_LIBELF_SUPPORT +#ifdef LIBELF_SUPPORT #include <libelf.h> #include <gelf.h> #endif @@ -21,7 +21,7 @@ #include "dso.h" -#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT +#ifdef HAVE_CPLUS_DEMANGLE extern char *cplus_demangle(const char *, int); static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) @@ -46,7 +46,7 @@ static inline char *bfd_demangle(void __maybe_unused *v, * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; * for newer versions we can use mmap to reduce memory usage: */ -#ifdef HAVE_LIBELF_MMAP_SUPPORT +#ifdef LIBELF_MMAP # define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP #else # define PERF_ELF_C_READ_MMAP ELF_C_READ @@ -85,7 +85,6 @@ struct symbol_conf { unsigned short priv_size; unsigned short nr_events; bool try_vmlinux_path, - ignore_vmlinux, show_kernel_path, use_modules, sort_by_name, @@ -179,7 +178,7 @@ struct symsrc { int fd; enum dso_binary_type type; -#ifdef HAVE_LIBELF_SUPPORT +#ifdef LIBELF_SUPPORT Elf *elf; GElf_Ehdr ehdr; @@ -223,9 +222,6 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size); int kallsyms__parse(const char *filename, void *arg, int (*process_symbol)(void *arg, const char *name, char type, u64 start)); -int modules__parse(const char *filename, void *arg, - int (*process_module)(void *arg, const char *name, - u64 start)); int filename__read_debuglink(const char *filename, char *debuglink, size_t size); @@ -256,21 +252,4 @@ typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data); int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, bool *is_64_bit); -#define PERF_KCORE_EXTRACT "/tmp/perf-kcore-XXXXXX" - -struct kcore_extract { - char *kcore_filename; - u64 addr; - u64 offs; - u64 len; - char extract_filename[sizeof(PERF_KCORE_EXTRACT)]; - int fd; -}; - -int kcore_extract__create(struct kcore_extract *kce); -void kcore_extract__delete(struct kcore_extract *kce); - -int kcore_copy(const char *from_dir, const char *to_dir); -int compare_proc_modules(const char *from, const char *to); - #endif /* __PERF_SYMBOL */ diff --git a/tools/perf/util/sysfs.c b/tools/perf/util/sysfs.c new file mode 100644 index 0000000..f71e9ea --- /dev/null +++ b/tools/perf/util/sysfs.c @@ -0,0 +1,60 @@ + +#include "util.h" +#include "sysfs.h" + +static const char * const sysfs_known_mountpoints[] = { + "/sys", + 0, +}; + +static int sysfs_found; +char sysfs_mountpoint[PATH_MAX + 1]; + +static int sysfs_valid_mountpoint(const char *sysfs) +{ + struct statfs st_fs; + + if (statfs(sysfs, &st_fs) < 0) + return -ENOENT; + else if (st_fs.f_type != (long) SYSFS_MAGIC) + return -ENOENT; + + return 0; +} + +const char *sysfs_find_mountpoint(void) +{ + const char * const *ptr; + char type[100]; + FILE *fp; + + if (sysfs_found) + return (const char *) sysfs_mountpoint; + + ptr = sysfs_known_mountpoints; + while (*ptr) { + if (sysfs_valid_mountpoint(*ptr) == 0) { + sysfs_found = 1; + strcpy(sysfs_mountpoint, *ptr); + return sysfs_mountpoint; + } + ptr++; + } + + /* give up and parse /proc/mounts */ + fp = fopen("/proc/mounts", "r"); + if (fp == NULL) + return NULL; + + while (!sysfs_found && + fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n", + sysfs_mountpoint, type) == 2) { + + if (strcmp(type, "sysfs") == 0) + sysfs_found = 1; + } + + fclose(fp); + + return sysfs_found ? sysfs_mountpoint : NULL; +} diff --git a/tools/perf/util/sysfs.h b/tools/perf/util/sysfs.h new file mode 100644 index 0000000..a813b72 --- /dev/null +++ b/tools/perf/util/sysfs.h @@ -0,0 +1,6 @@ +#ifndef __SYSFS_H__ +#define __SYSFS_H__ + +const char *sysfs_find_mountpoint(void); + +#endif /* __DEBUGFS_H__ */ diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c index 3c778a0..065528b 100644 --- a/tools/perf/util/target.c +++ b/tools/perf/util/target.c @@ -13,9 +13,9 @@ #include <string.h> -enum target_errno target__validate(struct target *target) +enum perf_target_errno perf_target__validate(struct perf_target *target) { - enum target_errno ret = TARGET_ERRNO__SUCCESS; + enum perf_target_errno ret = PERF_ERRNO_TARGET__SUCCESS; if (target->pid) target->tid = target->pid; @@ -23,42 +23,42 @@ enum target_errno target__validate(struct target *target) /* CPU and PID are mutually exclusive */ if (target->tid && target->cpu_list) { target->cpu_list = NULL; - if (ret == TARGET_ERRNO__SUCCESS) - ret = TARGET_ERRNO__PID_OVERRIDE_CPU; + if (ret == PERF_ERRNO_TARGET__SUCCESS) + ret = PERF_ERRNO_TARGET__PID_OVERRIDE_CPU; } /* UID and PID are mutually exclusive */ if (target->tid && target->uid_str) { target->uid_str = NULL; - if (ret == TARGET_ERRNO__SUCCESS) - ret = TARGET_ERRNO__PID_OVERRIDE_UID; + if (ret == PERF_ERRNO_TARGET__SUCCESS) + ret = PERF_ERRNO_TARGET__PID_OVERRIDE_UID; } /* UID and CPU are mutually exclusive */ if (target->uid_str && target->cpu_list) { target->cpu_list = NULL; - if (ret == TARGET_ERRNO__SUCCESS) - ret = TARGET_ERRNO__UID_OVERRIDE_CPU; + if (ret == PERF_ERRNO_TARGET__SUCCESS) + ret = PERF_ERRNO_TARGET__UID_OVERRIDE_CPU; } /* PID and SYSTEM are mutually exclusive */ if (target->tid && target->system_wide) { target->system_wide = false; - if (ret == TARGET_ERRNO__SUCCESS) - ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM; + if (ret == PERF_ERRNO_TARGET__SUCCESS) + ret = PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM; } /* UID and SYSTEM are mutually exclusive */ if (target->uid_str && target->system_wide) { target->system_wide = false; - if (ret == TARGET_ERRNO__SUCCESS) - ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM; + if (ret == PERF_ERRNO_TARGET__SUCCESS) + ret = PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM; } return ret; } -enum target_errno target__parse_uid(struct target *target) +enum perf_target_errno perf_target__parse_uid(struct perf_target *target) { struct passwd pwd, *result; char buf[1024]; @@ -66,7 +66,7 @@ enum target_errno target__parse_uid(struct target *target) target->uid = UINT_MAX; if (str == NULL) - return TARGET_ERRNO__SUCCESS; + return PERF_ERRNO_TARGET__SUCCESS; /* Try user name first */ getpwnam_r(str, &pwd, buf, sizeof(buf), &result); @@ -79,22 +79,22 @@ enum target_errno target__parse_uid(struct target *target) int uid = strtol(str, &endptr, 10); if (*endptr != '\0') - return TARGET_ERRNO__INVALID_UID; + return PERF_ERRNO_TARGET__INVALID_UID; getpwuid_r(uid, &pwd, buf, sizeof(buf), &result); if (result == NULL) - return TARGET_ERRNO__USER_NOT_FOUND; + return PERF_ERRNO_TARGET__USER_NOT_FOUND; } target->uid = result->pw_uid; - return TARGET_ERRNO__SUCCESS; + return PERF_ERRNO_TARGET__SUCCESS; } /* - * This must have a same ordering as the enum target_errno. + * This must have a same ordering as the enum perf_target_errno. */ -static const char *target__error_str[] = { +static const char *perf_target__error_str[] = { "PID/TID switch overriding CPU", "PID/TID switch overriding UID", "UID switch overriding CPU", @@ -104,7 +104,7 @@ static const char *target__error_str[] = { "Problems obtaining information for user %s", }; -int target__strerror(struct target *target, int errnum, +int perf_target__strerror(struct perf_target *target, int errnum, char *buf, size_t buflen) { int idx; @@ -124,19 +124,21 @@ int target__strerror(struct target *target, int errnum, return 0; } - if (errnum < __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END) + if (errnum < __PERF_ERRNO_TARGET__START || + errnum >= __PERF_ERRNO_TARGET__END) return -1; - idx = errnum - __TARGET_ERRNO__START; - msg = target__error_str[idx]; + idx = errnum - __PERF_ERRNO_TARGET__START; + msg = perf_target__error_str[idx]; switch (errnum) { - case TARGET_ERRNO__PID_OVERRIDE_CPU ... TARGET_ERRNO__UID_OVERRIDE_SYSTEM: + case PERF_ERRNO_TARGET__PID_OVERRIDE_CPU + ... PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM: snprintf(buf, buflen, "%s", msg); break; - case TARGET_ERRNO__INVALID_UID: - case TARGET_ERRNO__USER_NOT_FOUND: + case PERF_ERRNO_TARGET__INVALID_UID: + case PERF_ERRNO_TARGET__USER_NOT_FOUND: snprintf(buf, buflen, msg, target->uid_str); break; diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h index 2d0c506..a4be857 100644 --- a/tools/perf/util/target.h +++ b/tools/perf/util/target.h @@ -4,7 +4,7 @@ #include <stdbool.h> #include <sys/types.h> -struct target { +struct perf_target { const char *pid; const char *tid; const char *cpu_list; @@ -12,11 +12,10 @@ struct target { uid_t uid; bool system_wide; bool uses_mmap; - bool force_per_cpu; }; -enum target_errno { - TARGET_ERRNO__SUCCESS = 0, +enum perf_target_errno { + PERF_ERRNO_TARGET__SUCCESS = 0, /* * Choose an arbitrary negative big number not to clash with standard @@ -25,40 +24,42 @@ enum target_errno { * * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html */ - __TARGET_ERRNO__START = -10000, + __PERF_ERRNO_TARGET__START = -10000, - /* for target__validate() */ - TARGET_ERRNO__PID_OVERRIDE_CPU = __TARGET_ERRNO__START, - TARGET_ERRNO__PID_OVERRIDE_UID, - TARGET_ERRNO__UID_OVERRIDE_CPU, - TARGET_ERRNO__PID_OVERRIDE_SYSTEM, - TARGET_ERRNO__UID_OVERRIDE_SYSTEM, - /* for target__parse_uid() */ - TARGET_ERRNO__INVALID_UID, - TARGET_ERRNO__USER_NOT_FOUND, + /* for perf_target__validate() */ + PERF_ERRNO_TARGET__PID_OVERRIDE_CPU = __PERF_ERRNO_TARGET__START, + PERF_ERRNO_TARGET__PID_OVERRIDE_UID, + PERF_ERRNO_TARGET__UID_OVERRIDE_CPU, + PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM, + PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM, - __TARGET_ERRNO__END, + /* for perf_target__parse_uid() */ + PERF_ERRNO_TARGET__INVALID_UID, + PERF_ERRNO_TARGET__USER_NOT_FOUND, + + __PERF_ERRNO_TARGET__END, }; -enum target_errno target__validate(struct target *target); -enum target_errno target__parse_uid(struct target *target); +enum perf_target_errno perf_target__validate(struct perf_target *target); +enum perf_target_errno perf_target__parse_uid(struct perf_target *target); -int target__strerror(struct target *target, int errnum, char *buf, size_t buflen); +int perf_target__strerror(struct perf_target *target, int errnum, char *buf, + size_t buflen); -static inline bool target__has_task(struct target *target) +static inline bool perf_target__has_task(struct perf_target *target) { return target->tid || target->pid || target->uid_str; } -static inline bool target__has_cpu(struct target *target) +static inline bool perf_target__has_cpu(struct perf_target *target) { return target->system_wide || target->cpu_list; } -static inline bool target__none(struct target *target) +static inline bool perf_target__none(struct perf_target *target) { - return !target__has_task(target) && !target__has_cpu(target); + return !perf_target__has_task(target) && !perf_target__has_cpu(target); } #endif /* _PERF_TARGET_H */ diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 49eaf1d..e3d4a55 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -6,136 +6,86 @@ #include "thread.h" #include "util.h" #include "debug.h" -#include "comm.h" struct thread *thread__new(pid_t pid, pid_t tid) { - char *comm_str; - struct comm *comm; - struct thread *thread = zalloc(sizeof(*thread)); - - if (thread != NULL) { - map_groups__init(&thread->mg); - thread->pid_ = pid; - thread->tid = tid; - thread->ppid = -1; - INIT_LIST_HEAD(&thread->comm_list); - - comm_str = malloc(32); - if (!comm_str) - goto err_thread; - - snprintf(comm_str, 32, ":%d", tid); - comm = comm__new(comm_str, 0); - free(comm_str); - if (!comm) - goto err_thread; - - list_add(&comm->list, &thread->comm_list); - } - - return thread; - -err_thread: - free(thread); - return NULL; -} - -void thread__delete(struct thread *thread) -{ - struct comm *comm, *tmp; - - map_groups__exit(&thread->mg); - list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) { - list_del(&comm->list); - comm__free(comm); + struct thread *self = zalloc(sizeof(*self)); + + if (self != NULL) { + map_groups__init(&self->mg); + self->pid_ = pid; + self->tid = tid; + self->ppid = -1; + self->comm = malloc(32); + if (self->comm) + snprintf(self->comm, 32, ":%d", self->tid); } - free(thread); + return self; } -struct comm *thread__comm(const struct thread *thread) +void thread__delete(struct thread *self) { - if (list_empty(&thread->comm_list)) - return NULL; - - return list_first_entry(&thread->comm_list, struct comm, list); + map_groups__exit(&self->mg); + free(self->comm); + free(self); } -/* CHECKME: time should always be 0 if event aren't ordered */ -int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) +int thread__set_comm(struct thread *self, const char *comm) { - struct comm *new, *curr = thread__comm(thread); - - /* Override latest entry if it had no specific time coverage */ - if (!curr->start) { - comm__override(curr, str, timestamp); - } else { - new = comm__new(str, timestamp); - if (!new) - return -ENOMEM; - list_add(&new->list, &thread->comm_list); + int err; + + if (self->comm) + free(self->comm); + self->comm = strdup(comm); + err = self->comm == NULL ? -ENOMEM : 0; + if (!err) { + self->comm_set = true; } - - thread->comm_set = true; - - return 0; -} - -const char *thread__comm_str(const struct thread *thread) -{ - const struct comm *comm = thread__comm(thread); - - if (!comm) - return NULL; - - return comm__str(comm); + return err; } -/* CHECKME: it should probably better return the max comm len from its comm list */ -int thread__comm_len(struct thread *thread) +int thread__comm_len(struct thread *self) { - if (!thread->comm_len) { - const char *comm = thread__comm_str(thread); - if (!comm) + if (!self->comm_len) { + if (!self->comm) return 0; - thread->comm_len = strlen(comm); + self->comm_len = strlen(self->comm); } - return thread->comm_len; + return self->comm_len; } size_t thread__fprintf(struct thread *thread, FILE *fp) { - return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) + + return fprintf(fp, "Thread %d %s\n", thread->tid, thread->comm) + map_groups__fprintf(&thread->mg, verbose, fp); } -void thread__insert_map(struct thread *thread, struct map *map) +void thread__insert_map(struct thread *self, struct map *map) { - map_groups__fixup_overlappings(&thread->mg, map, verbose, stderr); - map_groups__insert(&thread->mg, map); + map_groups__fixup_overlappings(&self->mg, map, verbose, stderr); + map_groups__insert(&self->mg, map); } -int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) +int thread__fork(struct thread *self, struct thread *parent) { - int i, err; + int i; if (parent->comm_set) { - const char *comm = thread__comm_str(parent); - if (!comm) + if (self->comm) + free(self->comm); + self->comm = strdup(parent->comm); + if (!self->comm) return -ENOMEM; - err = thread__set_comm(thread, comm, timestamp); - if (!err) - return err; - thread->comm_set = true; + self->comm_set = true; } for (i = 0; i < MAP__NR_TYPES; ++i) - if (map_groups__clone(&thread->mg, &parent->mg, i) < 0) + if (map_groups__clone(&self->mg, &parent->mg, i) < 0) return -ENOMEM; - thread->ppid = parent->tid; + self->ppid = parent->tid; return 0; } diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 897c1b2..4ebbb40 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -2,7 +2,6 @@ #define __PERF_THREAD_H #include <linux/rbtree.h> -#include <linux/list.h> #include <unistd.h> #include <sys/types.h> #include "symbol.h" @@ -19,34 +18,31 @@ struct thread { char shortname[3]; bool comm_set; bool dead; /* if set thread has exited */ - struct list_head comm_list; + char *comm; int comm_len; void *priv; }; struct machine; -struct comm; struct thread *thread__new(pid_t pid, pid_t tid); -void thread__delete(struct thread *thread); +void thread__delete(struct thread *self); static inline void thread__exited(struct thread *thread) { thread->dead = true; } -int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp); -int thread__comm_len(struct thread *thread); -struct comm *thread__comm(const struct thread *thread); -const char *thread__comm_str(const struct thread *thread); -void thread__insert_map(struct thread *thread, struct map *map); -int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); +int thread__set_comm(struct thread *self, const char *comm); +int thread__comm_len(struct thread *self); +void thread__insert_map(struct thread *self, struct map *map); +int thread__fork(struct thread *self, struct thread *parent); size_t thread__fprintf(struct thread *thread, FILE *fp); -static inline struct map *thread__find_map(struct thread *thread, +static inline struct map *thread__find_map(struct thread *self, enum map_type type, u64 addr) { - return thread ? map_groups__find(&thread->mg, type, addr) : NULL; + return self ? map_groups__find(&self->mg, type, addr) : NULL; } void thread__find_addr_map(struct thread *thread, struct machine *machine, diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c index ce793c7..f857b51 100644 --- a/tools/perf/util/top.c +++ b/tools/perf/util/top.c @@ -27,7 +27,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) float ksamples_per_sec; float esamples_percent; struct perf_record_opts *opts = &top->record_opts; - struct target *target = &opts->target; + struct perf_target *target = &opts->target; size_t ret = 0; if (top->samples) { diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h index 88cfeaf..b554ffc 100644 --- a/tools/perf/util/top.h +++ b/tools/perf/util/top.h @@ -24,7 +24,6 @@ struct perf_top { u64 exact_samples; u64 guest_us_samples, guest_kernel_samples; int print_entries, count_filter, delay_secs; - int max_stack; bool hide_kernel_symbols, hide_user_symbols, zero; bool use_tui, use_stdio; bool kptr_restrict_warned; diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 6681f71..e9e1c03 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -120,6 +120,42 @@ raw_field_value(struct event_format *event, const char *name, void *data) return val; } +void *raw_field_ptr(struct event_format *event, const char *name, void *data) +{ + struct format_field *field; + + field = pevent_find_any_field(event, name); + if (!field) + return NULL; + + if (field->flags & FIELD_IS_DYNAMIC) { + int offset; + + offset = *(int *)(data + field->offset); + offset &= 0xffff; + + return data + offset; + } + + return data + field->offset; +} + +int trace_parse_common_type(struct pevent *pevent, void *data) +{ + struct pevent_record record; + + record.data = data; + return pevent_data_type(pevent, &record); +} + +int trace_parse_common_pid(struct pevent *pevent, void *data) +{ + struct pevent_record record; + + record.data = data; + return pevent_data_pid(pevent, &record); +} + unsigned long long read_size(struct event_format *event, void *ptr, int size) { return pevent_read_number(event->pevent, ptr, size); diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 04df631..fafe1a4 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -11,6 +11,8 @@ union perf_event; struct perf_tool; struct thread; +extern struct pevent *perf_pevent; + int bigendian(void); struct pevent *read_trace_init(int file_bigendian, int host_bigendian); @@ -21,19 +23,26 @@ int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size); int parse_event_file(struct pevent *pevent, char *buf, unsigned long size, char *sys); +struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu); + unsigned long long raw_field_value(struct event_format *event, const char *name, void *data); +void *raw_field_ptr(struct event_format *event, const char *name, void *data); void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); ssize_t trace_report(int fd, struct pevent **pevent, bool repipe); +int trace_parse_common_type(struct pevent *pevent, void *data); +int trace_parse_common_pid(struct pevent *pevent, void *data); + struct event_format *trace_find_next_event(struct pevent *pevent, struct event_format *event); unsigned long long read_size(struct event_format *event, void *ptr, int size); unsigned long long eval_flag(const char *flag); +struct pevent_record *trace_read_data(struct pevent *pevent, int cpu); int read_tracing_data(int fd, struct list_head *pattrs); struct tracing_data { diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c index 0efd539..2f891f7 100644 --- a/tools/perf/util/unwind.c +++ b/tools/perf/util/unwind.c @@ -39,15 +39,6 @@ UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, #define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) -extern int -UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, - unw_word_t ip, - unw_word_t segbase, - const char *obj_name, unw_word_t start, - unw_word_t end); - -#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) - #define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ #define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ @@ -254,9 +245,8 @@ static int unwind_spec_ehframe(struct dso *dso, struct machine *machine, return 0; } -static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine, - u64 *table_data, u64 *segbase, - u64 *fde_count) +static int read_unwind_spec(struct dso *dso, struct machine *machine, + u64 *table_data, u64 *segbase, u64 *fde_count) { int ret = -EINVAL, fd; u64 offset; @@ -265,7 +255,6 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine, if (fd < 0) return -EINVAL; - /* Check the .eh_frame section for unwinding info */ offset = elf_section_offset(fd, ".eh_frame_hdr"); close(fd); @@ -274,29 +263,10 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine, table_data, segbase, fde_count); + /* TODO .debug_frame check if eh_frame_hdr fails */ return ret; } -#ifndef NO_LIBUNWIND_DEBUG_FRAME -static int read_unwind_spec_debug_frame(struct dso *dso, - struct machine *machine, u64 *offset) -{ - int fd = dso__data_fd(dso, machine); - - if (fd < 0) - return -EINVAL; - - /* Check the .debug_frame section for unwinding info */ - *offset = elf_section_offset(fd, ".debug_frame"); - close(fd); - - if (*offset) - return 0; - - return -EINVAL; -} -#endif - static struct map *find_map(unw_word_t ip, struct unwind_info *ui) { struct addr_location al; @@ -321,33 +291,20 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, pr_debug("unwind: find_proc_info dso %s\n", map->dso->name); - /* Check the .eh_frame section for unwinding info */ - if (!read_unwind_spec_eh_frame(map->dso, ui->machine, - &table_data, &segbase, &fde_count)) { - memset(&di, 0, sizeof(di)); - di.format = UNW_INFO_FORMAT_REMOTE_TABLE; - di.start_ip = map->start; - di.end_ip = map->end; - di.u.rti.segbase = map->start + segbase; - di.u.rti.table_data = map->start + table_data; - di.u.rti.table_len = fde_count * sizeof(struct table_entry) - / sizeof(unw_word_t); - return dwarf_search_unwind_table(as, ip, &di, pi, - need_unwind_info, arg); - } - -#ifndef NO_LIBUNWIND_DEBUG_FRAME - /* Check the .debug_frame section for unwinding info */ - if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { - memset(&di, 0, sizeof(di)); - dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, - map->start, map->end); - return dwarf_search_unwind_table(as, ip, &di, pi, - need_unwind_info, arg); - } -#endif + if (read_unwind_spec(map->dso, ui->machine, + &table_data, &segbase, &fde_count)) + return -EINVAL; - return -EINVAL; + memset(&di, 0, sizeof(di)); + di.format = UNW_INFO_FORMAT_REMOTE_TABLE; + di.start_ip = map->start; + di.end_ip = map->end; + di.u.rti.segbase = map->start + segbase; + di.u.rti.table_data = map->start + table_data; + di.u.rti.table_len = fde_count * sizeof(struct table_entry) + / sizeof(unw_word_t); + return dwarf_search_unwind_table(as, ip, &di, pi, + need_unwind_info, arg); } static int access_fpreg(unw_addr_space_t __maybe_unused as, @@ -559,7 +516,7 @@ static unw_accessors_t accessors = { }; static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, - void *arg, int max_stack) + void *arg) { unw_addr_space_t addr_space; unw_cursor_t c; @@ -575,7 +532,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, if (ret) display_error(ret); - while (!ret && (unw_step(&c) > 0) && max_stack--) { + while (!ret && (unw_step(&c) > 0)) { unw_word_t ip; unw_get_reg(&c, UNW_REG_IP, &ip); @@ -588,8 +545,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, int unwind__get_entries(unwind_entry_cb_t cb, void *arg, struct machine *machine, struct thread *thread, - u64 sample_uregs, struct perf_sample *data, - int max_stack) + u64 sample_uregs, struct perf_sample *data) { unw_word_t ip; struct unwind_info ui = { @@ -611,5 +567,5 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, if (ret) return -ENOMEM; - return get_entries(&ui, cb, arg, max_stack); + return get_entries(&ui, cb, arg); } diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index d5966f49..cb6bc50 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -13,12 +13,12 @@ struct unwind_entry { typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); -#ifdef HAVE_LIBUNWIND_SUPPORT +#ifdef LIBUNWIND_SUPPORT int unwind__get_entries(unwind_entry_cb_t cb, void *arg, struct machine *machine, struct thread *thread, u64 sample_uregs, - struct perf_sample *data, int max_stack); + struct perf_sample *data); int unwind__arch_reg_id(int regnum); #else static inline int @@ -27,10 +27,9 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, struct machine *machine __maybe_unused, struct thread *thread __maybe_unused, u64 sample_uregs __maybe_unused, - struct perf_sample *data __maybe_unused, - int max_stack __maybe_unused) + struct perf_sample *data __maybe_unused) { return 0; } -#endif /* HAVE_LIBUNWIND_SUPPORT */ +#endif /* LIBUNWIND_SUPPORT */ #endif /* __UNWIND_H */ diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 28a0a89..6d17b18 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -1,7 +1,7 @@ #include "../perf.h" #include "util.h" #include <sys/mman.h> -#ifdef HAVE_BACKTRACE_SUPPORT +#ifdef BACKTRACE_SUPPORT #include <execinfo.h> #endif #include <stdio.h> @@ -55,20 +55,17 @@ int mkdir_p(char *path, mode_t mode) return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; } -static int slow_copyfile(const char *from, const char *to, mode_t mode) +static int slow_copyfile(const char *from, const char *to) { - int err = -1; + int err = 0; char *line = NULL; size_t n; FILE *from_fp = fopen(from, "r"), *to_fp; - mode_t old_umask; if (from_fp == NULL) goto out; - old_umask = umask(mode ^ 0777); to_fp = fopen(to, "w"); - umask(old_umask); if (to_fp == NULL) goto out_fclose_from; @@ -85,7 +82,7 @@ out: return err; } -int copyfile_mode(const char *from, const char *to, mode_t mode) +int copyfile(const char *from, const char *to) { int fromfd, tofd; struct stat st; @@ -96,13 +93,13 @@ int copyfile_mode(const char *from, const char *to, mode_t mode) goto out; if (st.st_size == 0) /* /proc? do it slowly... */ - return slow_copyfile(from, to, mode); + return slow_copyfile(from, to); fromfd = open(from, O_RDONLY); if (fromfd < 0) goto out; - tofd = creat(to, mode); + tofd = creat(to, 0755); if (tofd < 0) goto out_close_from; @@ -124,11 +121,6 @@ out: return err; } -int copyfile(const char *from, const char *to) -{ - return copyfile_mode(from, to, 0755); -} - unsigned long convert_unit(unsigned long value, char *unit) { *unit = ' '; @@ -212,7 +204,7 @@ int hex2u64(const char *ptr, u64 *long_val) } /* Obtain a backtrace and print it to stdout. */ -#ifdef HAVE_BACKTRACE_SUPPORT +#ifdef BACKTRACE_SUPPORT void dump_stack(void) { void *array[16]; @@ -369,47 +361,3 @@ int parse_nsec_time(const char *str, u64 *ptime) *ptime = time_sec * NSEC_PER_SEC + time_nsec; return 0; } - -unsigned long parse_tag_value(const char *str, struct parse_tag *tags) -{ - struct parse_tag *i = tags; - - while (i->tag) { - char *s; - - s = strchr(str, i->tag); - if (s) { - unsigned long int value; - char *endptr; - - value = strtoul(str, &endptr, 10); - if (s != endptr) - break; - - if (value > ULONG_MAX / i->mult) - break; - value *= i->mult; - return value; - } - i++; - } - - return (unsigned long) -1; -} - -int filename__read_int(const char *filename, int *value) -{ - char line[64]; - int fd = open(filename, O_RDONLY), err = -1; - - if (fd < 0) - return -1; - - if (read(fd, line, sizeof(line)) > 0) { - *value = atoi(line); - err = 0; - } - - close(fd); - return err; -} diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index c8f362d..a535359 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -128,8 +128,6 @@ void put_tracing_file(char *file); #endif #endif -#define PERF_GTK_DSO "libperf-gtk.so" - /* General helper functions */ extern void usage(const char *err) NORETURN; extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); @@ -243,7 +241,6 @@ static inline int sane_case(int x, int high) int mkdir_p(char *path, mode_t mode); int copyfile(const char *from, const char *to); -int copyfile_mode(const char *from, const char *to, mode_t mode); s64 perf_atoll(const char *str); char **argv_split(const char *str, int *argcp); @@ -273,13 +270,6 @@ bool is_power_of_2(unsigned long n) return (n != 0 && ((n & (n - 1)) == 0)); } -static inline unsigned next_pow2(unsigned x) -{ - if (!x) - return 1; - return 1ULL << (32 - __builtin_clz(x - 1)); -} - size_t hex_width(u64 v); int hex2u64(const char *ptr, u64 *val); @@ -291,20 +281,4 @@ void dump_stack(void); extern unsigned int page_size; void get_term_dimensions(struct winsize *ws); - -struct parse_tag { - char tag; - int mult; -}; - -unsigned long parse_tag_value(const char *str, struct parse_tag *tags); - -#define SRCLINE_UNKNOWN ((char *) "??:0") - -struct dso; - -char *get_srcline(struct dso *dso, unsigned long addr); -void free_srcline(char *srcline); - -int filename__read_int(const char *filename, int *value); #endif /* GIT_COMPAT_UTIL_H */ |