aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r--tools/perf/util/probe-finder.c644
1 files changed, 510 insertions, 134 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 32b81f707ff5..c20bd52833aa 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -116,6 +116,101 @@ static void line_list__free(struct list_head *head)
116 } 116 }
117} 117}
118 118
119/* Dwarf FL wrappers */
120
121static int __linux_kernel_find_elf(Dwfl_Module *mod,
122 void **userdata,
123 const char *module_name,
124 Dwarf_Addr base,
125 char **file_name, Elf **elfp)
126{
127 int fd;
128 const char *path = kernel_get_module_path(module_name);
129
130 if (path) {
131 fd = open(path, O_RDONLY);
132 if (fd >= 0) {
133 *file_name = strdup(path);
134 return fd;
135 }
136 }
137 /* If failed, try to call standard method */
138 return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
139 file_name, elfp);
140}
141
142static char *debuginfo_path; /* Currently dummy */
143
144static const Dwfl_Callbacks offline_callbacks = {
145 .find_debuginfo = dwfl_standard_find_debuginfo,
146 .debuginfo_path = &debuginfo_path,
147
148 .section_address = dwfl_offline_section_address,
149
150 /* We use this table for core files too. */
151 .find_elf = dwfl_build_id_find_elf,
152};
153
154static const Dwfl_Callbacks kernel_callbacks = {
155 .find_debuginfo = dwfl_standard_find_debuginfo,
156 .debuginfo_path = &debuginfo_path,
157
158 .find_elf = __linux_kernel_find_elf,
159 .section_address = dwfl_linux_kernel_module_section_address,
160};
161
162/* Get a Dwarf from offline image */
163static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias)
164{
165 Dwfl_Module *mod;
166 Dwarf *dbg = NULL;
167
168 if (!dwflp)
169 return NULL;
170
171 *dwflp = dwfl_begin(&offline_callbacks);
172 if (!*dwflp)
173 return NULL;
174
175 mod = dwfl_report_offline(*dwflp, "", "", fd);
176 if (!mod)
177 goto error;
178
179 dbg = dwfl_module_getdwarf(mod, bias);
180 if (!dbg) {
181error:
182 dwfl_end(*dwflp);
183 *dwflp = NULL;
184 }
185 return dbg;
186}
187
188/* Get a Dwarf from live kernel image */
189static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,
190 Dwarf_Addr *bias)
191{
192 Dwarf *dbg;
193
194 if (!dwflp)
195 return NULL;
196
197 *dwflp = dwfl_begin(&kernel_callbacks);
198 if (!*dwflp)
199 return NULL;
200
201 /* Load the kernel dwarves: Don't care the result here */
202 dwfl_linux_kernel_report_kernel(*dwflp);
203 dwfl_linux_kernel_report_modules(*dwflp);
204
205 dbg = dwfl_addrdwarf(*dwflp, addr, bias);
206 /* Here, check whether we could get a real dwarf */
207 if (!dbg) {
208 dwfl_end(*dwflp);
209 *dwflp = NULL;
210 }
211 return dbg;
212}
213
119/* Dwarf wrappers */ 214/* Dwarf wrappers */
120 215
121/* Find the realpath of the target file. */ 216/* Find the realpath of the target file. */
@@ -160,26 +255,44 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
160 return name ? (strcmp(tname, name) == 0) : false; 255 return name ? (strcmp(tname, name) == 0) : false;
161} 256}
162 257
163/* Get type die, but skip qualifiers and typedef */ 258/* Get type die */
164static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) 259static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
165{ 260{
166 Dwarf_Attribute attr; 261 Dwarf_Attribute attr;
262
263 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
264 dwarf_formref_die(&attr, die_mem))
265 return die_mem;
266 else
267 return NULL;
268}
269
270/* Get a type die, but skip qualifiers */
271static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
272{
167 int tag; 273 int tag;
168 274
169 do { 275 do {
170 if (dwarf_attr(vr_die, DW_AT_type, &attr) == NULL || 276 vr_die = die_get_type(vr_die, die_mem);
171 dwarf_formref_die(&attr, die_mem) == NULL) 277 if (!vr_die)
172 return NULL; 278 break;
173 279 tag = dwarf_tag(vr_die);
174 tag = dwarf_tag(die_mem);
175 vr_die = die_mem;
176 } while (tag == DW_TAG_const_type || 280 } while (tag == DW_TAG_const_type ||
177 tag == DW_TAG_restrict_type || 281 tag == DW_TAG_restrict_type ||
178 tag == DW_TAG_volatile_type || 282 tag == DW_TAG_volatile_type ||
179 tag == DW_TAG_shared_type || 283 tag == DW_TAG_shared_type);
180 tag == DW_TAG_typedef); 284
285 return vr_die;
286}
181 287
182 return die_mem; 288/* Get a type die, but skip qualifiers and typedef */
289static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
290{
291 do {
292 vr_die = __die_get_real_type(vr_die, die_mem);
293 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
294
295 return vr_die;
183} 296}
184 297
185static bool die_is_signed_type(Dwarf_Die *tp_die) 298static bool die_is_signed_type(Dwarf_Die *tp_die)
@@ -320,25 +433,35 @@ static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
320 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); 433 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
321} 434}
322 435
436struct __find_variable_param {
437 const char *name;
438 Dwarf_Addr addr;
439};
440
323static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) 441static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
324{ 442{
325 const char *name = data; 443 struct __find_variable_param *fvp = data;
326 int tag; 444 int tag;
327 445
328 tag = dwarf_tag(die_mem); 446 tag = dwarf_tag(die_mem);
329 if ((tag == DW_TAG_formal_parameter || 447 if ((tag == DW_TAG_formal_parameter ||
330 tag == DW_TAG_variable) && 448 tag == DW_TAG_variable) &&
331 die_compare_name(die_mem, name)) 449 die_compare_name(die_mem, fvp->name))
332 return DIE_FIND_CB_FOUND; 450 return DIE_FIND_CB_FOUND;
333 451
334 return DIE_FIND_CB_CONTINUE; 452 if (dwarf_haspc(die_mem, fvp->addr))
453 return DIE_FIND_CB_CONTINUE;
454 else
455 return DIE_FIND_CB_SIBLING;
335} 456}
336 457
337/* Find a variable called 'name' */ 458/* Find a variable called 'name' at given address */
338static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name, 459static Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
339 Dwarf_Die *die_mem) 460 Dwarf_Addr addr, Dwarf_Die *die_mem)
340{ 461{
341 return die_find_child(sp_die, __die_find_variable_cb, (void *)name, 462 struct __find_variable_param fvp = { .name = name, .addr = addr};
463
464 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
342 die_mem); 465 die_mem);
343} 466}
344 467
@@ -361,6 +484,60 @@ static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
361 die_mem); 484 die_mem);
362} 485}
363 486
487/* Get the name of given variable DIE */
488static int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
489{
490 Dwarf_Die type;
491 int tag, ret, ret2;
492 const char *tmp = "";
493
494 if (__die_get_real_type(vr_die, &type) == NULL)
495 return -ENOENT;
496
497 tag = dwarf_tag(&type);
498 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
499 tmp = "*";
500 else if (tag == DW_TAG_subroutine_type) {
501 /* Function pointer */
502 ret = snprintf(buf, len, "(function_type)");
503 return (ret >= len) ? -E2BIG : ret;
504 } else {
505 if (!dwarf_diename(&type))
506 return -ENOENT;
507 if (tag == DW_TAG_union_type)
508 tmp = "union ";
509 else if (tag == DW_TAG_structure_type)
510 tmp = "struct ";
511 /* Write a base name */
512 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
513 return (ret >= len) ? -E2BIG : ret;
514 }
515 ret = die_get_typename(&type, buf, len);
516 if (ret > 0) {
517 ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
518 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
519 }
520 return ret;
521}
522
523/* Get the name and type of given variable DIE, stored as "type\tname" */
524static int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
525{
526 int ret, ret2;
527
528 ret = die_get_typename(vr_die, buf, len);
529 if (ret < 0) {
530 pr_debug("Failed to get type, make it unknown.\n");
531 ret = snprintf(buf, len, "(unknown_type)");
532 }
533 if (ret > 0) {
534 ret2 = snprintf(buf + ret, len - ret, "\t%s",
535 dwarf_diename(vr_die));
536 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
537 }
538 return ret;
539}
540
364/* 541/*
365 * Probe finder related functions 542 * Probe finder related functions
366 */ 543 */
@@ -374,8 +551,13 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
374 return ref; 551 return ref;
375} 552}
376 553
377/* Show a location */ 554/*
378static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf) 555 * Convert a location into trace_arg.
556 * If tvar == NULL, this just checks variable can be converted.
557 */
558static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
559 Dwarf_Op *fb_ops,
560 struct probe_trace_arg *tvar)
379{ 561{
380 Dwarf_Attribute attr; 562 Dwarf_Attribute attr;
381 Dwarf_Op *op; 563 Dwarf_Op *op;
@@ -384,20 +566,23 @@ static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf)
384 Dwarf_Word offs = 0; 566 Dwarf_Word offs = 0;
385 bool ref = false; 567 bool ref = false;
386 const char *regs; 568 const char *regs;
387 struct probe_trace_arg *tvar = pf->tvar;
388 int ret; 569 int ret;
389 570
571 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
572 goto static_var;
573
390 /* TODO: handle more than 1 exprs */ 574 /* TODO: handle more than 1 exprs */
391 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL || 575 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
392 dwarf_getlocation_addr(&attr, pf->addr, &op, &nops, 1) <= 0 || 576 dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
393 nops == 0) { 577 nops == 0) {
394 /* TODO: Support const_value */ 578 /* TODO: Support const_value */
395 pr_err("Failed to find the location of %s at this address.\n"
396 " Perhaps, it has been optimized out.\n", pf->pvar->var);
397 return -ENOENT; 579 return -ENOENT;
398 } 580 }
399 581
400 if (op->atom == DW_OP_addr) { 582 if (op->atom == DW_OP_addr) {
583static_var:
584 if (!tvar)
585 return 0;
401 /* Static variables on memory (not stack), make @varname */ 586 /* Static variables on memory (not stack), make @varname */
402 ret = strlen(dwarf_diename(vr_die)); 587 ret = strlen(dwarf_diename(vr_die));
403 tvar->value = zalloc(ret + 2); 588 tvar->value = zalloc(ret + 2);
@@ -412,14 +597,11 @@ static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf)
412 597
413 /* If this is based on frame buffer, set the offset */ 598 /* If this is based on frame buffer, set the offset */
414 if (op->atom == DW_OP_fbreg) { 599 if (op->atom == DW_OP_fbreg) {
415 if (pf->fb_ops == NULL) { 600 if (fb_ops == NULL)
416 pr_warning("The attribute of frame base is not "
417 "supported.\n");
418 return -ENOTSUP; 601 return -ENOTSUP;
419 }
420 ref = true; 602 ref = true;
421 offs = op->number; 603 offs = op->number;
422 op = &pf->fb_ops[0]; 604 op = &fb_ops[0];
423 } 605 }
424 606
425 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) { 607 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
@@ -435,13 +617,18 @@ static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf)
435 } else if (op->atom == DW_OP_regx) { 617 } else if (op->atom == DW_OP_regx) {
436 regn = op->number; 618 regn = op->number;
437 } else { 619 } else {
438 pr_warning("DW_OP %x is not supported.\n", op->atom); 620 pr_debug("DW_OP %x is not supported.\n", op->atom);
439 return -ENOTSUP; 621 return -ENOTSUP;
440 } 622 }
441 623
624 if (!tvar)
625 return 0;
626
442 regs = get_arch_regstr(regn); 627 regs = get_arch_regstr(regn);
443 if (!regs) { 628 if (!regs) {
444 pr_warning("Mapping for DWARF register number %u missing on this architecture.", regn); 629 /* This should be a bug in DWARF or this tool */
630 pr_warning("Mapping for DWARF register number %u "
631 "missing on this architecture.", regn);
445 return -ERANGE; 632 return -ERANGE;
446 } 633 }
447 634
@@ -666,8 +853,14 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
666 pr_debug("Converting variable %s into trace event.\n", 853 pr_debug("Converting variable %s into trace event.\n",
667 dwarf_diename(vr_die)); 854 dwarf_diename(vr_die));
668 855
669 ret = convert_variable_location(vr_die, pf); 856 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
670 if (ret == 0 && pf->pvar->field) { 857 pf->tvar);
858 if (ret == -ENOENT)
859 pr_err("Failed to find the location of %s at this address.\n"
860 " Perhaps, it has been optimized out.\n", pf->pvar->var);
861 else if (ret == -ENOTSUP)
862 pr_err("Sorry, we don't support this variable location yet.\n");
863 else if (pf->pvar->field) {
671 ret = convert_variable_fields(vr_die, pf->pvar->var, 864 ret = convert_variable_fields(vr_die, pf->pvar->var,
672 pf->pvar->field, &pf->tvar->ref, 865 pf->pvar->field, &pf->tvar->ref,
673 &die_mem); 866 &die_mem);
@@ -722,56 +915,39 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
722 pr_debug("Searching '%s' variable in context.\n", 915 pr_debug("Searching '%s' variable in context.\n",
723 pf->pvar->var); 916 pf->pvar->var);
724 /* Search child die for local variables and parameters. */ 917 /* Search child die for local variables and parameters. */
725 if (die_find_variable(sp_die, pf->pvar->var, &vr_die)) 918 if (die_find_variable_at(sp_die, pf->pvar->var, pf->addr, &vr_die))
726 ret = convert_variable(&vr_die, pf); 919 ret = convert_variable(&vr_die, pf);
727 else { 920 else {
728 /* Search upper class */ 921 /* Search upper class */
729 nscopes = dwarf_getscopes_die(sp_die, &scopes); 922 nscopes = dwarf_getscopes_die(sp_die, &scopes);
730 if (nscopes > 0) { 923 while (nscopes-- > 1) {
731 ret = dwarf_getscopevar(scopes, nscopes, pf->pvar->var, 924 pr_debug("Searching variables in %s\n",
732 0, NULL, 0, 0, &vr_die); 925 dwarf_diename(&scopes[nscopes]));
733 if (ret >= 0) 926 /* We should check this scope, so give dummy address */
927 if (die_find_variable_at(&scopes[nscopes],
928 pf->pvar->var, 0,
929 &vr_die)) {
734 ret = convert_variable(&vr_die, pf); 930 ret = convert_variable(&vr_die, pf);
735 else 931 goto found;
736 ret = -ENOENT; 932 }
933 }
934 if (scopes)
737 free(scopes); 935 free(scopes);
738 } else 936 ret = -ENOENT;
739 ret = -ENOENT;
740 } 937 }
938found:
741 if (ret < 0) 939 if (ret < 0)
742 pr_warning("Failed to find '%s' in this function.\n", 940 pr_warning("Failed to find '%s' in this function.\n",
743 pf->pvar->var); 941 pf->pvar->var);
744 return ret; 942 return ret;
745} 943}
746 944
747/* Show a probe point to output buffer */ 945/* Convert subprogram DIE to trace point */
748static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) 946static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
947 bool retprobe, struct probe_trace_point *tp)
749{ 948{
750 struct probe_trace_event *tev;
751 Dwarf_Addr eaddr; 949 Dwarf_Addr eaddr;
752 Dwarf_Die die_mem;
753 const char *name; 950 const char *name;
754 int ret, i;
755 Dwarf_Attribute fb_attr;
756 size_t nops;
757
758 if (pf->ntevs == pf->max_tevs) {
759 pr_warning("Too many( > %d) probe point found.\n",
760 pf->max_tevs);
761 return -ERANGE;
762 }
763 tev = &pf->tevs[pf->ntevs++];
764
765 /* If no real subprogram, find a real one */
766 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
767 sp_die = die_find_real_subprogram(&pf->cu_die,
768 pf->addr, &die_mem);
769 if (!sp_die) {
770 pr_warning("Failed to find probe point in any "
771 "functions.\n");
772 return -ENOENT;
773 }
774 }
775 951
776 /* Copy the name of probe point */ 952 /* Copy the name of probe point */
777 name = dwarf_diename(sp_die); 953 name = dwarf_diename(sp_die);
@@ -781,26 +957,45 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
781 dwarf_diename(sp_die)); 957 dwarf_diename(sp_die));
782 return -ENOENT; 958 return -ENOENT;
783 } 959 }
784 tev->point.symbol = strdup(name); 960 tp->symbol = strdup(name);
785 if (tev->point.symbol == NULL) 961 if (tp->symbol == NULL)
786 return -ENOMEM; 962 return -ENOMEM;
787 tev->point.offset = (unsigned long)(pf->addr - eaddr); 963 tp->offset = (unsigned long)(paddr - eaddr);
788 } else 964 } else
789 /* This function has no name. */ 965 /* This function has no name. */
790 tev->point.offset = (unsigned long)pf->addr; 966 tp->offset = (unsigned long)paddr;
791 967
792 /* Return probe must be on the head of a subprogram */ 968 /* Return probe must be on the head of a subprogram */
793 if (pf->pev->point.retprobe) { 969 if (retprobe) {
794 if (tev->point.offset != 0) { 970 if (eaddr != paddr) {
795 pr_warning("Return probe must be on the head of" 971 pr_warning("Return probe must be on the head of"
796 " a real function\n"); 972 " a real function\n");
797 return -EINVAL; 973 return -EINVAL;
798 } 974 }
799 tev->point.retprobe = true; 975 tp->retprobe = true;
800 } 976 }
801 977
802 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 978 return 0;
803 tev->point.offset); 979}
980
981/* Call probe_finder callback with real subprogram DIE */
982static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
983{
984 Dwarf_Die die_mem;
985 Dwarf_Attribute fb_attr;
986 size_t nops;
987 int ret;
988
989 /* If no real subprogram, find a real one */
990 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
991 sp_die = die_find_real_subprogram(&pf->cu_die,
992 pf->addr, &die_mem);
993 if (!sp_die) {
994 pr_warning("Failed to find probe point in any "
995 "functions.\n");
996 return -ENOENT;
997 }
998 }
804 999
805 /* Get the frame base attribute/ops */ 1000 /* Get the frame base attribute/ops */
806 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); 1001 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
@@ -820,22 +1015,13 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
820#endif 1015#endif
821 } 1016 }
822 1017
823 /* Find each argument */ 1018 /* Call finder's callback handler */
824 tev->nargs = pf->pev->nargs; 1019 ret = pf->callback(sp_die, pf);
825 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
826 if (tev->args == NULL)
827 return -ENOMEM;
828 for (i = 0; i < pf->pev->nargs; i++) {
829 pf->pvar = &pf->pev->args[i];
830 pf->tvar = &tev->args[i];
831 ret = find_variable(sp_die, pf);
832 if (ret != 0)
833 return ret;
834 }
835 1020
836 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 1021 /* *pf->fb_ops will be cached in libdw. Don't free it. */
837 pf->fb_ops = NULL; 1022 pf->fb_ops = NULL;
838 return 0; 1023
1024 return ret;
839} 1025}
840 1026
841/* Find probe point from its line number */ 1027/* Find probe point from its line number */
@@ -871,7 +1057,7 @@ static int find_probe_point_by_line(struct probe_finder *pf)
871 (int)i, lineno, (uintmax_t)addr); 1057 (int)i, lineno, (uintmax_t)addr);
872 pf->addr = addr; 1058 pf->addr = addr;
873 1059
874 ret = convert_probe_point(NULL, pf); 1060 ret = call_probe_finder(NULL, pf);
875 /* Continuing, because target line might be inlined. */ 1061 /* Continuing, because target line might be inlined. */
876 } 1062 }
877 return ret; 1063 return ret;
@@ -984,7 +1170,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
984 (int)i, lineno, (unsigned long long)addr); 1170 (int)i, lineno, (unsigned long long)addr);
985 pf->addr = addr; 1171 pf->addr = addr;
986 1172
987 ret = convert_probe_point(sp_die, pf); 1173 ret = call_probe_finder(sp_die, pf);
988 /* Continuing, because target line might be inlined. */ 1174 /* Continuing, because target line might be inlined. */
989 } 1175 }
990 /* TODO: deallocate lines, but how? */ 1176 /* TODO: deallocate lines, but how? */
@@ -1019,7 +1205,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1019 pr_debug("found inline addr: 0x%jx\n", 1205 pr_debug("found inline addr: 0x%jx\n",
1020 (uintmax_t)pf->addr); 1206 (uintmax_t)pf->addr);
1021 1207
1022 param->retval = convert_probe_point(in_die, pf); 1208 param->retval = call_probe_finder(in_die, pf);
1023 if (param->retval < 0) 1209 if (param->retval < 0)
1024 return DWARF_CB_ABORT; 1210 return DWARF_CB_ABORT;
1025 } 1211 }
@@ -1057,7 +1243,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1057 } 1243 }
1058 pf->addr += pp->offset; 1244 pf->addr += pp->offset;
1059 /* TODO: Check the address in this function */ 1245 /* TODO: Check the address in this function */
1060 param->retval = convert_probe_point(sp_die, pf); 1246 param->retval = call_probe_finder(sp_die, pf);
1061 } 1247 }
1062 } else { 1248 } else {
1063 struct dwarf_callback_param _param = {.data = (void *)pf, 1249 struct dwarf_callback_param _param = {.data = (void *)pf,
@@ -1079,90 +1265,276 @@ static int find_probe_point_by_func(struct probe_finder *pf)
1079 return _param.retval; 1265 return _param.retval;
1080} 1266}
1081 1267
1082/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1268/* Find probe points from debuginfo */
1083int find_probe_trace_events(int fd, struct perf_probe_event *pev, 1269static int find_probes(int fd, struct probe_finder *pf)
1084 struct probe_trace_event **tevs, int max_tevs)
1085{ 1270{
1086 struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs}; 1271 struct perf_probe_point *pp = &pf->pev->point;
1087 struct perf_probe_point *pp = &pev->point;
1088 Dwarf_Off off, noff; 1272 Dwarf_Off off, noff;
1089 size_t cuhl; 1273 size_t cuhl;
1090 Dwarf_Die *diep; 1274 Dwarf_Die *diep;
1091 Dwarf *dbg; 1275 Dwarf *dbg = NULL;
1276 Dwfl *dwfl;
1277 Dwarf_Addr bias; /* Currently ignored */
1092 int ret = 0; 1278 int ret = 0;
1093 1279
1094 pf.tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs); 1280 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1095 if (pf.tevs == NULL)
1096 return -ENOMEM;
1097 *tevs = pf.tevs;
1098 pf.ntevs = 0;
1099
1100 dbg = dwarf_begin(fd, DWARF_C_READ);
1101 if (!dbg) { 1281 if (!dbg) {
1102 pr_warning("No dwarf info found in the vmlinux - " 1282 pr_warning("No dwarf info found in the vmlinux - "
1103 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1283 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1104 free(pf.tevs);
1105 *tevs = NULL;
1106 return -EBADF; 1284 return -EBADF;
1107 } 1285 }
1108 1286
1109#if _ELFUTILS_PREREQ(0, 142) 1287#if _ELFUTILS_PREREQ(0, 142)
1110 /* Get the call frame information from this dwarf */ 1288 /* Get the call frame information from this dwarf */
1111 pf.cfi = dwarf_getcfi(dbg); 1289 pf->cfi = dwarf_getcfi(dbg);
1112#endif 1290#endif
1113 1291
1114 off = 0; 1292 off = 0;
1115 line_list__init(&pf.lcache); 1293 line_list__init(&pf->lcache);
1116 /* Loop on CUs (Compilation Unit) */ 1294 /* Loop on CUs (Compilation Unit) */
1117 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) && 1295 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1118 ret >= 0) { 1296 ret >= 0) {
1119 /* Get the DIE(Debugging Information Entry) of this CU */ 1297 /* Get the DIE(Debugging Information Entry) of this CU */
1120 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die); 1298 diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die);
1121 if (!diep) 1299 if (!diep)
1122 continue; 1300 continue;
1123 1301
1124 /* Check if target file is included. */ 1302 /* Check if target file is included. */
1125 if (pp->file) 1303 if (pp->file)
1126 pf.fname = cu_find_realpath(&pf.cu_die, pp->file); 1304 pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
1127 else 1305 else
1128 pf.fname = NULL; 1306 pf->fname = NULL;
1129 1307
1130 if (!pp->file || pf.fname) { 1308 if (!pp->file || pf->fname) {
1131 if (pp->function) 1309 if (pp->function)
1132 ret = find_probe_point_by_func(&pf); 1310 ret = find_probe_point_by_func(pf);
1133 else if (pp->lazy_line) 1311 else if (pp->lazy_line)
1134 ret = find_probe_point_lazy(NULL, &pf); 1312 ret = find_probe_point_lazy(NULL, pf);
1135 else { 1313 else {
1136 pf.lno = pp->line; 1314 pf->lno = pp->line;
1137 ret = find_probe_point_by_line(&pf); 1315 ret = find_probe_point_by_line(pf);
1138 } 1316 }
1139 } 1317 }
1140 off = noff; 1318 off = noff;
1141 } 1319 }
1142 line_list__free(&pf.lcache); 1320 line_list__free(&pf->lcache);
1143 dwarf_end(dbg); 1321 if (dwfl)
1322 dwfl_end(dwfl);
1144 1323
1145 return (ret < 0) ? ret : pf.ntevs; 1324 return ret;
1325}
1326
1327/* Add a found probe point into trace event list */
1328static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1329{
1330 struct trace_event_finder *tf =
1331 container_of(pf, struct trace_event_finder, pf);
1332 struct probe_trace_event *tev;
1333 int ret, i;
1334
1335 /* Check number of tevs */
1336 if (tf->ntevs == tf->max_tevs) {
1337 pr_warning("Too many( > %d) probe point found.\n",
1338 tf->max_tevs);
1339 return -ERANGE;
1340 }
1341 tev = &tf->tevs[tf->ntevs++];
1342
1343 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
1344 &tev->point);
1345 if (ret < 0)
1346 return ret;
1347
1348 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1349 tev->point.offset);
1350
1351 /* Find each argument */
1352 tev->nargs = pf->pev->nargs;
1353 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1354 if (tev->args == NULL)
1355 return -ENOMEM;
1356 for (i = 0; i < pf->pev->nargs; i++) {
1357 pf->pvar = &pf->pev->args[i];
1358 pf->tvar = &tev->args[i];
1359 ret = find_variable(sp_die, pf);
1360 if (ret != 0)
1361 return ret;
1362 }
1363
1364 return 0;
1365}
1366
1367/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1368int find_probe_trace_events(int fd, struct perf_probe_event *pev,
1369 struct probe_trace_event **tevs, int max_tevs)
1370{
1371 struct trace_event_finder tf = {
1372 .pf = {.pev = pev, .callback = add_probe_trace_event},
1373 .max_tevs = max_tevs};
1374 int ret;
1375
1376 /* Allocate result tevs array */
1377 *tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
1378 if (*tevs == NULL)
1379 return -ENOMEM;
1380
1381 tf.tevs = *tevs;
1382 tf.ntevs = 0;
1383
1384 ret = find_probes(fd, &tf.pf);
1385 if (ret < 0) {
1386 free(*tevs);
1387 *tevs = NULL;
1388 return ret;
1389 }
1390
1391 return (ret < 0) ? ret : tf.ntevs;
1392}
1393
1394#define MAX_VAR_LEN 64
1395
1396/* Collect available variables in this scope */
1397static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1398{
1399 struct available_var_finder *af = data;
1400 struct variable_list *vl;
1401 char buf[MAX_VAR_LEN];
1402 int tag, ret;
1403
1404 vl = &af->vls[af->nvls - 1];
1405
1406 tag = dwarf_tag(die_mem);
1407 if (tag == DW_TAG_formal_parameter ||
1408 tag == DW_TAG_variable) {
1409 ret = convert_variable_location(die_mem, af->pf.addr,
1410 af->pf.fb_ops, NULL);
1411 if (ret == 0) {
1412 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
1413 pr_debug2("Add new var: %s\n", buf);
1414 if (ret > 0)
1415 strlist__add(vl->vars, buf);
1416 }
1417 }
1418
1419 if (af->child && dwarf_haspc(die_mem, af->pf.addr))
1420 return DIE_FIND_CB_CONTINUE;
1421 else
1422 return DIE_FIND_CB_SIBLING;
1423}
1424
1425/* Add a found vars into available variables list */
1426static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1427{
1428 struct available_var_finder *af =
1429 container_of(pf, struct available_var_finder, pf);
1430 struct variable_list *vl;
1431 Dwarf_Die die_mem, *scopes = NULL;
1432 int ret, nscopes;
1433
1434 /* Check number of tevs */
1435 if (af->nvls == af->max_vls) {
1436 pr_warning("Too many( > %d) probe point found.\n", af->max_vls);
1437 return -ERANGE;
1438 }
1439 vl = &af->vls[af->nvls++];
1440
1441 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
1442 &vl->point);
1443 if (ret < 0)
1444 return ret;
1445
1446 pr_debug("Probe point found: %s+%lu\n", vl->point.symbol,
1447 vl->point.offset);
1448
1449 /* Find local variables */
1450 vl->vars = strlist__new(true, NULL);
1451 if (vl->vars == NULL)
1452 return -ENOMEM;
1453 af->child = true;
1454 die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem);
1455
1456 /* Find external variables */
1457 if (!af->externs)
1458 goto out;
1459 /* Don't need to search child DIE for externs. */
1460 af->child = false;
1461 nscopes = dwarf_getscopes_die(sp_die, &scopes);
1462 while (nscopes-- > 1)
1463 die_find_child(&scopes[nscopes], collect_variables_cb,
1464 (void *)af, &die_mem);
1465 if (scopes)
1466 free(scopes);
1467
1468out:
1469 if (strlist__empty(vl->vars)) {
1470 strlist__delete(vl->vars);
1471 vl->vars = NULL;
1472 }
1473
1474 return ret;
1475}
1476
1477/* Find available variables at given probe point */
1478int find_available_vars_at(int fd, struct perf_probe_event *pev,
1479 struct variable_list **vls, int max_vls,
1480 bool externs)
1481{
1482 struct available_var_finder af = {
1483 .pf = {.pev = pev, .callback = add_available_vars},
1484 .max_vls = max_vls, .externs = externs};
1485 int ret;
1486
1487 /* Allocate result vls array */
1488 *vls = zalloc(sizeof(struct variable_list) * max_vls);
1489 if (*vls == NULL)
1490 return -ENOMEM;
1491
1492 af.vls = *vls;
1493 af.nvls = 0;
1494
1495 ret = find_probes(fd, &af.pf);
1496 if (ret < 0) {
1497 /* Free vlist for error */
1498 while (af.nvls--) {
1499 if (af.vls[af.nvls].point.symbol)
1500 free(af.vls[af.nvls].point.symbol);
1501 if (af.vls[af.nvls].vars)
1502 strlist__delete(af.vls[af.nvls].vars);
1503 }
1504 free(af.vls);
1505 *vls = NULL;
1506 return ret;
1507 }
1508
1509 return (ret < 0) ? ret : af.nvls;
1146} 1510}
1147 1511
1148/* Reverse search */ 1512/* Reverse search */
1149int find_perf_probe_point(int fd, unsigned long addr, 1513int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1150 struct perf_probe_point *ppt)
1151{ 1514{
1152 Dwarf_Die cudie, spdie, indie; 1515 Dwarf_Die cudie, spdie, indie;
1153 Dwarf *dbg; 1516 Dwarf *dbg = NULL;
1517 Dwfl *dwfl = NULL;
1154 Dwarf_Line *line; 1518 Dwarf_Line *line;
1155 Dwarf_Addr laddr, eaddr; 1519 Dwarf_Addr laddr, eaddr, bias = 0;
1156 const char *tmp; 1520 const char *tmp;
1157 int lineno, ret = 0; 1521 int lineno, ret = 0;
1158 bool found = false; 1522 bool found = false;
1159 1523
1160 dbg = dwarf_begin(fd, DWARF_C_READ); 1524 /* Open the live linux kernel */
1161 if (!dbg) 1525 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
1162 return -EBADF; 1526 if (!dbg) {
1527 pr_warning("No dwarf info found in the vmlinux - "
1528 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1529 ret = -EINVAL;
1530 goto end;
1531 }
1163 1532
1533 /* Adjust address with bias */
1534 addr += bias;
1164 /* Find cu die */ 1535 /* Find cu die */
1165 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) { 1536 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) {
1537 pr_warning("No CU DIE is found at %lx\n", addr);
1166 ret = -EINVAL; 1538 ret = -EINVAL;
1167 goto end; 1539 goto end;
1168 } 1540 }
@@ -1225,7 +1597,8 @@ found:
1225 } 1597 }
1226 1598
1227end: 1599end:
1228 dwarf_end(dbg); 1600 if (dwfl)
1601 dwfl_end(dwfl);
1229 if (ret >= 0) 1602 if (ret >= 0)
1230 ret = found ? 1 : 0; 1603 ret = found ? 1 : 0;
1231 return ret; 1604 return ret;
@@ -1358,6 +1731,8 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1358 struct line_finder *lf = param->data; 1731 struct line_finder *lf = param->data;
1359 struct line_range *lr = lf->lr; 1732 struct line_range *lr = lf->lr;
1360 1733
1734 pr_debug("find (%lx) %s\n", dwarf_dieoffset(sp_die),
1735 dwarf_diename(sp_die));
1361 if (dwarf_tag(sp_die) == DW_TAG_subprogram && 1736 if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
1362 die_compare_name(sp_die, lr->function)) { 1737 die_compare_name(sp_die, lr->function)) {
1363 lf->fname = dwarf_decl_file(sp_die); 1738 lf->fname = dwarf_decl_file(sp_die);
@@ -1401,10 +1776,12 @@ int find_line_range(int fd, struct line_range *lr)
1401 Dwarf_Off off = 0, noff; 1776 Dwarf_Off off = 0, noff;
1402 size_t cuhl; 1777 size_t cuhl;
1403 Dwarf_Die *diep; 1778 Dwarf_Die *diep;
1404 Dwarf *dbg; 1779 Dwarf *dbg = NULL;
1780 Dwfl *dwfl;
1781 Dwarf_Addr bias; /* Currently ignored */
1405 const char *comp_dir; 1782 const char *comp_dir;
1406 1783
1407 dbg = dwarf_begin(fd, DWARF_C_READ); 1784 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1408 if (!dbg) { 1785 if (!dbg) {
1409 pr_warning("No dwarf info found in the vmlinux - " 1786 pr_warning("No dwarf info found in the vmlinux - "
1410 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1787 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
@@ -1450,8 +1827,7 @@ int find_line_range(int fd, struct line_range *lr)
1450 } 1827 }
1451 1828
1452 pr_debug("path: %s\n", lr->path); 1829 pr_debug("path: %s\n", lr->path);
1453 dwarf_end(dbg); 1830 dwfl_end(dwfl);
1454
1455 return (ret < 0) ? ret : lf.found; 1831 return (ret < 0) ? ret : lf.found;
1456} 1832}
1457 1833