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 ---