1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Parts came from builtin-annotate.c, see those files for further 5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * copyright notes. 6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Released under the GPL v2. (and only v2, not any later version) 8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util.h" 11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "build-id.h" 12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "color.h" 13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "cache.h" 14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "symbol.h" 15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "debug.h" 16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "annotate.h" 17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <pthread.h> 18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint symbol__annotate_init(struct map *map __used, struct symbol *sym) 20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pthread_mutex_init(¬es->lock, NULL); 23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint symbol__alloc_hist(struct symbol *sym, int nevents) 27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t sizeof_sym_hist = (sizeof(struct sym_hist) + 30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (sym->end - sym->start) * sizeof(u64)); 31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist); 33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (notes->src == NULL) 34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng notes->src->sizeof_sym_hist = sizeof_sym_hist; 36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng notes->src->nr_histograms = nevents; 37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng INIT_LIST_HEAD(¬es->src->source); 38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid symbol__annotate_zero_histograms(struct symbol *sym) 42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pthread_mutex_lock(¬es->lock); 46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (notes->src != NULL) 47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(notes->src->histograms, 0, 48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng notes->src->nr_histograms * notes->src->sizeof_sym_hist); 49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pthread_mutex_unlock(¬es->lock); 50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint symbol__inc_addr_samples(struct symbol *sym, struct map *map, 53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int evidx, u64 addr) 54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned offset; 56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes; 57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct sym_hist *h; 58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng notes = symbol__annotation(sym); 60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (notes->src == NULL) 61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (addr >= sym->end) 66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng offset = addr - sym->start; 69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng h = annotation__histogram(notes, evidx); 70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng h->sum++; 71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng h->addr[offset]++; 72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64 74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name, 75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng addr, addr - sym->start, evidx, h->addr[offset]); 76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize) 80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct objdump_line *self = malloc(sizeof(*self) + privsize); 82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (self != NULL) { 84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->offset = offset; 85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng self->line = line; 86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return self; 89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid objdump_line__free(struct objdump_line *self) 92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(self->line); 94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(self); 95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void objdump__add_line(struct list_head *head, struct objdump_line *line) 98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_add_tail(&line->node, head); 100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct objdump_line *objdump__get_next_ip_line(struct list_head *head, 103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct objdump_line *pos) 104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry_continue(pos, head, node) 106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pos->offset >= 0) 107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return pos; 108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return NULL; 110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int objdump_line__print(struct objdump_line *oline, struct symbol *sym, 113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int evidx, u64 len, int min_pcnt, 114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int printed, int max_lines, 115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct objdump_line *queue) 116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng static const char *prev_line; 118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng static const char *prev_color; 119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (oline->offset != -1) { 121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *path = NULL; 122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng unsigned int hits = 0; 123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng double percent = 0.0; 124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *color; 125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct source_line *src_line = notes->src->lines; 127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct sym_hist *h = annotation__histogram(notes, evidx); 128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng s64 offset = oline->offset; 129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct objdump_line *next; 130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng next = objdump__get_next_ip_line(¬es->src->source, oline); 132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (offset < (s64)len && 134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (next == NULL || offset < next->offset)) { 135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (src_line) { 136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (path == NULL) 137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng path = src_line[offset].path; 138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng percent += src_line[offset].percent; 139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else 140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng hits += h->addr[offset]; 141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ++offset; 143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (src_line == NULL && h->sum) 146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng percent = 100.0 * hits / h->sum; 147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (percent < min_pcnt) 149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (max_lines && printed >= max_lines) 152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (queue != NULL) { 155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry_from(queue, ¬es->src->source, node) { 156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (queue == oline) 157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng objdump_line__print(queue, sym, evidx, len, 159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 0, 0, 1, NULL); 160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng color = get_percent_color(percent); 164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Also color the filename and line if needed, with 167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * the same color than the percentage. Don't print it 168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * twice for close colored addr with the same filename:line 169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (path) { 171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!prev_line || strcmp(prev_line, path) 172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng || color != prev_color) { 173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng color_fprintf(stdout, color, " %s", path); 174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng prev_line = path; 175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng prev_color = color; 176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng color_fprintf(stdout, color, " %7.2f", percent); 180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" : "); 181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line); 182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (max_lines && printed >= max_lines) 183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else { 185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (queue) 186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!*oline->line) 189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" :\n"); 190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" : %s\n", oline->line); 192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int symbol__parse_objdump_line(struct symbol *sym, struct map *map, 198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng FILE *file, size_t privsize) 199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct objdump_line *objdump_line; 202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *line = NULL, *tmp, *tmp2, *c; 203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t line_len; 204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng s64 line_ip, offset = -1; 205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (getline(&line, &line_len, file) < 0) 207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!line) 210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (line_len != 0 && isspace(line[line_len - 1])) 213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng line[--line_len] = '\0'; 214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng c = strchr(line, '\n'); 216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (c) 217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *c = 0; 218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng line_ip = -1; 220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Strip leading spaces: 223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp = line; 225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*tmp) { 226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*tmp != ' ') 227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tmp++; 229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*tmp) { 232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Parse hexa addresses followed by ':' 234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng line_ip = strtoull(tmp, &tmp2, 16); 236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0') 237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng line_ip = -1; 238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (line_ip != -1) { 241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 start = map__rip_2objdump(map, sym->start), 242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng end = map__rip_2objdump(map, sym->end); 243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng offset = line_ip - start; 245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (offset < 0 || (u64)line_ip > end) 246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng offset = -1; 247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng objdump_line = objdump_line__new(offset, line, privsize); 250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (objdump_line == NULL) { 251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(line); 252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng objdump__add_line(¬es->src->source, objdump_line); 255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 2598a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng/* ANDROID_CHANGE_BEGIN */ 2608a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng#if 0 261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) 2628a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng#else 2638a1715044713722b9fa01419a2148a4a2a67aae5Ben Chengint symbol__annotate(struct symbol *sym, struct map *map, size_t privsize, 2648a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng bool print_lines) 2658a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng#endif 2668a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng/* ANDROID_CHANGE_END */ 267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dso *dso = map->dso; 269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *filename = dso__build_id_filename(dso, NULL, 0); 270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng bool free_filename = true; 271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char command[PATH_MAX * 2]; 272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng FILE *file; 273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int err = 0; 274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char symfs_filename[PATH_MAX]; 275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (filename) { 277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_conf.symfs, filename); 279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (filename == NULL) { 282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dso->has_build_id) { 283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Can't annotate %s: not enough memory\n", 284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sym->name); 285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOMEM; 286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto fallback; 288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || 289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strstr(command, "[kernel.kallsyms]") || 290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng access(symfs_filename, R_OK)) { 291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(filename); 292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengfallback: 293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * If we don't have build-ids or the build-id file isn't in the 295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * cache, or is just a kallsyms file, well, lets hope that this 296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * DSO is the same as when 'perf record' ran. 297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng filename = dso->long_name; 299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_conf.symfs, filename); 301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free_filename = false; 302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dso->symtab_type == SYMTAB__KALLSYMS) { 305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char bf[BUILD_ID_SIZE * 2 + 16] = " with build id "; 306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *build_id_msg = NULL; 307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dso->annotate_warned) 309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_free_filename; 310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dso->has_build_id) { 312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng build_id__sprintf(dso->build_id, 313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sizeof(dso->build_id), bf + 15); 314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng build_id_msg = bf; 315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = -ENOENT; 317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso->annotate_warned = 1; 318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Can't annotate %s: No vmlinux file%s was found in the " 319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "path.\nPlease use 'perf buildid-cache -av vmlinux' or " 320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "--vmlinux vmlinux.\n", 321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sym->name, build_id_msg ?: ""); 322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_free_filename; 323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, 326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng filename, sym->name, map->unmap_ip(map, sym->start), 327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map->unmap_ip(map, sym->end)); 328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("annotating [%p] %30s : [%p] %30s\n", 330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso, dso->long_name, sym, sym->name); 331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 3328a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng /* ANDROID_CHANGE_BEGIN */ 333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#if 0 334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(command, sizeof(command), 335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "objdump --start-address=0x%016" PRIx64 336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand", 337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__rip_2objdump(map, sym->start), 338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__rip_2objdump(map, sym->end), 339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symfs_filename, filename); 340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#else 341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(command, sizeof(command), 342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "arm-eabi-objdump --start-address=0x%016" PRIx64 3438a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng " --stop-address=0x%016" PRIx64 " -d%c -C %s|grep -v %s|expand", 344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__rip_2objdump(map, sym->start), 345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map__rip_2objdump(map, sym->end), 3468a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng print_lines ? 'S' : ' ', 347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symfs_filename, filename); 348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif 3498a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng /* ANDROID_CHANGE_END */ 350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Executing: %s\n", command); 352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng file = popen(command, "r"); 354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!file) 355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_free_filename; 356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 357e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (!feof(file)) 358e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) 359e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 360e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 361e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pclose(file); 362e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_free_filename: 363e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (free_filename) 364e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(filename); 365e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return err; 366e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 367e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 368e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void insert_source_line(struct rb_root *root, struct source_line *src_line) 369e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 370e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct source_line *iter; 371e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node **p = &root->rb_node; 372e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *parent = NULL; 373e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 374e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*p != NULL) { 375e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng parent = *p; 376e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng iter = rb_entry(parent, struct source_line, node); 377e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 378e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (src_line->percent > iter->percent) 379e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_left; 380e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 381e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng p = &(*p)->rb_right; 382e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 383e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 384e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_link_node(&src_line->node, parent, p); 385e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng rb_insert_color(&src_line->node, root); 386e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 387e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 388e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void symbol__free_source_line(struct symbol *sym, int len) 389e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 390e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 391e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct source_line *src_line = notes->src->lines; 392e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i; 393e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 394e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < len; i++) 395e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(src_line[i].path); 396e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 397e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(src_line); 398e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng notes->src->lines = NULL; 399e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 400e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 401e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Get the filename:line for the colored entries */ 402e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int symbol__get_source_line(struct symbol *sym, struct map *map, 403e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int evidx, struct rb_root *root, int len, 404e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *filename) 405e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 406e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 start; 407e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int i; 408e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char cmd[PATH_MAX * 2]; 409e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct source_line *src_line; 410e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 411e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct sym_hist *h = annotation__histogram(notes, evidx); 412e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 413e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!h->sum) 414e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 415e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 416e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng src_line = notes->src->lines = calloc(len, sizeof(struct source_line)); 417e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!notes->src->lines) 418e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 419e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 4208a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng /* ANDORID_CHANGE_BEGIN */ 4218a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng#if 0 422e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng start = map->unmap_ip(map, sym->start); 4238a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng#else 4248a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng /* Use relative start address */ 4258a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng start = sym->start; 4268a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng#endif 4278a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng /* ANDORID_CHANGE_END */ 428e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 429e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (i = 0; i < len; i++) { 430e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *path = NULL; 431e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t line_len; 432e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 offset; 433e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng FILE *fp; 434e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 435e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng src_line[i].percent = 100.0 * h->addr[i] / h->sum; 436e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (src_line[i].percent <= 0.5) 437e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 438e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 439e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng offset = start + i; 4408a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng sprintf(cmd, "arm-eabi-addr2line -e %s%s %016" PRIx64, symbol_conf.symfs, 4418a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng filename, offset); 442e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fp = popen(cmd, "r"); 443e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!fp) 444e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 445e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 446e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (getline(&path, &line_len, fp) < 0 || !line_len) 447e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto next; 448e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 449e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng src_line[i].path = malloc(sizeof(char) * line_len + 1); 450e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!src_line[i].path) 451e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto next; 452e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 453e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strcpy(src_line[i].path, path); 454e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng insert_source_line(root, &src_line[i]); 455e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 456e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng next: 457e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pclose(fp); 458e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 459e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 460e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 461e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 462e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 463e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void print_summary(struct rb_root *root, const char *filename) 464e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 465e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct source_line *src_line; 466e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *node; 467e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 468e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("\nSorted summary for file %s\n", filename); 469e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("----------------------------------------------\n\n"); 470e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 471e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (RB_EMPTY_ROOT(root)) { 472e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" Nothing higher than %1.1f%%\n", MIN_GREEN); 473e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 474e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 475e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 476e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node = rb_first(root); 477e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (node) { 478e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng double percent; 479e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *color; 480e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *path; 481e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 482e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng src_line = rb_entry(node, struct source_line, node); 483e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng percent = src_line->percent; 484e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng color = get_percent_color(percent); 485e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng path = src_line->path; 486e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 487e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng color_fprintf(stdout, color, " %7.2f %s", percent, path); 488e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng node = rb_next(node); 489e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 490e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 491e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 492e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void symbol__annotate_hits(struct symbol *sym, int evidx) 493e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 494e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 495e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct sym_hist *h = annotation__histogram(notes, evidx); 496e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 len = sym->end - sym->start, offset; 497e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 498e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (offset = 0; offset < len; ++offset) 499e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (h->addr[offset] != 0) 500e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2, 501e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sym->start + offset, h->addr[offset]); 502e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); 503e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 504e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 505e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, 506e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng bool full_paths, int min_pcnt, int max_lines, 507e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int context) 508e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 509e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dso *dso = map->dso; 510e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *filename = dso->long_name, *d_filename; 511e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 512e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct objdump_line *pos, *queue = NULL; 513e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int printed = 2, queue_len = 0; 514e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int more = 0; 515e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 len; 516e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 517e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (full_paths) 518e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng d_filename = filename; 519e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 520e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng d_filename = basename(filename); 521e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 522e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len = sym->end - sym->start; 523e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 524e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf(" Percent | Source code & Disassembly of %s\n", d_filename); 525e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printf("------------------------------------------------\n"); 526e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 527e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (verbose) 528e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol__annotate_hits(sym, evidx); 529e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 530e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry(pos, ¬es->src->source, node) { 531e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (context && queue == NULL) { 532e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng queue = pos; 533e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng queue_len = 0; 534e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 535e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 536e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng switch (objdump_line__print(pos, sym, evidx, len, min_pcnt, 537e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed, max_lines, queue)) { 538e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case 0: 539e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ++printed; 540e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (context) { 541e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng printed += queue_len; 542e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng queue = NULL; 543e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng queue_len = 0; 544e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 545e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 546e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case 1: 547e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* filtered by max_lines */ 548e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ++more; 549e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 550e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case -1: 551e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng default: 552e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 553e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Filtered by min_pcnt or non IP lines when 554e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * context != 0 555e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 556e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!context) 557e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 558e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (queue_len == context) 559e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng queue = list_entry(queue->node.next, typeof(*queue), node); 560e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 561e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ++queue_len; 562e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 563e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 564e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 565e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 566e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return more; 567e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 568e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 569e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid symbol__annotate_zero_histogram(struct symbol *sym, int evidx) 570e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 571e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 572e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct sym_hist *h = annotation__histogram(notes, evidx); 573e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 574e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(h, 0, notes->src->sizeof_sym_hist); 575e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 576e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 577e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid symbol__annotate_decay_histogram(struct symbol *sym, int evidx) 578e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 579e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct annotation *notes = symbol__annotation(sym); 580e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct sym_hist *h = annotation__histogram(notes, evidx); 581e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct objdump_line *pos; 582e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int len = sym->end - sym->start; 583e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 584e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng h->sum = 0; 585e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 586e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry(pos, ¬es->src->source, node) { 587e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pos->offset != -1 && pos->offset < len) { 588e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8; 589e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng h->sum += h->addr[pos->offset]; 590e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 591e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 592e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 593e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 594e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid objdump_line_list__purge(struct list_head *head) 595e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 596e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct objdump_line *pos, *n; 597e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 598e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_for_each_entry_safe(pos, n, head, node) { 599e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng list_del(&pos->node); 600e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng objdump_line__free(pos); 601e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 602e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 603e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 604e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, 605e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng bool print_lines, bool full_paths, int min_pcnt, 606e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int max_lines) 607e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 608e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dso *dso = map->dso; 609e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *filename = dso->long_name; 610e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_root source_line = RB_ROOT; 611e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 len; 612e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 6138a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng /* ANDROID_CHANGE_BEGIN */ 6148a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng#if 0 615e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (symbol__annotate(sym, map, 0) < 0) 616e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 6178a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng#else 6188a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng if (symbol__annotate(sym, map, 0, print_lines) < 0) 6198a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng return -1; 6208a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng#endif 6218a1715044713722b9fa01419a2148a4a2a67aae5Ben Cheng /* ANDROID_CHANGE_END */ 622e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 623e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len = sym->end - sym->start; 624e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 625e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (print_lines) { 626e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol__get_source_line(sym, map, evidx, &source_line, 627e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng len, filename); 628e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng print_summary(&source_line, filename); 629e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 630e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 631e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol__annotate_printf(sym, map, evidx, full_paths, 632e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng min_pcnt, max_lines, 0); 633e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (print_lines) 634e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol__free_source_line(sym, len); 635e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 636e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng objdump_line_list__purge(&symbol__annotation(sym)->src->source); 637e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 638e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 639e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 640