Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf symbols: Retain bfd reference to lookup source line numbers

Closng and re-opening for every lookup when using libbfd to lookup
source file name and line number is very very slow. Instead keep the
reference on struct dso.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1386055390-13757-5-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
454ff00f d88938eb

+34 -6
+1
tools/perf/util/dso.c
··· 469 469 if (dso->lname_alloc) 470 470 free(dso->long_name); 471 471 dso_cache__free(&dso->cache); 472 + dso__free_a2l(dso); 472 473 free(dso); 473 474 } 474 475
+3
tools/perf/util/dso.h
··· 77 77 struct rb_root symbols[MAP__NR_TYPES]; 78 78 struct rb_root symbol_names[MAP__NR_TYPES]; 79 79 struct rb_root cache; 80 + void *a2l; 80 81 enum dso_kernel_type kernel; 81 82 enum dso_swap_type needs_swap; 82 83 enum dso_binary_type symtab_type; ··· 166 165 return dso->data_type == DSO_BINARY_TYPE__KCORE || 167 166 dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE; 168 167 } 168 + 169 + void dso__free_a2l(struct dso *dso); 169 170 170 171 #endif /* __PERF_DSO */
+30 -6
tools/perf/util/srcline.c
··· 146 146 } 147 147 148 148 static int addr2line(const char *dso_name, unsigned long addr, 149 - char **file, unsigned int *line) 149 + char **file, unsigned int *line, struct dso *dso) 150 150 { 151 151 int ret = 0; 152 - struct a2l_data *a2l; 152 + struct a2l_data *a2l = dso->a2l; 153 153 154 - a2l = addr2line_init(dso_name); 154 + if (!a2l) { 155 + dso->a2l = addr2line_init(dso_name); 156 + a2l = dso->a2l; 157 + } 158 + 155 159 if (a2l == NULL) { 156 160 pr_warning("addr2line_init failed for %s\n", dso_name); 157 161 return 0; 158 162 } 159 163 160 164 a2l->addr = addr; 165 + a2l->found = false; 166 + 161 167 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); 162 168 163 169 if (a2l->found && a2l->filename) { ··· 174 168 ret = 1; 175 169 } 176 170 177 - addr2line_cleanup(a2l); 178 171 return ret; 172 + } 173 + 174 + void dso__free_a2l(struct dso *dso) 175 + { 176 + struct a2l_data *a2l = dso->a2l; 177 + 178 + if (!a2l) 179 + return; 180 + 181 + addr2line_cleanup(a2l); 182 + 183 + dso->a2l = NULL; 179 184 } 180 185 181 186 #else /* HAVE_LIBBFD_SUPPORT */ 182 187 183 188 static int addr2line(const char *dso_name, unsigned long addr, 184 - char **file, unsigned int *line_nr) 189 + char **file, unsigned int *line_nr, 190 + struct dso *dso __maybe_unused) 185 191 { 186 192 FILE *fp; 187 193 char cmd[PATH_MAX]; ··· 237 219 pclose(fp); 238 220 return ret; 239 221 } 222 + 223 + void dso__free_a2l(struct dso *dso __maybe_unused) 224 + { 225 + } 226 + 240 227 #endif /* HAVE_LIBBFD_SUPPORT */ 241 228 242 229 char *get_srcline(struct dso *dso, unsigned long addr) ··· 260 237 if (!strncmp(dso_name, "/tmp/perf-", 10)) 261 238 goto out; 262 239 263 - if (!addr2line(dso_name, addr, &file, &line)) 240 + if (!addr2line(dso_name, addr, &file, &line, dso)) 264 241 goto out; 265 242 266 243 if (asprintf(&srcline, "%s:%u", file, line) < 0) ··· 271 248 272 249 out: 273 250 dso->has_srcline = 0; 251 + dso__free_a2l(dso); 274 252 return SRCLINE_UNKNOWN; 275 253 } 276 254