symbol.c (b30d7a77c53ec04a6d94683d7680ec406b7f3ac8) | symbol.c (78a175c4623f66722709494295a0f6754b46f858) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2#include <dirent.h> 3#include <errno.h> 4#include <stdlib.h> 5#include <stdio.h> 6#include <string.h> 7#include <linux/capability.h> 8#include <linux/kernel.h> --- 426 unchanged lines hidden (view full) --- 435 struct rb_node *n = rb_next(&sym->rb_node); 436 437 if (n) 438 return rb_entry(n, struct symbol, rb_node); 439 440 return NULL; 441} 442 | 1// SPDX-License-Identifier: GPL-2.0 2#include <dirent.h> 3#include <errno.h> 4#include <stdlib.h> 5#include <stdio.h> 6#include <string.h> 7#include <linux/capability.h> 8#include <linux/kernel.h> --- 426 unchanged lines hidden (view full) --- 435 struct rb_node *n = rb_next(&sym->rb_node); 436 437 if (n) 438 return rb_entry(n, struct symbol, rb_node); 439 440 return NULL; 441} 442 |
443static void symbols__insert_by_name(struct rb_root_cached *symbols, struct symbol *sym) | 443static int symbols__sort_name_cmp(const void *vlhs, const void *vrhs) |
444{ | 444{ |
445 struct rb_node **p = &symbols->rb_root.rb_node; 446 struct rb_node *parent = NULL; 447 struct symbol_name_rb_node *symn, *s; 448 bool leftmost = true; | 445 const struct symbol *lhs = *((const struct symbol **)vlhs); 446 const struct symbol *rhs = *((const struct symbol **)vrhs); |
449 | 447 |
450 symn = container_of(sym, struct symbol_name_rb_node, sym); 451 452 while (*p != NULL) { 453 parent = *p; 454 s = rb_entry(parent, struct symbol_name_rb_node, rb_node); 455 if (strcmp(sym->name, s->sym.name) < 0) 456 p = &(*p)->rb_left; 457 else { 458 p = &(*p)->rb_right; 459 leftmost = false; 460 } 461 } 462 rb_link_node(&symn->rb_node, parent, p); 463 rb_insert_color_cached(&symn->rb_node, symbols, leftmost); | 448 return strcmp(lhs->name, rhs->name); |
464} 465 | 449} 450 |
466static void symbols__sort_by_name(struct rb_root_cached *symbols, 467 struct rb_root_cached *source) | 451static struct symbol **symbols__sort_by_name(struct rb_root_cached *source, size_t *len) |
468{ 469 struct rb_node *nd; | 452{ 453 struct rb_node *nd; |
454 struct symbol **result; 455 size_t i = 0, size = 0; |
|
470 | 456 |
457 for (nd = rb_first_cached(source); nd; nd = rb_next(nd)) 458 size++; 459 460 result = malloc(sizeof(*result) * size); 461 if (!result) 462 return NULL; 463 |
|
471 for (nd = rb_first_cached(source); nd; nd = rb_next(nd)) { 472 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); | 464 for (nd = rb_first_cached(source); nd; nd = rb_next(nd)) { 465 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); |
473 symbols__insert_by_name(symbols, pos); | 466 467 result[i++] = pos; |
474 } | 468 } |
469 qsort(result, size, sizeof(*result), symbols__sort_name_cmp); 470 *len = size; 471 return result; |
|
475} 476 477int symbol__match_symbol_name(const char *name, const char *str, 478 enum symbol_tag_include includes) 479{ 480 const char *versioning; 481 482 if (includes == SYMBOL_TAG_INCLUDE__DEFAULT_ONLY && 483 (versioning = strstr(name, "@@"))) { 484 int len = strlen(str); 485 486 if (len < versioning - name) 487 len = versioning - name; 488 489 return arch__compare_symbol_names_n(name, str, len); 490 } else 491 return arch__compare_symbol_names(name, str); 492} 493 | 472} 473 474int symbol__match_symbol_name(const char *name, const char *str, 475 enum symbol_tag_include includes) 476{ 477 const char *versioning; 478 479 if (includes == SYMBOL_TAG_INCLUDE__DEFAULT_ONLY && 480 (versioning = strstr(name, "@@"))) { 481 int len = strlen(str); 482 483 if (len < versioning - name) 484 len = versioning - name; 485 486 return arch__compare_symbol_names_n(name, str, len); 487 } else 488 return arch__compare_symbol_names(name, str); 489} 490 |
494static struct symbol *symbols__find_by_name(struct rb_root_cached *symbols, | 491static struct symbol *symbols__find_by_name(struct symbol *symbols[], 492 size_t symbols_len, |
495 const char *name, | 493 const char *name, |
496 enum symbol_tag_include includes) | 494 enum symbol_tag_include includes, 495 size_t *found_idx) |
497{ | 496{ |
498 struct rb_node *n; 499 struct symbol_name_rb_node *s = NULL; | 497 size_t i, lower = 0, upper = symbols_len; 498 struct symbol *s = NULL; |
500 | 499 |
501 if (symbols == NULL) | 500 if (found_idx) 501 *found_idx = SIZE_MAX; 502 503 if (!symbols_len) |
502 return NULL; 503 | 504 return NULL; 505 |
504 n = symbols->rb_root.rb_node; 505 506 while (n) { | 506 while (lower < upper) { |
507 int cmp; 508 | 507 int cmp; 508 |
509 s = rb_entry(n, struct symbol_name_rb_node, rb_node); 510 cmp = symbol__match_symbol_name(s->sym.name, name, includes); | 509 i = (lower + upper) / 2; 510 cmp = symbol__match_symbol_name(symbols[i]->name, name, includes); |
511 512 if (cmp > 0) | 511 512 if (cmp > 0) |
513 n = n->rb_left; | 513 upper = i; |
514 else if (cmp < 0) | 514 else if (cmp < 0) |
515 n = n->rb_right; 516 else | 515 lower = i + 1; 516 else { 517 if (found_idx) 518 *found_idx = i; 519 s = symbols[i]; |
517 break; | 520 break; |
521 } |
|
518 } | 522 } |
519 520 if (n == NULL) 521 return NULL; 522 523 if (includes != SYMBOL_TAG_INCLUDE__DEFAULT_ONLY) | 523 if (s && includes != SYMBOL_TAG_INCLUDE__DEFAULT_ONLY) { |
524 /* return first symbol that has same name (if any) */ | 524 /* return first symbol that has same name (if any) */ |
525 for (n = rb_prev(n); n; n = rb_prev(n)) { 526 struct symbol_name_rb_node *tmp; | 525 for (; i > 0; i--) { 526 struct symbol *tmp = symbols[i - 1]; |
527 | 527 |
528 tmp = rb_entry(n, struct symbol_name_rb_node, rb_node); 529 if (arch__compare_symbol_names(tmp->sym.name, s->sym.name)) | 528 if (!arch__compare_symbol_names(tmp->name, s->name)) { 529 if (found_idx) 530 *found_idx = i - 1; 531 s = tmp; 532 } else |
530 break; | 533 break; |
531 532 s = tmp; | |
533 } | 534 } |
534 535 return &s->sym; | 535 } 536 assert(!found_idx || !s || s == symbols[*found_idx]); 537 return s; |
536} 537 538void dso__reset_find_symbol_cache(struct dso *dso) 539{ 540 dso->last_find_result.addr = 0; 541 dso->last_find_result.symbol = NULL; 542} 543 --- 41 unchanged lines hidden (view full) --- 585 return symbols__last(&dso->symbols); 586} 587 588struct symbol *dso__next_symbol(struct symbol *sym) 589{ 590 return symbols__next(sym); 591} 592 | 538} 539 540void dso__reset_find_symbol_cache(struct dso *dso) 541{ 542 dso->last_find_result.addr = 0; 543 dso->last_find_result.symbol = NULL; 544} 545 --- 41 unchanged lines hidden (view full) --- 587 return symbols__last(&dso->symbols); 588} 589 590struct symbol *dso__next_symbol(struct symbol *sym) 591{ 592 return symbols__next(sym); 593} 594 |
593struct symbol *symbol__next_by_name(struct symbol *sym) | 595struct symbol *dso__next_symbol_by_name(struct dso *dso, size_t *idx) |
594{ | 596{ |
595 struct symbol_name_rb_node *s = container_of(sym, struct symbol_name_rb_node, sym); 596 struct rb_node *n = rb_next(&s->rb_node); | 597 if (*idx + 1 >= dso->symbol_names_len) 598 return NULL; |
597 | 599 |
598 return n ? &rb_entry(n, struct symbol_name_rb_node, rb_node)->sym : NULL; | 600 ++*idx; 601 return dso->symbol_names[*idx]; |
599} 600 601 /* 602 * Returns first symbol that matched with @name. 603 */ | 602} 603 604 /* 605 * Returns first symbol that matched with @name. 606 */ |
604struct symbol *dso__find_symbol_by_name(struct dso *dso, const char *name) | 607struct symbol *dso__find_symbol_by_name(struct dso *dso, const char *name, size_t *idx) |
605{ | 608{ |
606 struct symbol *s = symbols__find_by_name(&dso->symbol_names, name, 607 SYMBOL_TAG_INCLUDE__NONE); | 609 struct symbol *s = symbols__find_by_name(dso->symbol_names, dso->symbol_names_len, 610 name, SYMBOL_TAG_INCLUDE__NONE, idx); |
608 if (!s) | 611 if (!s) |
609 s = symbols__find_by_name(&dso->symbol_names, name, 610 SYMBOL_TAG_INCLUDE__DEFAULT_ONLY); | 612 s = symbols__find_by_name(dso->symbol_names, dso->symbol_names_len, 613 name, SYMBOL_TAG_INCLUDE__DEFAULT_ONLY, idx); |
611 return s; 612} 613 614void dso__sort_by_name(struct dso *dso) 615{ | 614 return s; 615} 616 617void dso__sort_by_name(struct dso *dso) 618{ |
616 dso__set_sorted_by_name(dso); 617 return symbols__sort_by_name(&dso->symbol_names, &dso->symbols); | 619 mutex_lock(&dso->lock); 620 if (!dso__sorted_by_name(dso)) { 621 size_t len; 622 623 dso->symbol_names = symbols__sort_by_name(&dso->symbols, &len); 624 if (dso->symbol_names) { 625 dso->symbol_names_len = len; 626 dso__set_sorted_by_name(dso); 627 } 628 } 629 mutex_unlock(&dso->lock); |
618} 619 620/* 621 * While we find nice hex chars, build a long_val. 622 * Return number of chars processed. 623 */ 624static int hex2u64(const char *ptr, u64 *long_val) 625{ --- 2025 unchanged lines hidden (view full) --- 2651 2652 if (symbol_conf.initialized) 2653 return 0; 2654 2655 symbol_conf.priv_size = PERF_ALIGN(symbol_conf.priv_size, sizeof(u64)); 2656 2657 symbol__elf_init(); 2658 | 630} 631 632/* 633 * While we find nice hex chars, build a long_val. 634 * Return number of chars processed. 635 */ 636static int hex2u64(const char *ptr, u64 *long_val) 637{ --- 2025 unchanged lines hidden (view full) --- 2663 2664 if (symbol_conf.initialized) 2665 return 0; 2666 2667 symbol_conf.priv_size = PERF_ALIGN(symbol_conf.priv_size, sizeof(u64)); 2668 2669 symbol__elf_init(); 2670 |
2659 if (symbol_conf.sort_by_name) 2660 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 2661 sizeof(struct symbol)); 2662 | |
2663 if (symbol_conf.try_vmlinux_path && vmlinux_path__init(env) < 0) 2664 return -1; 2665 2666 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { 2667 pr_err("'.' is the only non valid --field-separator argument\n"); 2668 return -1; 2669 } 2670 --- 142 unchanged lines hidden --- | 2671 if (symbol_conf.try_vmlinux_path && vmlinux_path__init(env) < 0) 2672 return -1; 2673 2674 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { 2675 pr_err("'.' is the only non valid --field-separator argument\n"); 2676 return -1; 2677 } 2678 --- 142 unchanged lines hidden --- |