1 // SPDX-License-Identifier: GPL-2.0 2 #include <inttypes.h> 3 #include <signal.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <sys/types.h> 8 9 #include <linux/kernel.h> 10 #include <linux/string.h> 11 #include <linux/zalloc.h> 12 13 #include <api/io.h> 14 15 #include "util/dso.h" 16 #include "util/debug.h" 17 #include "util/callchain.h" 18 #include "util/symbol_conf.h" 19 #include "srcline.h" 20 #include "string2.h" 21 #include "symbol.h" 22 #include "subcmd/run-command.h" 23 24 bool srcline_full_filename; 25 26 static const char *dso__name(struct dso *dso) 27 { 28 const char *dso_name; 29 30 if (dso->symsrc_filename) 31 dso_name = dso->symsrc_filename; 32 else 33 dso_name = dso->long_name; 34 35 if (dso_name[0] == '[') 36 return NULL; 37 38 if (!strncmp(dso_name, "/tmp/perf-", 10)) 39 return NULL; 40 41 return dso_name; 42 } 43 44 static int inline_list__append(struct symbol *symbol, char *srcline, 45 struct inline_node *node) 46 { 47 struct inline_list *ilist; 48 49 ilist = zalloc(sizeof(*ilist)); 50 if (ilist == NULL) 51 return -1; 52 53 ilist->symbol = symbol; 54 ilist->srcline = srcline; 55 56 if (callchain_param.order == ORDER_CALLEE) 57 list_add_tail(&ilist->list, &node->val); 58 else 59 list_add(&ilist->list, &node->val); 60 61 return 0; 62 } 63 64 /* basename version that takes a const input string */ 65 static const char *gnu_basename(const char *path) 66 { 67 const char *base = strrchr(path, '/'); 68 69 return base ? base + 1 : path; 70 } 71 72 static char *srcline_from_fileline(const char *file, unsigned int line) 73 { 74 char *srcline; 75 76 if (!file) 77 return NULL; 78 79 if (!srcline_full_filename) 80 file = gnu_basename(file); 81 82 if (asprintf(&srcline, "%s:%u", file, line) < 0) 83 return NULL; 84 85 return srcline; 86 } 87 88 static struct symbol *new_inline_sym(struct dso *dso, 89 struct symbol *base_sym, 90 const char *funcname) 91 { 92 struct symbol *inline_sym; 93 char *demangled = NULL; 94 95 if (!funcname) 96 funcname = "??"; 97 98 if (dso) { 99 demangled = dso__demangle_sym(dso, 0, funcname); 100 if (demangled) 101 funcname = demangled; 102 } 103 104 if (base_sym && strcmp(funcname, base_sym->name) == 0) { 105 /* reuse the real, existing symbol */ 106 inline_sym = base_sym; 107 /* ensure that we don't alias an inlined symbol, which could 108 * lead to double frees in inline_node__delete 109 */ 110 assert(!base_sym->inlined); 111 } else { 112 /* create a fake symbol for the inline frame */ 113 inline_sym = symbol__new(base_sym ? base_sym->start : 0, 114 base_sym ? (base_sym->end - base_sym->start) : 0, 115 base_sym ? base_sym->binding : 0, 116 base_sym ? base_sym->type : 0, 117 funcname); 118 if (inline_sym) 119 inline_sym->inlined = 1; 120 } 121 122 free(demangled); 123 124 return inline_sym; 125 } 126 127 #define MAX_INLINE_NEST 1024 128 129 #ifdef HAVE_LIBBFD_SUPPORT 130 131 /* 132 * Implement addr2line using libbfd. 133 */ 134 #define PACKAGE "perf" 135 #include <bfd.h> 136 137 struct a2l_data { 138 const char *input; 139 u64 addr; 140 141 bool found; 142 const char *filename; 143 const char *funcname; 144 unsigned line; 145 146 bfd *abfd; 147 asymbol **syms; 148 }; 149 150 static int bfd_error(const char *string) 151 { 152 const char *errmsg; 153 154 errmsg = bfd_errmsg(bfd_get_error()); 155 fflush(stdout); 156 157 if (string) 158 pr_debug("%s: %s\n", string, errmsg); 159 else 160 pr_debug("%s\n", errmsg); 161 162 return -1; 163 } 164 165 static int slurp_symtab(bfd *abfd, struct a2l_data *a2l) 166 { 167 long storage; 168 long symcount; 169 asymbol **syms; 170 bfd_boolean dynamic = FALSE; 171 172 if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0) 173 return bfd_error(bfd_get_filename(abfd)); 174 175 storage = bfd_get_symtab_upper_bound(abfd); 176 if (storage == 0L) { 177 storage = bfd_get_dynamic_symtab_upper_bound(abfd); 178 dynamic = TRUE; 179 } 180 if (storage < 0L) 181 return bfd_error(bfd_get_filename(abfd)); 182 183 syms = malloc(storage); 184 if (dynamic) 185 symcount = bfd_canonicalize_dynamic_symtab(abfd, syms); 186 else 187 symcount = bfd_canonicalize_symtab(abfd, syms); 188 189 if (symcount < 0) { 190 free(syms); 191 return bfd_error(bfd_get_filename(abfd)); 192 } 193 194 a2l->syms = syms; 195 return 0; 196 } 197 198 static void find_address_in_section(bfd *abfd, asection *section, void *data) 199 { 200 bfd_vma pc, vma; 201 bfd_size_type size; 202 struct a2l_data *a2l = data; 203 flagword flags; 204 205 if (a2l->found) 206 return; 207 208 #ifdef bfd_get_section_flags 209 flags = bfd_get_section_flags(abfd, section); 210 #else 211 flags = bfd_section_flags(section); 212 #endif 213 if ((flags & SEC_ALLOC) == 0) 214 return; 215 216 pc = a2l->addr; 217 #ifdef bfd_get_section_vma 218 vma = bfd_get_section_vma(abfd, section); 219 #else 220 vma = bfd_section_vma(section); 221 #endif 222 #ifdef bfd_get_section_size 223 size = bfd_get_section_size(section); 224 #else 225 size = bfd_section_size(section); 226 #endif 227 228 if (pc < vma || pc >= vma + size) 229 return; 230 231 a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma, 232 &a2l->filename, &a2l->funcname, 233 &a2l->line); 234 235 if (a2l->filename && !strlen(a2l->filename)) 236 a2l->filename = NULL; 237 } 238 239 static struct a2l_data *addr2line_init(const char *path) 240 { 241 bfd *abfd; 242 struct a2l_data *a2l = NULL; 243 244 abfd = bfd_openr(path, NULL); 245 if (abfd == NULL) 246 return NULL; 247 248 if (!bfd_check_format(abfd, bfd_object)) 249 goto out; 250 251 a2l = zalloc(sizeof(*a2l)); 252 if (a2l == NULL) 253 goto out; 254 255 a2l->abfd = abfd; 256 a2l->input = strdup(path); 257 if (a2l->input == NULL) 258 goto out; 259 260 if (slurp_symtab(abfd, a2l)) 261 goto out; 262 263 return a2l; 264 265 out: 266 if (a2l) { 267 zfree((char **)&a2l->input); 268 free(a2l); 269 } 270 bfd_close(abfd); 271 return NULL; 272 } 273 274 static void addr2line_cleanup(struct a2l_data *a2l) 275 { 276 if (a2l->abfd) 277 bfd_close(a2l->abfd); 278 zfree((char **)&a2l->input); 279 zfree(&a2l->syms); 280 free(a2l); 281 } 282 283 static int inline_list__append_dso_a2l(struct dso *dso, 284 struct inline_node *node, 285 struct symbol *sym) 286 { 287 struct a2l_data *a2l = dso->a2l; 288 struct symbol *inline_sym = new_inline_sym(dso, sym, a2l->funcname); 289 char *srcline = NULL; 290 291 if (a2l->filename) 292 srcline = srcline_from_fileline(a2l->filename, a2l->line); 293 294 return inline_list__append(inline_sym, srcline, node); 295 } 296 297 static int addr2line(const char *dso_name, u64 addr, 298 char **file, unsigned int *line, struct dso *dso, 299 bool unwind_inlines, struct inline_node *node, 300 struct symbol *sym) 301 { 302 int ret = 0; 303 struct a2l_data *a2l = dso->a2l; 304 305 if (!a2l) { 306 dso->a2l = addr2line_init(dso_name); 307 a2l = dso->a2l; 308 } 309 310 if (a2l == NULL) { 311 if (!symbol_conf.disable_add2line_warn) 312 pr_warning("addr2line_init failed for %s\n", dso_name); 313 return 0; 314 } 315 316 a2l->addr = addr; 317 a2l->found = false; 318 319 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); 320 321 if (!a2l->found) 322 return 0; 323 324 if (unwind_inlines) { 325 int cnt = 0; 326 327 if (node && inline_list__append_dso_a2l(dso, node, sym)) 328 return 0; 329 330 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, 331 &a2l->funcname, &a2l->line) && 332 cnt++ < MAX_INLINE_NEST) { 333 334 if (a2l->filename && !strlen(a2l->filename)) 335 a2l->filename = NULL; 336 337 if (node != NULL) { 338 if (inline_list__append_dso_a2l(dso, node, sym)) 339 return 0; 340 // found at least one inline frame 341 ret = 1; 342 } 343 } 344 } 345 346 if (file) { 347 *file = a2l->filename ? strdup(a2l->filename) : NULL; 348 ret = *file ? 1 : 0; 349 } 350 351 if (line) 352 *line = a2l->line; 353 354 return ret; 355 } 356 357 void dso__free_a2l(struct dso *dso) 358 { 359 struct a2l_data *a2l = dso->a2l; 360 361 if (!a2l) 362 return; 363 364 addr2line_cleanup(a2l); 365 366 dso->a2l = NULL; 367 } 368 369 #else /* HAVE_LIBBFD_SUPPORT */ 370 371 static int filename_split(char *filename, unsigned int *line_nr) 372 { 373 char *sep; 374 375 sep = strchr(filename, '\n'); 376 if (sep) 377 *sep = '\0'; 378 379 if (!strcmp(filename, "??:0")) 380 return 0; 381 382 sep = strchr(filename, ':'); 383 if (sep) { 384 *sep++ = '\0'; 385 *line_nr = strtoul(sep, NULL, 0); 386 return 1; 387 } 388 389 return 0; 390 } 391 392 static void addr2line_subprocess_cleanup(struct child_process *a2l) 393 { 394 if (a2l->pid != -1) { 395 kill(a2l->pid, SIGKILL); 396 finish_command(a2l); /* ignore result, we don't care */ 397 a2l->pid = -1; 398 } 399 400 free(a2l); 401 } 402 403 static struct child_process *addr2line_subprocess_init(const char *addr2line_path, 404 const char *binary_path) 405 { 406 const char *argv[] = { 407 addr2line_path ?: "addr2line", 408 "-e", binary_path, 409 "-i", "-f", NULL 410 }; 411 struct child_process *a2l = zalloc(sizeof(*a2l)); 412 int start_command_status = 0; 413 414 if (a2l == NULL) { 415 pr_err("Failed to allocate memory for addr2line"); 416 return NULL; 417 } 418 419 a2l->pid = -1; 420 a2l->in = -1; 421 a2l->out = -1; 422 a2l->no_stderr = 1; 423 424 a2l->argv = argv; 425 start_command_status = start_command(a2l); 426 a2l->argv = NULL; /* it's not used after start_command; avoid dangling pointers */ 427 428 if (start_command_status != 0) { 429 pr_warning("could not start addr2line (%s) for %s: start_command return code %d\n", 430 addr2line_path, binary_path, start_command_status); 431 addr2line_subprocess_cleanup(a2l); 432 return NULL; 433 } 434 435 return a2l; 436 } 437 438 enum a2l_style { 439 BROKEN, 440 GNU_BINUTILS, 441 LLVM, 442 }; 443 444 static enum a2l_style addr2line_configure(struct child_process *a2l) 445 { 446 static bool cached; 447 static enum a2l_style style; 448 449 if (!cached) { 450 char buf[128]; 451 struct io io; 452 int ch; 453 454 if (write(a2l->in, ",\n", 2) != 2) 455 return BROKEN; 456 457 io__init(&io, a2l->out, buf, sizeof(buf)); 458 ch = io__get_char(&io); 459 if (ch == ',') { 460 style = LLVM; 461 cached = true; 462 } else if (ch == '?') { 463 style = GNU_BINUTILS; 464 cached = true; 465 } else { 466 style = BROKEN; 467 } 468 do { 469 ch = io__get_char(&io); 470 } while (ch > 0 && ch != '\n'); 471 if (style == GNU_BINUTILS) { 472 do { 473 ch = io__get_char(&io); 474 } while (ch > 0 && ch != '\n'); 475 } 476 /* Ignore SIGPIPE in the event addr2line exits. */ 477 signal(SIGPIPE, SIG_IGN); 478 } 479 return style; 480 } 481 482 static int read_addr2line_record(struct io *io, 483 enum a2l_style style, 484 char **function, 485 char **filename, 486 unsigned int *line_nr) 487 { 488 /* 489 * Returns: 490 * -1 ==> error 491 * 0 ==> sentinel (or other ill-formed) record read 492 * 1 ==> a genuine record read 493 */ 494 char *line = NULL; 495 size_t line_len = 0; 496 unsigned int dummy_line_nr = 0; 497 int ret = -1; 498 499 if (function != NULL) 500 zfree(function); 501 502 if (filename != NULL) 503 zfree(filename); 504 505 if (line_nr != NULL) 506 *line_nr = 0; 507 508 if (io__getline(io, &line, &line_len) < 0 || !line_len) 509 goto error; 510 511 if (style == LLVM && line_len == 2 && line[0] == ',') { 512 zfree(&line); 513 return 0; 514 } 515 516 if (function != NULL) 517 *function = strdup(strim(line)); 518 519 zfree(&line); 520 line_len = 0; 521 522 if (io__getline(io, &line, &line_len) < 0 || !line_len) 523 goto error; 524 525 if (filename_split(line, line_nr == NULL ? &dummy_line_nr : line_nr) == 0 && 526 style == GNU_BINUTILS) { 527 ret = 0; 528 goto error; 529 } 530 531 if (filename != NULL) 532 *filename = strdup(line); 533 534 zfree(&line); 535 line_len = 0; 536 537 return 1; 538 539 error: 540 free(line); 541 if (function != NULL) 542 zfree(function); 543 if (filename != NULL) 544 zfree(filename); 545 return ret; 546 } 547 548 static int inline_list__append_record(struct dso *dso, 549 struct inline_node *node, 550 struct symbol *sym, 551 const char *function, 552 const char *filename, 553 unsigned int line_nr) 554 { 555 struct symbol *inline_sym = new_inline_sym(dso, sym, function); 556 557 return inline_list__append(inline_sym, srcline_from_fileline(filename, line_nr), node); 558 } 559 560 static int addr2line(const char *dso_name, u64 addr, 561 char **file, unsigned int *line_nr, 562 struct dso *dso, 563 bool unwind_inlines, 564 struct inline_node *node, 565 struct symbol *sym __maybe_unused) 566 { 567 struct child_process *a2l = dso->a2l; 568 char *record_function = NULL; 569 char *record_filename = NULL; 570 unsigned int record_line_nr = 0; 571 int record_status = -1; 572 int ret = 0; 573 size_t inline_count = 0; 574 int len; 575 char buf[128]; 576 ssize_t written; 577 struct io io; 578 enum a2l_style a2l_style; 579 580 if (!a2l) { 581 if (!filename__has_section(dso_name, ".debug_line")) 582 goto out; 583 584 dso->a2l = addr2line_subprocess_init(symbol_conf.addr2line_path, 585 dso_name); 586 a2l = dso->a2l; 587 } 588 589 if (a2l == NULL) { 590 if (!symbol_conf.disable_add2line_warn) 591 pr_warning("%s %s: addr2line_subprocess_init failed\n", __func__, dso_name); 592 goto out; 593 } 594 a2l_style = addr2line_configure(a2l); 595 if (a2l_style == BROKEN) { 596 if (!symbol_conf.disable_add2line_warn) 597 pr_warning("%s: addr2line configuration failed\n", __func__); 598 goto out; 599 } 600 601 /* 602 * Send our request and then *deliberately* send something that can't be interpreted as 603 * a valid address to ask addr2line about (namely, ","). This causes addr2line to first 604 * write out the answer to our request, in an unbounded/unknown number of records, and 605 * then to write out the lines "??" and "??:0", for GNU binutils, or "," for 606 * llvm-addr2line, so that we can detect when it has finished giving us anything 607 * useful. With GNU binutils, we have to be careful about the first record, though, 608 * because it may be genuinely unknown, in which case we'll get two sets of "??"/"??:0" 609 * lines. 610 */ 611 len = snprintf(buf, sizeof(buf), "%016"PRIx64"\n,\n", addr); 612 written = len > 0 ? write(a2l->in, buf, len) : -1; 613 if (written != len) { 614 if (!symbol_conf.disable_add2line_warn) 615 pr_warning("%s %s: could not send request\n", __func__, dso_name); 616 goto out; 617 } 618 io__init(&io, a2l->out, buf, sizeof(buf)); 619 620 switch (read_addr2line_record(&io, a2l_style, 621 &record_function, &record_filename, &record_line_nr)) { 622 case -1: 623 if (!symbol_conf.disable_add2line_warn) 624 pr_warning("%s %s: could not read first record\n", __func__, dso_name); 625 goto out; 626 case 0: 627 /* 628 * The first record was invalid, so return failure, but first read another 629 * record, since we asked a junk question and have to clear the answer out. 630 */ 631 switch (read_addr2line_record(&io, a2l_style, NULL, NULL, NULL)) { 632 case -1: 633 if (!symbol_conf.disable_add2line_warn) 634 pr_warning("%s %s: could not read delimiter record\n", 635 __func__, dso_name); 636 break; 637 case 0: 638 /* As expected. */ 639 break; 640 default: 641 if (!symbol_conf.disable_add2line_warn) 642 pr_warning("%s %s: unexpected record instead of sentinel", 643 __func__, dso_name); 644 break; 645 } 646 goto out; 647 default: 648 break; 649 } 650 651 if (file) { 652 *file = strdup(record_filename); 653 ret = 1; 654 } 655 if (line_nr) 656 *line_nr = record_line_nr; 657 658 if (unwind_inlines) { 659 if (node && inline_list__append_record(dso, node, sym, 660 record_function, 661 record_filename, 662 record_line_nr)) { 663 ret = 0; 664 goto out; 665 } 666 } 667 668 /* We have to read the records even if we don't care about the inline info. */ 669 while ((record_status = read_addr2line_record(&io, 670 a2l_style, 671 &record_function, 672 &record_filename, 673 &record_line_nr)) == 1) { 674 if (unwind_inlines && node && inline_count++ < MAX_INLINE_NEST) { 675 if (inline_list__append_record(dso, node, sym, 676 record_function, 677 record_filename, 678 record_line_nr)) { 679 ret = 0; 680 goto out; 681 } 682 ret = 1; /* found at least one inline frame */ 683 } 684 } 685 686 out: 687 free(record_function); 688 free(record_filename); 689 return ret; 690 } 691 692 void dso__free_a2l(struct dso *dso) 693 { 694 struct child_process *a2l = dso->a2l; 695 696 if (!a2l) 697 return; 698 699 addr2line_subprocess_cleanup(a2l); 700 701 dso->a2l = NULL; 702 } 703 704 #endif /* HAVE_LIBBFD_SUPPORT */ 705 706 static struct inline_node *addr2inlines(const char *dso_name, u64 addr, 707 struct dso *dso, struct symbol *sym) 708 { 709 struct inline_node *node; 710 711 node = zalloc(sizeof(*node)); 712 if (node == NULL) { 713 perror("not enough memory for the inline node"); 714 return NULL; 715 } 716 717 INIT_LIST_HEAD(&node->val); 718 node->addr = addr; 719 720 addr2line(dso_name, addr, NULL, NULL, dso, true, node, sym); 721 return node; 722 } 723 724 /* 725 * Number of addr2line failures (without success) before disabling it for that 726 * dso. 727 */ 728 #define A2L_FAIL_LIMIT 123 729 730 char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 731 bool show_sym, bool show_addr, bool unwind_inlines, 732 u64 ip) 733 { 734 char *file = NULL; 735 unsigned line = 0; 736 char *srcline; 737 const char *dso_name; 738 739 if (!dso->has_srcline) 740 goto out; 741 742 dso_name = dso__name(dso); 743 if (dso_name == NULL) 744 goto out; 745 746 if (!addr2line(dso_name, addr, &file, &line, dso, 747 unwind_inlines, NULL, sym)) 748 goto out; 749 750 srcline = srcline_from_fileline(file, line); 751 free(file); 752 753 if (!srcline) 754 goto out; 755 756 dso->a2l_fails = 0; 757 758 return srcline; 759 760 out: 761 if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) { 762 dso->has_srcline = 0; 763 dso__free_a2l(dso); 764 } 765 766 if (!show_addr) 767 return (show_sym && sym) ? 768 strndup(sym->name, sym->namelen) : SRCLINE_UNKNOWN; 769 770 if (sym) { 771 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "", 772 ip - sym->start) < 0) 773 return SRCLINE_UNKNOWN; 774 } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0) 775 return SRCLINE_UNKNOWN; 776 return srcline; 777 } 778 779 /* Returns filename and fills in line number in line */ 780 char *get_srcline_split(struct dso *dso, u64 addr, unsigned *line) 781 { 782 char *file = NULL; 783 const char *dso_name; 784 785 if (!dso->has_srcline) 786 goto out; 787 788 dso_name = dso__name(dso); 789 if (dso_name == NULL) 790 goto out; 791 792 if (!addr2line(dso_name, addr, &file, line, dso, true, NULL, NULL)) 793 goto out; 794 795 dso->a2l_fails = 0; 796 return file; 797 798 out: 799 if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) { 800 dso->has_srcline = 0; 801 dso__free_a2l(dso); 802 } 803 804 return NULL; 805 } 806 807 void free_srcline(char *srcline) 808 { 809 if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0) 810 free(srcline); 811 } 812 813 char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 814 bool show_sym, bool show_addr, u64 ip) 815 { 816 return __get_srcline(dso, addr, sym, show_sym, show_addr, false, ip); 817 } 818 819 struct srcline_node { 820 u64 addr; 821 char *srcline; 822 struct rb_node rb_node; 823 }; 824 825 void srcline__tree_insert(struct rb_root_cached *tree, u64 addr, char *srcline) 826 { 827 struct rb_node **p = &tree->rb_root.rb_node; 828 struct rb_node *parent = NULL; 829 struct srcline_node *i, *node; 830 bool leftmost = true; 831 832 node = zalloc(sizeof(struct srcline_node)); 833 if (!node) { 834 perror("not enough memory for the srcline node"); 835 return; 836 } 837 838 node->addr = addr; 839 node->srcline = srcline; 840 841 while (*p != NULL) { 842 parent = *p; 843 i = rb_entry(parent, struct srcline_node, rb_node); 844 if (addr < i->addr) 845 p = &(*p)->rb_left; 846 else { 847 p = &(*p)->rb_right; 848 leftmost = false; 849 } 850 } 851 rb_link_node(&node->rb_node, parent, p); 852 rb_insert_color_cached(&node->rb_node, tree, leftmost); 853 } 854 855 char *srcline__tree_find(struct rb_root_cached *tree, u64 addr) 856 { 857 struct rb_node *n = tree->rb_root.rb_node; 858 859 while (n) { 860 struct srcline_node *i = rb_entry(n, struct srcline_node, 861 rb_node); 862 863 if (addr < i->addr) 864 n = n->rb_left; 865 else if (addr > i->addr) 866 n = n->rb_right; 867 else 868 return i->srcline; 869 } 870 871 return NULL; 872 } 873 874 void srcline__tree_delete(struct rb_root_cached *tree) 875 { 876 struct srcline_node *pos; 877 struct rb_node *next = rb_first_cached(tree); 878 879 while (next) { 880 pos = rb_entry(next, struct srcline_node, rb_node); 881 next = rb_next(&pos->rb_node); 882 rb_erase_cached(&pos->rb_node, tree); 883 free_srcline(pos->srcline); 884 zfree(&pos); 885 } 886 } 887 888 struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr, 889 struct symbol *sym) 890 { 891 const char *dso_name; 892 893 dso_name = dso__name(dso); 894 if (dso_name == NULL) 895 return NULL; 896 897 return addr2inlines(dso_name, addr, dso, sym); 898 } 899 900 void inline_node__delete(struct inline_node *node) 901 { 902 struct inline_list *ilist, *tmp; 903 904 list_for_each_entry_safe(ilist, tmp, &node->val, list) { 905 list_del_init(&ilist->list); 906 free_srcline(ilist->srcline); 907 /* only the inlined symbols are owned by the list */ 908 if (ilist->symbol && ilist->symbol->inlined) 909 symbol__delete(ilist->symbol); 910 free(ilist); 911 } 912 913 free(node); 914 } 915 916 void inlines__tree_insert(struct rb_root_cached *tree, 917 struct inline_node *inlines) 918 { 919 struct rb_node **p = &tree->rb_root.rb_node; 920 struct rb_node *parent = NULL; 921 const u64 addr = inlines->addr; 922 struct inline_node *i; 923 bool leftmost = true; 924 925 while (*p != NULL) { 926 parent = *p; 927 i = rb_entry(parent, struct inline_node, rb_node); 928 if (addr < i->addr) 929 p = &(*p)->rb_left; 930 else { 931 p = &(*p)->rb_right; 932 leftmost = false; 933 } 934 } 935 rb_link_node(&inlines->rb_node, parent, p); 936 rb_insert_color_cached(&inlines->rb_node, tree, leftmost); 937 } 938 939 struct inline_node *inlines__tree_find(struct rb_root_cached *tree, u64 addr) 940 { 941 struct rb_node *n = tree->rb_root.rb_node; 942 943 while (n) { 944 struct inline_node *i = rb_entry(n, struct inline_node, 945 rb_node); 946 947 if (addr < i->addr) 948 n = n->rb_left; 949 else if (addr > i->addr) 950 n = n->rb_right; 951 else 952 return i; 953 } 954 955 return NULL; 956 } 957 958 void inlines__tree_delete(struct rb_root_cached *tree) 959 { 960 struct inline_node *pos; 961 struct rb_node *next = rb_first_cached(tree); 962 963 while (next) { 964 pos = rb_entry(next, struct inline_node, rb_node); 965 next = rb_next(&pos->rb_node); 966 rb_erase_cached(&pos->rb_node, tree); 967 inline_node__delete(pos); 968 } 969 } 970