diff options
Diffstat (limited to 'tools/perf/util/probe-finder.c')
| -rw-r--r-- | tools/perf/util/probe-finder.c | 89 |
1 files changed, 46 insertions, 43 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index be0329394d56..371476cb8ddc 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -118,7 +118,6 @@ static const Dwfl_Callbacks offline_callbacks = { | |||
| 118 | static int debuginfo__init_offline_dwarf(struct debuginfo *self, | 118 | static int debuginfo__init_offline_dwarf(struct debuginfo *self, |
| 119 | const char *path) | 119 | const char *path) |
| 120 | { | 120 | { |
| 121 | Dwfl_Module *mod; | ||
| 122 | int fd; | 121 | int fd; |
| 123 | 122 | ||
| 124 | fd = open(path, O_RDONLY); | 123 | fd = open(path, O_RDONLY); |
| @@ -129,11 +128,11 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self, | |||
| 129 | if (!self->dwfl) | 128 | if (!self->dwfl) |
| 130 | goto error; | 129 | goto error; |
| 131 | 130 | ||
| 132 | mod = dwfl_report_offline(self->dwfl, "", "", fd); | 131 | self->mod = dwfl_report_offline(self->dwfl, "", "", fd); |
| 133 | if (!mod) | 132 | if (!self->mod) |
| 134 | goto error; | 133 | goto error; |
| 135 | 134 | ||
| 136 | self->dbg = dwfl_module_getdwarf(mod, &self->bias); | 135 | self->dbg = dwfl_module_getdwarf(self->mod, &self->bias); |
| 137 | if (!self->dbg) | 136 | if (!self->dbg) |
| 138 | goto error; | 137 | goto error; |
| 139 | 138 | ||
| @@ -676,37 +675,42 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
| 676 | } | 675 | } |
| 677 | 676 | ||
| 678 | /* Convert subprogram DIE to trace point */ | 677 | /* Convert subprogram DIE to trace point */ |
| 679 | static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr, | 678 | static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, |
| 680 | bool retprobe, struct probe_trace_point *tp) | 679 | Dwarf_Addr paddr, bool retprobe, |
| 680 | struct probe_trace_point *tp) | ||
| 681 | { | 681 | { |
| 682 | Dwarf_Addr eaddr, highaddr; | 682 | Dwarf_Addr eaddr, highaddr; |
| 683 | const char *name; | 683 | GElf_Sym sym; |
| 684 | 684 | const char *symbol; | |
| 685 | /* Copy the name of probe point */ | 685 | |
| 686 | name = dwarf_diename(sp_die); | 686 | /* Verify the address is correct */ |
| 687 | if (name) { | 687 | if (dwarf_entrypc(sp_die, &eaddr) != 0) { |
| 688 | if (dwarf_entrypc(sp_die, &eaddr) != 0) { | 688 | pr_warning("Failed to get entry address of %s\n", |
| 689 | pr_warning("Failed to get entry address of %s\n", | 689 | dwarf_diename(sp_die)); |
| 690 | dwarf_diename(sp_die)); | 690 | return -ENOENT; |
| 691 | return -ENOENT; | 691 | } |
| 692 | } | 692 | if (dwarf_highpc(sp_die, &highaddr) != 0) { |
| 693 | if (dwarf_highpc(sp_die, &highaddr) != 0) { | 693 | pr_warning("Failed to get end address of %s\n", |
| 694 | pr_warning("Failed to get end address of %s\n", | 694 | dwarf_diename(sp_die)); |
| 695 | dwarf_diename(sp_die)); | 695 | return -ENOENT; |
| 696 | return -ENOENT; | 696 | } |
| 697 | } | 697 | if (paddr > highaddr) { |
| 698 | if (paddr > highaddr) { | 698 | pr_warning("Offset specified is greater than size of %s\n", |
| 699 | pr_warning("Offset specified is greater than size of %s\n", | 699 | dwarf_diename(sp_die)); |
| 700 | dwarf_diename(sp_die)); | 700 | return -EINVAL; |
| 701 | return -EINVAL; | 701 | } |
| 702 | } | 702 | |
| 703 | tp->symbol = strdup(name); | 703 | /* Get an appropriate symbol from symtab */ |
| 704 | if (tp->symbol == NULL) | 704 | symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); |
| 705 | return -ENOMEM; | 705 | if (!symbol) { |
| 706 | tp->offset = (unsigned long)(paddr - eaddr); | 706 | pr_warning("Failed to find symbol at 0x%lx\n", |
| 707 | } else | 707 | (unsigned long)paddr); |
| 708 | /* This function has no name. */ | 708 | return -ENOENT; |
| 709 | tp->offset = (unsigned long)paddr; | 709 | } |
| 710 | tp->offset = (unsigned long)(paddr - sym.st_value); | ||
| 711 | tp->symbol = strdup(symbol); | ||
| 712 | if (!tp->symbol) | ||
| 713 | return -ENOMEM; | ||
| 710 | 714 | ||
| 711 | /* Return probe must be on the head of a subprogram */ | 715 | /* Return probe must be on the head of a subprogram */ |
| 712 | if (retprobe) { | 716 | if (retprobe) { |
| @@ -734,7 +738,7 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
| 734 | } | 738 | } |
| 735 | 739 | ||
| 736 | /* If not a real subprogram, find a real one */ | 740 | /* If not a real subprogram, find a real one */ |
| 737 | if (dwarf_tag(sc_die) != DW_TAG_subprogram) { | 741 | if (!die_is_func_def(sc_die)) { |
| 738 | if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { | 742 | if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { |
| 739 | pr_warning("Failed to find probe point in any " | 743 | pr_warning("Failed to find probe point in any " |
| 740 | "functions.\n"); | 744 | "functions.\n"); |
| @@ -980,12 +984,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) | |||
| 980 | struct dwarf_callback_param *param = data; | 984 | struct dwarf_callback_param *param = data; |
| 981 | struct probe_finder *pf = param->data; | 985 | struct probe_finder *pf = param->data; |
| 982 | struct perf_probe_point *pp = &pf->pev->point; | 986 | struct perf_probe_point *pp = &pf->pev->point; |
| 983 | Dwarf_Attribute attr; | ||
| 984 | 987 | ||
| 985 | /* Check tag and diename */ | 988 | /* Check tag and diename */ |
| 986 | if (dwarf_tag(sp_die) != DW_TAG_subprogram || | 989 | if (!die_is_func_def(sp_die) || |
| 987 | !die_compare_name(sp_die, pp->function) || | 990 | !die_compare_name(sp_die, pp->function)) |
| 988 | dwarf_attr(sp_die, DW_AT_declaration, &attr)) | ||
| 989 | return DWARF_CB_OK; | 991 | return DWARF_CB_OK; |
| 990 | 992 | ||
| 991 | /* Check declared file */ | 993 | /* Check declared file */ |
| @@ -1151,7 +1153,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
| 1151 | tev = &tf->tevs[tf->ntevs++]; | 1153 | tev = &tf->tevs[tf->ntevs++]; |
| 1152 | 1154 | ||
| 1153 | /* Trace point should be converted from subprogram DIE */ | 1155 | /* Trace point should be converted from subprogram DIE */ |
| 1154 | ret = convert_to_trace_point(&pf->sp_die, pf->addr, | 1156 | ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, |
| 1155 | pf->pev->point.retprobe, &tev->point); | 1157 | pf->pev->point.retprobe, &tev->point); |
| 1156 | if (ret < 0) | 1158 | if (ret < 0) |
| 1157 | return ret; | 1159 | return ret; |
| @@ -1183,7 +1185,7 @@ int debuginfo__find_trace_events(struct debuginfo *self, | |||
| 1183 | { | 1185 | { |
| 1184 | struct trace_event_finder tf = { | 1186 | struct trace_event_finder tf = { |
| 1185 | .pf = {.pev = pev, .callback = add_probe_trace_event}, | 1187 | .pf = {.pev = pev, .callback = add_probe_trace_event}, |
| 1186 | .max_tevs = max_tevs}; | 1188 | .mod = self->mod, .max_tevs = max_tevs}; |
| 1187 | int ret; | 1189 | int ret; |
| 1188 | 1190 | ||
| 1189 | /* Allocate result tevs array */ | 1191 | /* Allocate result tevs array */ |
| @@ -1252,7 +1254,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
| 1252 | vl = &af->vls[af->nvls++]; | 1254 | vl = &af->vls[af->nvls++]; |
| 1253 | 1255 | ||
| 1254 | /* Trace point should be converted from subprogram DIE */ | 1256 | /* Trace point should be converted from subprogram DIE */ |
| 1255 | ret = convert_to_trace_point(&pf->sp_die, pf->addr, | 1257 | ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr, |
| 1256 | pf->pev->point.retprobe, &vl->point); | 1258 | pf->pev->point.retprobe, &vl->point); |
| 1257 | if (ret < 0) | 1259 | if (ret < 0) |
| 1258 | return ret; | 1260 | return ret; |
| @@ -1291,6 +1293,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self, | |||
| 1291 | { | 1293 | { |
| 1292 | struct available_var_finder af = { | 1294 | struct available_var_finder af = { |
| 1293 | .pf = {.pev = pev, .callback = add_available_vars}, | 1295 | .pf = {.pev = pev, .callback = add_available_vars}, |
| 1296 | .mod = self->mod, | ||
| 1294 | .max_vls = max_vls, .externs = externs}; | 1297 | .max_vls = max_vls, .externs = externs}; |
| 1295 | int ret; | 1298 | int ret; |
| 1296 | 1299 | ||
| @@ -1474,7 +1477,7 @@ static int line_range_inline_cb(Dwarf_Die *in_die, void *data) | |||
| 1474 | return 0; | 1477 | return 0; |
| 1475 | } | 1478 | } |
| 1476 | 1479 | ||
| 1477 | /* Search function from function name */ | 1480 | /* Search function definition from function name */ |
| 1478 | static int line_range_search_cb(Dwarf_Die *sp_die, void *data) | 1481 | static int line_range_search_cb(Dwarf_Die *sp_die, void *data) |
| 1479 | { | 1482 | { |
| 1480 | struct dwarf_callback_param *param = data; | 1483 | struct dwarf_callback_param *param = data; |
| @@ -1485,7 +1488,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) | |||
| 1485 | if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die))) | 1488 | if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die))) |
| 1486 | return DWARF_CB_OK; | 1489 | return DWARF_CB_OK; |
| 1487 | 1490 | ||
| 1488 | if (dwarf_tag(sp_die) == DW_TAG_subprogram && | 1491 | if (die_is_func_def(sp_die) && |
| 1489 | die_compare_name(sp_die, lr->function)) { | 1492 | die_compare_name(sp_die, lr->function)) { |
| 1490 | lf->fname = dwarf_decl_file(sp_die); | 1493 | lf->fname = dwarf_decl_file(sp_die); |
| 1491 | dwarf_decl_line(sp_die, &lr->offset); | 1494 | dwarf_decl_line(sp_die, &lr->offset); |
