1 // SPDX-License-Identifier: GPL-2.0 2 #include <inttypes.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include <linux/kernel.h> 8 9 #include "util/dso.h" 10 #include "util/util.h" 11 #include "util/debug.h" 12 #include "util/callchain.h" 13 #include "srcline.h" 14 15 #include "symbol.h" 16 17 bool srcline_full_filename; 18 19 static const char *dso__name(struct dso *dso) 20 { 21 const char *dso_name; 22 23 if (dso->symsrc_filename) 24 dso_name = dso->symsrc_filename; 25 else 26 dso_name = dso->long_name; 27 28 if (dso_name[0] == '[') 29 return NULL; 30 31 if (!strncmp(dso_name, "/tmp/perf-", 10)) 32 return NULL; 33 34 return dso_name; 35 } 36 37 static int inline_list__append(char *filename, char *funcname, int line_nr, 38 struct inline_node *node, struct dso *dso) 39 { 40 struct inline_list *ilist; 41 char *demangled; 42 43 ilist = zalloc(sizeof(*ilist)); 44 if (ilist == NULL) 45 return -1; 46 47 ilist->filename = filename; 48 ilist->line_nr = line_nr; 49 50 if (dso != NULL) { 51 demangled = dso__demangle_sym(dso, 0, funcname); 52 if (demangled == NULL) { 53 ilist->funcname = funcname; 54 } else { 55 ilist->funcname = demangled; 56 free(funcname); 57 } 58 } 59 60 if (callchain_param.order == ORDER_CALLEE) 61 list_add_tail(&ilist->list, &node->val); 62 else 63 list_add(&ilist->list, &node->val); 64 65 return 0; 66 } 67 68 #ifdef HAVE_LIBBFD_SUPPORT 69 70 /* 71 * Implement addr2line using libbfd. 72 */ 73 #define PACKAGE "perf" 74 #include <bfd.h> 75 76 struct a2l_data { 77 const char *input; 78 u64 addr; 79 80 bool found; 81 const char *filename; 82 const char *funcname; 83 unsigned line; 84 85 bfd *abfd; 86 asymbol **syms; 87 }; 88 89 static int bfd_error(const char *string) 90 { 91 const char *errmsg; 92 93 errmsg = bfd_errmsg(bfd_get_error()); 94 fflush(stdout); 95 96 if (string) 97 pr_debug("%s: %s\n", string, errmsg); 98 else 99 pr_debug("%s\n", errmsg); 100 101 return -1; 102 } 103 104 static int slurp_symtab(bfd *abfd, struct a2l_data *a2l) 105 { 106 long storage; 107 long symcount; 108 asymbol **syms; 109 bfd_boolean dynamic = FALSE; 110 111 if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0) 112 return bfd_error(bfd_get_filename(abfd)); 113 114 storage = bfd_get_symtab_upper_bound(abfd); 115 if (storage == 0L) { 116 storage = bfd_get_dynamic_symtab_upper_bound(abfd); 117 dynamic = TRUE; 118 } 119 if (storage < 0L) 120 return bfd_error(bfd_get_filename(abfd)); 121 122 syms = malloc(storage); 123 if (dynamic) 124 symcount = bfd_canonicalize_dynamic_symtab(abfd, syms); 125 else 126 symcount = bfd_canonicalize_symtab(abfd, syms); 127 128 if (symcount < 0) { 129 free(syms); 130 return bfd_error(bfd_get_filename(abfd)); 131 } 132 133 a2l->syms = syms; 134 return 0; 135 } 136 137 static void find_address_in_section(bfd *abfd, asection *section, void *data) 138 { 139 bfd_vma pc, vma; 140 bfd_size_type size; 141 struct a2l_data *a2l = data; 142 143 if (a2l->found) 144 return; 145 146 if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0) 147 return; 148 149 pc = a2l->addr; 150 vma = bfd_get_section_vma(abfd, section); 151 size = bfd_get_section_size(section); 152 153 if (pc < vma || pc >= vma + size) 154 return; 155 156 a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma, 157 &a2l->filename, &a2l->funcname, 158 &a2l->line); 159 160 if (a2l->filename && !strlen(a2l->filename)) 161 a2l->filename = NULL; 162 } 163 164 static struct a2l_data *addr2line_init(const char *path) 165 { 166 bfd *abfd; 167 struct a2l_data *a2l = NULL; 168 169 abfd = bfd_openr(path, NULL); 170 if (abfd == NULL) 171 return NULL; 172 173 if (!bfd_check_format(abfd, bfd_object)) 174 goto out; 175 176 a2l = zalloc(sizeof(*a2l)); 177 if (a2l == NULL) 178 goto out; 179 180 a2l->abfd = abfd; 181 a2l->input = strdup(path); 182 if (a2l->input == NULL) 183 goto out; 184 185 if (slurp_symtab(abfd, a2l)) 186 goto out; 187 188 return a2l; 189 190 out: 191 if (a2l) { 192 zfree((char **)&a2l->input); 193 free(a2l); 194 } 195 bfd_close(abfd); 196 return NULL; 197 } 198 199 static void addr2line_cleanup(struct a2l_data *a2l) 200 { 201 if (a2l->abfd) 202 bfd_close(a2l->abfd); 203 zfree((char **)&a2l->input); 204 zfree(&a2l->syms); 205 free(a2l); 206 } 207 208 #define MAX_INLINE_NEST 1024 209 210 static int inline_list__append_dso_a2l(struct dso *dso, 211 struct inline_node *node) 212 { 213 struct a2l_data *a2l = dso->a2l; 214 char *funcname = a2l->funcname ? strdup(a2l->funcname) : NULL; 215 char *filename = a2l->filename ? strdup(a2l->filename) : NULL; 216 217 return inline_list__append(filename, funcname, a2l->line, node, dso); 218 } 219 220 static int addr2line(const char *dso_name, u64 addr, 221 char **file, unsigned int *line, struct dso *dso, 222 bool unwind_inlines, struct inline_node *node) 223 { 224 int ret = 0; 225 struct a2l_data *a2l = dso->a2l; 226 227 if (!a2l) { 228 dso->a2l = addr2line_init(dso_name); 229 a2l = dso->a2l; 230 } 231 232 if (a2l == NULL) { 233 pr_warning("addr2line_init failed for %s\n", dso_name); 234 return 0; 235 } 236 237 a2l->addr = addr; 238 a2l->found = false; 239 240 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); 241 242 if (!a2l->found) 243 return 0; 244 245 if (unwind_inlines) { 246 int cnt = 0; 247 248 if (node && inline_list__append_dso_a2l(dso, node)) 249 return 0; 250 251 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, 252 &a2l->funcname, &a2l->line) && 253 cnt++ < MAX_INLINE_NEST) { 254 255 if (a2l->filename && !strlen(a2l->filename)) 256 a2l->filename = NULL; 257 258 if (node != NULL) { 259 if (inline_list__append_dso_a2l(dso, node)) 260 return 0; 261 // found at least one inline frame 262 ret = 1; 263 } 264 } 265 } 266 267 if (file) { 268 *file = a2l->filename ? strdup(a2l->filename) : NULL; 269 ret = *file ? 1 : 0; 270 } 271 272 if (line) 273 *line = a2l->line; 274 275 return ret; 276 } 277 278 void dso__free_a2l(struct dso *dso) 279 { 280 struct a2l_data *a2l = dso->a2l; 281 282 if (!a2l) 283 return; 284 285 addr2line_cleanup(a2l); 286 287 dso->a2l = NULL; 288 } 289 290 static struct inline_node *addr2inlines(const char *dso_name, u64 addr, 291 struct dso *dso) 292 { 293 struct inline_node *node; 294 295 node = zalloc(sizeof(*node)); 296 if (node == NULL) { 297 perror("not enough memory for the inline node"); 298 return NULL; 299 } 300 301 INIT_LIST_HEAD(&node->val); 302 node->addr = addr; 303 304 if (!addr2line(dso_name, addr, NULL, NULL, dso, TRUE, node)) 305 goto out_free_inline_node; 306 307 if (list_empty(&node->val)) 308 goto out_free_inline_node; 309 310 return node; 311 312 out_free_inline_node: 313 inline_node__delete(node); 314 return NULL; 315 } 316 317 #else /* HAVE_LIBBFD_SUPPORT */ 318 319 static int filename_split(char *filename, unsigned int *line_nr) 320 { 321 char *sep; 322 323 sep = strchr(filename, '\n'); 324 if (sep) 325 *sep = '\0'; 326 327 if (!strcmp(filename, "??:0")) 328 return 0; 329 330 sep = strchr(filename, ':'); 331 if (sep) { 332 *sep++ = '\0'; 333 *line_nr = strtoul(sep, NULL, 0); 334 return 1; 335 } 336 337 return 0; 338 } 339 340 static int addr2line(const char *dso_name, u64 addr, 341 char **file, unsigned int *line_nr, 342 struct dso *dso __maybe_unused, 343 bool unwind_inlines __maybe_unused, 344 struct inline_node *node __maybe_unused) 345 { 346 FILE *fp; 347 char cmd[PATH_MAX]; 348 char *filename = NULL; 349 size_t len; 350 int ret = 0; 351 352 scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64, 353 dso_name, addr); 354 355 fp = popen(cmd, "r"); 356 if (fp == NULL) { 357 pr_warning("popen failed for %s\n", dso_name); 358 return 0; 359 } 360 361 if (getline(&filename, &len, fp) < 0 || !len) { 362 pr_warning("addr2line has no output for %s\n", dso_name); 363 goto out; 364 } 365 366 ret = filename_split(filename, line_nr); 367 if (ret != 1) { 368 free(filename); 369 goto out; 370 } 371 372 *file = filename; 373 374 out: 375 pclose(fp); 376 return ret; 377 } 378 379 void dso__free_a2l(struct dso *dso __maybe_unused) 380 { 381 } 382 383 static struct inline_node *addr2inlines(const char *dso_name, u64 addr, 384 struct dso *dso __maybe_unused) 385 { 386 FILE *fp; 387 char cmd[PATH_MAX]; 388 struct inline_node *node; 389 char *filename = NULL; 390 size_t len; 391 unsigned int line_nr = 0; 392 393 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64, 394 dso_name, addr); 395 396 fp = popen(cmd, "r"); 397 if (fp == NULL) { 398 pr_err("popen failed for %s\n", dso_name); 399 return NULL; 400 } 401 402 node = zalloc(sizeof(*node)); 403 if (node == NULL) { 404 perror("not enough memory for the inline node"); 405 goto out; 406 } 407 408 INIT_LIST_HEAD(&node->val); 409 node->addr = addr; 410 411 while (getline(&filename, &len, fp) != -1) { 412 if (filename_split(filename, &line_nr) != 1) { 413 free(filename); 414 goto out; 415 } 416 417 if (inline_list__append(filename, NULL, line_nr, node, 418 NULL) != 0) 419 goto out; 420 421 filename = NULL; 422 } 423 424 out: 425 pclose(fp); 426 427 if (list_empty(&node->val)) { 428 inline_node__delete(node); 429 return NULL; 430 } 431 432 return node; 433 } 434 435 #endif /* HAVE_LIBBFD_SUPPORT */ 436 437 /* 438 * Number of addr2line failures (without success) before disabling it for that 439 * dso. 440 */ 441 #define A2L_FAIL_LIMIT 123 442 443 char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 444 bool show_sym, bool show_addr, bool unwind_inlines) 445 { 446 char *file = NULL; 447 unsigned line = 0; 448 char *srcline; 449 const char *dso_name; 450 451 if (!dso->has_srcline) 452 goto out; 453 454 dso_name = dso__name(dso); 455 if (dso_name == NULL) 456 goto out; 457 458 if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines, NULL)) 459 goto out; 460 461 if (asprintf(&srcline, "%s:%u", 462 srcline_full_filename ? file : basename(file), 463 line) < 0) { 464 free(file); 465 goto out; 466 } 467 468 dso->a2l_fails = 0; 469 470 free(file); 471 return srcline; 472 473 out: 474 if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) { 475 dso->has_srcline = 0; 476 dso__free_a2l(dso); 477 } 478 479 if (!show_addr) 480 return (show_sym && sym) ? 481 strndup(sym->name, sym->namelen) : NULL; 482 483 if (sym) { 484 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "", 485 addr - sym->start) < 0) 486 return SRCLINE_UNKNOWN; 487 } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0) 488 return SRCLINE_UNKNOWN; 489 return srcline; 490 } 491 492 void free_srcline(char *srcline) 493 { 494 if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0) 495 free(srcline); 496 } 497 498 char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 499 bool show_sym, bool show_addr) 500 { 501 return __get_srcline(dso, addr, sym, show_sym, show_addr, false); 502 } 503 504 struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr) 505 { 506 const char *dso_name; 507 508 dso_name = dso__name(dso); 509 if (dso_name == NULL) 510 return NULL; 511 512 return addr2inlines(dso_name, addr, dso); 513 } 514 515 void inline_node__delete(struct inline_node *node) 516 { 517 struct inline_list *ilist, *tmp; 518 519 list_for_each_entry_safe(ilist, tmp, &node->val, list) { 520 list_del_init(&ilist->list); 521 zfree(&ilist->filename); 522 zfree(&ilist->funcname); 523 free(ilist); 524 } 525 526 free(node); 527 } 528