static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym, struct disasm_line *dl, int evidx) { struct sym_hist *symhist; double percent = 0.0; const char *markup; int ret = 0; strcpy(buf, ""); if (dl->offset == (s64) -1) return 0; symhist = annotation__histogram(symbol__annotation(sym), evidx); if (!symbol_conf.event_group && !symhist->addr[dl->offset]) return 0; percent = 100.0 * symhist->addr[dl->offset] / symhist->sum; markup = perf_gtk__get_percent_color(percent); if (markup) ret += scnprintf(buf, size, "%s", markup); ret += scnprintf(buf + ret, size - ret, "%6.2f%%", percent); if (markup) ret += scnprintf(buf + ret, size - ret, "</span>"); return ret; }
static int perf_session__add_hist_entry(struct perf_session *session, struct addr_location *al, struct perf_sample *sample, struct perf_evsel *evsel) { struct symbol *parent = NULL; int err = 0; struct hist_entry *he; if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { err = perf_session__resolve_callchain(session, al->thread, sample->callchain, &parent); if (err) return err; } he = __hists__add_entry(&evsel->hists, al, parent, sample->period); if (he == NULL) return -ENOMEM; if (symbol_conf.use_callchain) { err = callchain_append(he->callchain, &session->callchain_cursor, sample->period); if (err) return err; } /* * Only in the newt browser we are doing integrated annotation, * so we don't allocated the extra space needed because the stdio * code will not use it. */ if (al->sym != NULL && use_browser > 0) { struct annotation *notes = symbol__annotation(he->ms.sym); assert(evsel != NULL); err = -ENOMEM; if (notes->src == NULL && symbol__alloc_hist(he->ms.sym, session->evlist->nr_entries) < 0) goto out; err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); } evsel->hists.stats.total_period += sample->period; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); out: return err; }
static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) { struct perf_evsel *evsel = hists_to_evsel(he->hists); struct symbol *sym; struct annotation *notes; struct map *map; int err = -1; if (!he || !he->ms.sym) return -1; sym = he->ms.sym; map = he->ms.map; /* * We can't annotate with just /proc/kallsyms */ if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && !dso__is_kcore(map->dso)) { pr_err("Can't annotate %s: No vmlinux file was found in the " "path\n", sym->name); sleep(1); return -1; } notes = symbol__annotation(sym); pthread_mutex_lock(¬es->lock); if (!symbol__hists(sym, top->evlist->nr_entries)) { pthread_mutex_unlock(¬es->lock); pr_err("Not enough memory for annotating '%s' symbol!\n", sym->name); sleep(1); return err; } err = symbol__annotate(sym, map, evsel, 0, &top->annotation_opts, NULL); if (err == 0) { top->sym_filter_entry = he; } else { char msg[BUFSIZ]; symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); pr_err("Couldn't annotate %s: %s\n", sym->name, msg); } pthread_mutex_unlock(¬es->lock); return err; }
static void perf_top__record_precise_ip(struct perf_top *top, struct hist_entry *he, struct perf_sample *sample, struct perf_evsel *evsel, u64 ip) { struct annotation *notes; struct symbol *sym = he->ms.sym; int err = 0; if (sym == NULL || (use_browser == 0 && (top->sym_filter_entry == NULL || top->sym_filter_entry->ms.sym != sym))) return; notes = symbol__annotation(sym); if (pthread_mutex_trylock(¬es->lock)) return; err = hist_entry__inc_addr_samples(he, sample, evsel, ip); pthread_mutex_unlock(¬es->lock); if (unlikely(err)) { /* * This function is now called with he->hists->lock held. * Release it before going to sleep. */ pthread_mutex_unlock(&he->hists->lock); if (err == -ERANGE && !he->ms.map->erange_warned) ui__warn_map_erange(he->ms.map, sym, ip); else if (err == -ENOMEM) { pr_err("Not enough memory for annotating '%s' symbol!\n", sym->name); sleep(1); } pthread_mutex_lock(&he->hists->lock); } }
static void perf_top__show_details(struct perf_top *top) { struct hist_entry *he = top->sym_filter_entry; struct perf_evsel *evsel = hists_to_evsel(he->hists); struct annotation *notes; struct symbol *symbol; int more; if (!he) return; symbol = he->ms.sym; notes = symbol__annotation(symbol); pthread_mutex_lock(¬es->lock); symbol__calc_percent(symbol, evsel); if (notes->src == NULL) goto out_unlock; printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name); printf(" Events Pcnt (>=%d%%)\n", top->annotation_opts.min_pcnt); more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel, &top->annotation_opts); if (top->evlist->enabled) { if (top->zero) symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx); else symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx); } if (more != 0) printf("%d lines not displayed, maybe increase display entries [e]\n", more); out_unlock: pthread_mutex_unlock(¬es->lock); }
} static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, struct map *map, struct perf_evsel *evsel, struct hist_browser_timer *hbt __maybe_unused) { struct disasm_line *pos, *n; struct annotation *notes; GType col_types[MAX_ANN_COLS]; GtkCellRenderer *renderer; GtkListStore *store; GtkWidget *view; int i; char s[512]; notes = symbol__annotation(sym); for (i = 0; i < MAX_ANN_COLS; i++) { col_types[i] = G_TYPE_STRING; } store = gtk_list_store_newv(MAX_ANN_COLS, col_types); view = gtk_tree_view_new(); renderer = gtk_cell_renderer_text_new(); for (i = 0; i < MAX_ANN_COLS; i++) { gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, col_names[i], renderer, "markup", i, NULL); }
*/ #include "util.h" #include "build-id.h" #include "color.h" #include "cache.h" #include "symbol.h" #include "debug.h" #include "annotate.h" #include <pthread.h> const char *disassembler_style; int symbol__annotate_init(struct map *map __used, struct symbol *sym) { struct annotation *notes = symbol__annotation(sym); pthread_mutex_init(¬es->lock, NULL); return 0; } int symbol__alloc_hist(struct symbol *sym) { struct annotation *notes = symbol__annotation(sym); size_t sizeof_sym_hist = (sizeof(struct sym_hist) + (sym->end - sym->start) * sizeof(u64)); notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); if (notes->src == NULL) return -1; notes->src->sizeof_sym_hist = sizeof_sym_hist; notes->src->nr_histograms = symbol_conf.nr_events;