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