probe-finder.c (ac94be498f84f7327533b62faca4c3da64434904) | probe-finder.c (1ae5d88a4eefacd4a3643170c20cf6403a24d254) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * probe-finder.c : C expression to kprobe event converter 4 * 5 * Written by Masami Hiramatsu <mhiramat@redhat.com> 6 */ 7 8#include <inttypes.h> --- 590 unchanged lines hidden (view full) --- 599} 600 601/* Convert subprogram DIE to trace point */ 602static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, 603 Dwarf_Addr paddr, bool retprobe, 604 const char *function, 605 struct probe_trace_point *tp) 606{ | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * probe-finder.c : C expression to kprobe event converter 4 * 5 * Written by Masami Hiramatsu <mhiramat@redhat.com> 6 */ 7 8#include <inttypes.h> --- 590 unchanged lines hidden (view full) --- 599} 600 601/* Convert subprogram DIE to trace point */ 602static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, 603 Dwarf_Addr paddr, bool retprobe, 604 const char *function, 605 struct probe_trace_point *tp) 606{ |
607 Dwarf_Addr eaddr, highaddr; | 607 Dwarf_Addr eaddr; |
608 GElf_Sym sym; 609 const char *symbol; 610 611 /* Verify the address is correct */ | 608 GElf_Sym sym; 609 const char *symbol; 610 611 /* Verify the address is correct */ |
612 if (dwarf_entrypc(sp_die, &eaddr) != 0) { 613 pr_warning("Failed to get entry address of %s\n", | 612 if (!dwarf_haspc(sp_die, paddr)) { 613 pr_warning("Specified offset is out of %s\n", |
614 dwarf_diename(sp_die)); | 614 dwarf_diename(sp_die)); |
615 return -ENOENT; 616 } 617 if (dwarf_highpc(sp_die, &highaddr) != 0) { 618 pr_warning("Failed to get end address of %s\n", 619 dwarf_diename(sp_die)); 620 return -ENOENT; 621 } 622 if (paddr > highaddr) { 623 pr_warning("Offset specified is greater than size of %s\n", 624 dwarf_diename(sp_die)); | |
625 return -EINVAL; 626 } 627 | 615 return -EINVAL; 616 } 617 |
628 symbol = dwarf_diename(sp_die); | 618 /* Try to get actual symbol name from symtab */ 619 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); |
629 if (!symbol) { | 620 if (!symbol) { |
630 /* Try to get the symbol name from symtab */ 631 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); 632 if (!symbol) { 633 pr_warning("Failed to find symbol at 0x%lx\n", 634 (unsigned long)paddr); 635 return -ENOENT; 636 } 637 eaddr = sym.st_value; | 621 pr_warning("Failed to find symbol at 0x%lx\n", 622 (unsigned long)paddr); 623 return -ENOENT; |
638 } | 624 } |
625 eaddr = sym.st_value; 626 |
|
639 tp->offset = (unsigned long)(paddr - eaddr); 640 tp->address = (unsigned long)paddr; 641 tp->symbol = strdup(symbol); 642 if (!tp->symbol) 643 return -ENOMEM; 644 645 /* Return probe must be on the head of a subprogram */ 646 if (retprobe) { --- 104 unchanged lines hidden (view full) --- 751 fsp->diff = fsp->line - lno; 752 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); 753 fsp->found = true; 754 } 755 } 756 return 0; 757} 758 | 627 tp->offset = (unsigned long)(paddr - eaddr); 628 tp->address = (unsigned long)paddr; 629 tp->symbol = strdup(symbol); 630 if (!tp->symbol) 631 return -ENOMEM; 632 633 /* Return probe must be on the head of a subprogram */ 634 if (retprobe) { --- 104 unchanged lines hidden (view full) --- 739 fsp->diff = fsp->line - lno; 740 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); 741 fsp->found = true; 742 } 743 } 744 return 0; 745} 746 |
747/* Return innermost DIE */ 748static int find_inner_scope_cb(Dwarf_Die *fn_die, void *data) 749{ 750 struct find_scope_param *fsp = data; 751 752 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); 753 fsp->found = true; 754 return 1; 755} 756 |
|
759/* Find an appropriate scope fits to given conditions */ 760static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem) 761{ 762 struct find_scope_param fsp = { 763 .function = pf->pev->point.function, 764 .file = pf->fname, 765 .line = pf->lno, 766 .diff = INT_MAX, 767 .die_mem = die_mem, 768 .found = false, 769 }; | 757/* Find an appropriate scope fits to given conditions */ 758static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem) 759{ 760 struct find_scope_param fsp = { 761 .function = pf->pev->point.function, 762 .file = pf->fname, 763 .line = pf->lno, 764 .diff = INT_MAX, 765 .die_mem = die_mem, 766 .found = false, 767 }; |
768 int ret; |
|
770 | 769 |
771 cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp); | 770 ret = cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, 771 &fsp); 772 if (!ret && !fsp.found) 773 cu_walk_functions_at(&pf->cu_die, pf->addr, 774 find_inner_scope_cb, &fsp); |
772 773 return fsp.found ? die_mem : NULL; 774} 775 | 775 776 return fsp.found ? die_mem : NULL; 777} 778 |
779static int verify_representive_line(struct probe_finder *pf, const char *fname, 780 int lineno, Dwarf_Addr addr) 781{ 782 const char *__fname, *__func = NULL; 783 Dwarf_Die die_mem; 784 int __lineno; 785 786 /* Verify line number and address by reverse search */ 787 if (cu_find_lineinfo(&pf->cu_die, addr, &__fname, &__lineno) < 0) 788 return 0; 789 790 pr_debug2("Reversed line: %s:%d\n", __fname, __lineno); 791 if (strcmp(fname, __fname) || lineno == __lineno) 792 return 0; 793 794 pr_warning("This line is sharing the addrees with other lines.\n"); 795 796 if (pf->pev->point.function) { 797 /* Find best match function name and lines */ 798 pf->addr = addr; 799 if (find_best_scope(pf, &die_mem) 800 && die_match_name(&die_mem, pf->pev->point.function) 801 && dwarf_decl_line(&die_mem, &lineno) == 0) { 802 __func = dwarf_diename(&die_mem); 803 __lineno -= lineno; 804 } 805 } 806 pr_warning("Please try to probe at %s:%d instead.\n", 807 __func ? : __fname, __lineno); 808 809 return -ENOENT; 810} 811 |
|
776static int probe_point_line_walker(const char *fname, int lineno, 777 Dwarf_Addr addr, void *data) 778{ 779 struct probe_finder *pf = data; 780 Dwarf_Die *sc_die, die_mem; 781 int ret; 782 783 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0) 784 return 0; 785 | 812static int probe_point_line_walker(const char *fname, int lineno, 813 Dwarf_Addr addr, void *data) 814{ 815 struct probe_finder *pf = data; 816 Dwarf_Die *sc_die, die_mem; 817 int ret; 818 819 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0) 820 return 0; 821 |
822 if (verify_representive_line(pf, fname, lineno, addr)) 823 return -ENOENT; 824 |
|
786 pf->addr = addr; 787 sc_die = find_best_scope(pf, &die_mem); 788 if (!sc_die) { 789 pr_warning("Failed to find scope of probe point.\n"); 790 return -ENOENT; 791 } 792 793 ret = call_probe_finder(sc_die, pf); --- 143 unchanged lines hidden (view full) --- 937 struct perf_probe_point *pp = &pf->pev->point; 938 Dwarf_Addr addr; 939 int ret; 940 941 if (pp->lazy_line) 942 ret = find_probe_point_lazy(in_die, pf); 943 else { 944 /* Get probe address */ | 825 pf->addr = addr; 826 sc_die = find_best_scope(pf, &die_mem); 827 if (!sc_die) { 828 pr_warning("Failed to find scope of probe point.\n"); 829 return -ENOENT; 830 } 831 832 ret = call_probe_finder(sc_die, pf); --- 143 unchanged lines hidden (view full) --- 976 struct perf_probe_point *pp = &pf->pev->point; 977 Dwarf_Addr addr; 978 int ret; 979 980 if (pp->lazy_line) 981 ret = find_probe_point_lazy(in_die, pf); 982 else { 983 /* Get probe address */ |
945 if (dwarf_entrypc(in_die, &addr) != 0) { | 984 if (die_entrypc(in_die, &addr) != 0) { |
946 pr_warning("Failed to get entry address of %s.\n", 947 dwarf_diename(in_die)); 948 return -ENOENT; 949 } 950 if (addr == 0) { 951 pr_debug("%s has no valid entry address. skipped.\n", 952 dwarf_diename(in_die)); 953 return -ENOENT; --- 35 unchanged lines hidden (view full) --- 989 (unsigned long)dwarf_dieoffset(sp_die)); 990 pf->fname = dwarf_decl_file(sp_die); 991 if (pp->line) { /* Function relative line */ 992 dwarf_decl_line(sp_die, &pf->lno); 993 pf->lno += pp->line; 994 param->retval = find_probe_point_by_line(pf); 995 } else if (die_is_func_instance(sp_die)) { 996 /* Instances always have the entry address */ | 985 pr_warning("Failed to get entry address of %s.\n", 986 dwarf_diename(in_die)); 987 return -ENOENT; 988 } 989 if (addr == 0) { 990 pr_debug("%s has no valid entry address. skipped.\n", 991 dwarf_diename(in_die)); 992 return -ENOENT; --- 35 unchanged lines hidden (view full) --- 1028 (unsigned long)dwarf_dieoffset(sp_die)); 1029 pf->fname = dwarf_decl_file(sp_die); 1030 if (pp->line) { /* Function relative line */ 1031 dwarf_decl_line(sp_die, &pf->lno); 1032 pf->lno += pp->line; 1033 param->retval = find_probe_point_by_line(pf); 1034 } else if (die_is_func_instance(sp_die)) { 1035 /* Instances always have the entry address */ |
997 dwarf_entrypc(sp_die, &pf->addr); | 1036 die_entrypc(sp_die, &pf->addr); |
998 /* But in some case the entry address is 0 */ 999 if (pf->addr == 0) { 1000 pr_debug("%s has no entry PC. Skipped\n", 1001 dwarf_diename(sp_die)); 1002 param->retval = 0; 1003 /* Real function */ 1004 } else if (pp->lazy_line) 1005 param->retval = find_probe_point_lazy(sp_die, pf); --- 414 unchanged lines hidden (view full) --- 1420 else 1421 return DIE_FIND_CB_SIBLING; 1422error: 1423 strbuf_release(&buf); 1424 pr_debug("Error in strbuf\n"); 1425 return DIE_FIND_CB_END; 1426} 1427 | 1037 /* But in some case the entry address is 0 */ 1038 if (pf->addr == 0) { 1039 pr_debug("%s has no entry PC. Skipped\n", 1040 dwarf_diename(sp_die)); 1041 param->retval = 0; 1042 /* Real function */ 1043 } else if (pp->lazy_line) 1044 param->retval = find_probe_point_lazy(sp_die, pf); --- 414 unchanged lines hidden (view full) --- 1459 else 1460 return DIE_FIND_CB_SIBLING; 1461error: 1462 strbuf_release(&buf); 1463 pr_debug("Error in strbuf\n"); 1464 return DIE_FIND_CB_END; 1465} 1466 |
1467static bool available_var_finder_overlap(struct available_var_finder *af) 1468{ 1469 int i; 1470 1471 for (i = 0; i < af->nvls; i++) { 1472 if (af->pf.addr == af->vls[i].point.address) 1473 return true; 1474 } 1475 return false; 1476 1477} 1478 |
|
1428/* Add a found vars into available variables list */ 1429static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) 1430{ 1431 struct available_var_finder *af = 1432 container_of(pf, struct available_var_finder, pf); 1433 struct perf_probe_point *pp = &pf->pev->point; 1434 struct variable_list *vl; 1435 Dwarf_Die die_mem; 1436 int ret; 1437 | 1479/* Add a found vars into available variables list */ 1480static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) 1481{ 1482 struct available_var_finder *af = 1483 container_of(pf, struct available_var_finder, pf); 1484 struct perf_probe_point *pp = &pf->pev->point; 1485 struct variable_list *vl; 1486 Dwarf_Die die_mem; 1487 int ret; 1488 |
1489 /* 1490 * For some reason (e.g. different column assigned to same address), 1491 * this callback can be called with the address which already passed. 1492 * Ignore it first. 1493 */ 1494 if (available_var_finder_overlap(af)) 1495 return 0; 1496 |
|
1438 /* Check number of tevs */ 1439 if (af->nvls == af->max_vls) { 1440 pr_warning("Too many( > %d) probe point found.\n", af->max_vls); 1441 return -ERANGE; 1442 } 1443 vl = &af->vls[af->nvls++]; 1444 1445 /* Trace point should be converted from subprogram DIE */ --- 127 unchanged lines hidden (view full) --- 1573 cu_find_lineinfo(&cudie, addr, &fname, &lineno); 1574 /* Don't care whether it failed or not */ 1575 1576 /* Find a corresponding function (name, baseline and baseaddr) */ 1577 if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) { 1578 /* Get function entry information */ 1579 func = basefunc = dwarf_diename(&spdie); 1580 if (!func || | 1497 /* Check number of tevs */ 1498 if (af->nvls == af->max_vls) { 1499 pr_warning("Too many( > %d) probe point found.\n", af->max_vls); 1500 return -ERANGE; 1501 } 1502 vl = &af->vls[af->nvls++]; 1503 1504 /* Trace point should be converted from subprogram DIE */ --- 127 unchanged lines hidden (view full) --- 1632 cu_find_lineinfo(&cudie, addr, &fname, &lineno); 1633 /* Don't care whether it failed or not */ 1634 1635 /* Find a corresponding function (name, baseline and baseaddr) */ 1636 if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) { 1637 /* Get function entry information */ 1638 func = basefunc = dwarf_diename(&spdie); 1639 if (!func || |
1581 dwarf_entrypc(&spdie, &baseaddr) != 0 || | 1640 die_entrypc(&spdie, &baseaddr) != 0 || |
1582 dwarf_decl_line(&spdie, &baseline) != 0) { 1583 lineno = 0; 1584 goto post; 1585 } 1586 1587 fname = dwarf_decl_file(&spdie); 1588 if (addr == (unsigned long)baseaddr) { 1589 /* Function entry - Relative line number is 0 */ 1590 lineno = baseline; 1591 goto post; 1592 } 1593 1594 /* Track down the inline functions step by step */ 1595 while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr, 1596 &indie)) { 1597 /* There is an inline function */ | 1641 dwarf_decl_line(&spdie, &baseline) != 0) { 1642 lineno = 0; 1643 goto post; 1644 } 1645 1646 fname = dwarf_decl_file(&spdie); 1647 if (addr == (unsigned long)baseaddr) { 1648 /* Function entry - Relative line number is 0 */ 1649 lineno = baseline; 1650 goto post; 1651 } 1652 1653 /* Track down the inline functions step by step */ 1654 while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr, 1655 &indie)) { 1656 /* There is an inline function */ |
1598 if (dwarf_entrypc(&indie, &_addr) == 0 && | 1657 if (die_entrypc(&indie, &_addr) == 0 && |
1599 _addr == addr) { 1600 /* 1601 * addr is at an inline function entry. 1602 * In this case, lineno should be the call-site 1603 * line number. (overwrite lineinfo) 1604 */ 1605 lineno = die_get_call_lineno(&indie); 1606 fname = die_get_call_file(&indie); --- 286 unchanged lines hidden --- | 1658 _addr == addr) { 1659 /* 1660 * addr is at an inline function entry. 1661 * In this case, lineno should be the call-site 1662 * line number. (overwrite lineinfo) 1663 */ 1664 lineno = die_get_call_lineno(&indie); 1665 fname = die_get_call_file(&indie); --- 286 unchanged lines hidden --- |