aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2010-10-21 06:13:23 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-10-21 13:59:06 -0400
commitcf6eb489e5c04c8f8d5fd7bf90b8346c987688bc (patch)
tree3da471c3ae3f99cdcbec26cc95412a4b44506f3c /tools/perf/util/probe-finder.c
parent632941c4f8fbd5b90dcb1672cd0422dfd7332bc9 (diff)
perf probe: Show accessible local variables
Add -V (--vars) option for listing accessible local variables at given probe point. This will help finding which local variables are available for event arguments. e.g.) # perf probe -V call_timer_fn:23 Available variables at call_timer_fn:23 @<run_timer_softirq+345> function_type* fn int preempt_count long unsigned int data struct list_head work_list struct list_head* head struct timer_list* timer struct tvec_base* base Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20101021101323.3542.40282.stgit@ltc236.sdl.hitachi.co.jp> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r--tools/perf/util/probe-finder.c412
1 files changed, 317 insertions, 95 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index c6fe80ebb262..986027fa495f 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -172,8 +172,8 @@ static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
172 return NULL; 172 return NULL;
173} 173}
174 174
175/* Get type die, but skip qualifiers and typedef */ 175/* Get a type die, but skip qualifiers */
176static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) 176static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
177{ 177{
178 int tag; 178 int tag;
179 179
@@ -185,8 +185,17 @@ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
185 } while (tag == DW_TAG_const_type || 185 } while (tag == DW_TAG_const_type ||
186 tag == DW_TAG_restrict_type || 186 tag == DW_TAG_restrict_type ||
187 tag == DW_TAG_volatile_type || 187 tag == DW_TAG_volatile_type ||
188 tag == DW_TAG_shared_type || 188 tag == DW_TAG_shared_type);
189 tag == DW_TAG_typedef); 189
190 return vr_die;
191}
192
193/* Get a type die, but skip qualifiers and typedef */
194static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
195{
196 do {
197 vr_die = __die_get_real_type(vr_die, die_mem);
198 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
190 199
191 return vr_die; 200 return vr_die;
192} 201}
@@ -380,6 +389,60 @@ static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
380 die_mem); 389 die_mem);
381} 390}
382 391
392/* Get the name of given variable DIE */
393static int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
394{
395 Dwarf_Die type;
396 int tag, ret, ret2;
397 const char *tmp = "";
398
399 if (__die_get_real_type(vr_die, &type) == NULL)
400 return -ENOENT;
401
402 tag = dwarf_tag(&type);
403 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
404 tmp = "*";
405 else if (tag == DW_TAG_subroutine_type) {
406 /* Function pointer */
407 ret = snprintf(buf, len, "(function_type)");
408 return (ret >= len) ? -E2BIG : ret;
409 } else {
410 if (!dwarf_diename(&type))
411 return -ENOENT;
412 if (tag == DW_TAG_union_type)
413 tmp = "union ";
414 else if (tag == DW_TAG_structure_type)
415 tmp = "struct ";
416 /* Write a base name */
417 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
418 return (ret >= len) ? -E2BIG : ret;
419 }
420 ret = die_get_typename(&type, buf, len);
421 if (ret > 0) {
422 ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
423 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
424 }
425 return ret;
426}
427
428/* Get the name and type of given variable DIE, stored as "type\tname" */
429static int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
430{
431 int ret, ret2;
432
433 ret = die_get_typename(vr_die, buf, len);
434 if (ret < 0) {
435 pr_debug("Failed to get type, make it unknown.\n");
436 ret = snprintf(buf, len, "(unknown_type)");
437 }
438 if (ret > 0) {
439 ret2 = snprintf(buf + ret, len - ret, "\t%s",
440 dwarf_diename(vr_die));
441 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
442 }
443 return ret;
444}
445
383/* 446/*
384 * Probe finder related functions 447 * Probe finder related functions
385 */ 448 */
@@ -393,8 +456,13 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
393 return ref; 456 return ref;
394} 457}
395 458
396/* Show a location */ 459/*
397static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf) 460 * Convert a location into trace_arg.
461 * If tvar == NULL, this just checks variable can be converted.
462 */
463static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
464 Dwarf_Op *fb_ops,
465 struct probe_trace_arg *tvar)
398{ 466{
399 Dwarf_Attribute attr; 467 Dwarf_Attribute attr;
400 Dwarf_Op *op; 468 Dwarf_Op *op;
@@ -403,7 +471,6 @@ static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf)
403 Dwarf_Word offs = 0; 471 Dwarf_Word offs = 0;
404 bool ref = false; 472 bool ref = false;
405 const char *regs; 473 const char *regs;
406 struct probe_trace_arg *tvar = pf->tvar;
407 int ret; 474 int ret;
408 475
409 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL) 476 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
@@ -411,16 +478,16 @@ static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf)
411 478
412 /* TODO: handle more than 1 exprs */ 479 /* TODO: handle more than 1 exprs */
413 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL || 480 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
414 dwarf_getlocation_addr(&attr, pf->addr, &op, &nops, 1) <= 0 || 481 dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
415 nops == 0) { 482 nops == 0) {
416 /* TODO: Support const_value */ 483 /* TODO: Support const_value */
417 pr_err("Failed to find the location of %s at this address.\n"
418 " Perhaps, it has been optimized out.\n", pf->pvar->var);
419 return -ENOENT; 484 return -ENOENT;
420 } 485 }
421 486
422 if (op->atom == DW_OP_addr) { 487 if (op->atom == DW_OP_addr) {
423static_var: 488static_var:
489 if (!tvar)
490 return 0;
424 /* Static variables on memory (not stack), make @varname */ 491 /* Static variables on memory (not stack), make @varname */
425 ret = strlen(dwarf_diename(vr_die)); 492 ret = strlen(dwarf_diename(vr_die));
426 tvar->value = zalloc(ret + 2); 493 tvar->value = zalloc(ret + 2);
@@ -435,14 +502,11 @@ static_var:
435 502
436 /* If this is based on frame buffer, set the offset */ 503 /* If this is based on frame buffer, set the offset */
437 if (op->atom == DW_OP_fbreg) { 504 if (op->atom == DW_OP_fbreg) {
438 if (pf->fb_ops == NULL) { 505 if (fb_ops == NULL)
439 pr_warning("The attribute of frame base is not "
440 "supported.\n");
441 return -ENOTSUP; 506 return -ENOTSUP;
442 }
443 ref = true; 507 ref = true;
444 offs = op->number; 508 offs = op->number;
445 op = &pf->fb_ops[0]; 509 op = &fb_ops[0];
446 } 510 }
447 511
448 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) { 512 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
@@ -458,13 +522,18 @@ static_var:
458 } else if (op->atom == DW_OP_regx) { 522 } else if (op->atom == DW_OP_regx) {
459 regn = op->number; 523 regn = op->number;
460 } else { 524 } else {
461 pr_warning("DW_OP %x is not supported.\n", op->atom); 525 pr_debug("DW_OP %x is not supported.\n", op->atom);
462 return -ENOTSUP; 526 return -ENOTSUP;
463 } 527 }
464 528
529 if (!tvar)
530 return 0;
531
465 regs = get_arch_regstr(regn); 532 regs = get_arch_regstr(regn);
466 if (!regs) { 533 if (!regs) {
467 pr_warning("Mapping for DWARF register number %u missing on this architecture.", regn); 534 /* This should be a bug in DWARF or this tool */
535 pr_warning("Mapping for DWARF register number %u "
536 "missing on this architecture.", regn);
468 return -ERANGE; 537 return -ERANGE;
469 } 538 }
470 539
@@ -689,8 +758,14 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
689 pr_debug("Converting variable %s into trace event.\n", 758 pr_debug("Converting variable %s into trace event.\n",
690 dwarf_diename(vr_die)); 759 dwarf_diename(vr_die));
691 760
692 ret = convert_variable_location(vr_die, pf); 761 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
693 if (ret == 0 && pf->pvar->field) { 762 pf->tvar);
763 if (ret == -ENOENT)
764 pr_err("Failed to find the location of %s at this address.\n"
765 " Perhaps, it has been optimized out.\n", pf->pvar->var);
766 else if (ret == -ENOTSUP)
767 pr_err("Sorry, we don't support this variable location yet.\n");
768 else if (pf->pvar->field) {
694 ret = convert_variable_fields(vr_die, pf->pvar->var, 769 ret = convert_variable_fields(vr_die, pf->pvar->var,
695 pf->pvar->field, &pf->tvar->ref, 770 pf->pvar->field, &pf->tvar->ref,
696 &die_mem); 771 &die_mem);
@@ -772,34 +847,12 @@ found:
772 return ret; 847 return ret;
773} 848}
774 849
775/* Show a probe point to output buffer */ 850/* Convert subprogram DIE to trace point */
776static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) 851static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
852 bool retprobe, struct probe_trace_point *tp)
777{ 853{
778 struct probe_trace_event *tev;
779 Dwarf_Addr eaddr; 854 Dwarf_Addr eaddr;
780 Dwarf_Die die_mem;
781 const char *name; 855 const char *name;
782 int ret, i;
783 Dwarf_Attribute fb_attr;
784 size_t nops;
785
786 if (pf->ntevs == pf->max_tevs) {
787 pr_warning("Too many( > %d) probe point found.\n",
788 pf->max_tevs);
789 return -ERANGE;
790 }
791 tev = &pf->tevs[pf->ntevs++];
792
793 /* If no real subprogram, find a real one */
794 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
795 sp_die = die_find_real_subprogram(&pf->cu_die,
796 pf->addr, &die_mem);
797 if (!sp_die) {
798 pr_warning("Failed to find probe point in any "
799 "functions.\n");
800 return -ENOENT;
801 }
802 }
803 856
804 /* Copy the name of probe point */ 857 /* Copy the name of probe point */
805 name = dwarf_diename(sp_die); 858 name = dwarf_diename(sp_die);
@@ -809,26 +862,45 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
809 dwarf_diename(sp_die)); 862 dwarf_diename(sp_die));
810 return -ENOENT; 863 return -ENOENT;
811 } 864 }
812 tev->point.symbol = strdup(name); 865 tp->symbol = strdup(name);
813 if (tev->point.symbol == NULL) 866 if (tp->symbol == NULL)
814 return -ENOMEM; 867 return -ENOMEM;
815 tev->point.offset = (unsigned long)(pf->addr - eaddr); 868 tp->offset = (unsigned long)(paddr - eaddr);
816 } else 869 } else
817 /* This function has no name. */ 870 /* This function has no name. */
818 tev->point.offset = (unsigned long)pf->addr; 871 tp->offset = (unsigned long)paddr;
819 872
820 /* Return probe must be on the head of a subprogram */ 873 /* Return probe must be on the head of a subprogram */
821 if (pf->pev->point.retprobe) { 874 if (retprobe) {
822 if (tev->point.offset != 0) { 875 if (eaddr != paddr) {
823 pr_warning("Return probe must be on the head of" 876 pr_warning("Return probe must be on the head of"
824 " a real function\n"); 877 " a real function\n");
825 return -EINVAL; 878 return -EINVAL;
826 } 879 }
827 tev->point.retprobe = true; 880 tp->retprobe = true;
828 } 881 }
829 882
830 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 883 return 0;
831 tev->point.offset); 884}
885
886/* Call probe_finder callback with real subprogram DIE */
887static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
888{
889 Dwarf_Die die_mem;
890 Dwarf_Attribute fb_attr;
891 size_t nops;
892 int ret;
893
894 /* If no real subprogram, find a real one */
895 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
896 sp_die = die_find_real_subprogram(&pf->cu_die,
897 pf->addr, &die_mem);
898 if (!sp_die) {
899 pr_warning("Failed to find probe point in any "
900 "functions.\n");
901 return -ENOENT;
902 }
903 }
832 904
833 /* Get the frame base attribute/ops */ 905 /* Get the frame base attribute/ops */
834 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); 906 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
@@ -848,22 +920,13 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
848#endif 920#endif
849 } 921 }
850 922
851 /* Find each argument */ 923 /* Call finder's callback handler */
852 tev->nargs = pf->pev->nargs; 924 ret = pf->callback(sp_die, pf);
853 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
854 if (tev->args == NULL)
855 return -ENOMEM;
856 for (i = 0; i < pf->pev->nargs; i++) {
857 pf->pvar = &pf->pev->args[i];
858 pf->tvar = &tev->args[i];
859 ret = find_variable(sp_die, pf);
860 if (ret != 0)
861 return ret;
862 }
863 925
864 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 926 /* *pf->fb_ops will be cached in libdw. Don't free it. */
865 pf->fb_ops = NULL; 927 pf->fb_ops = NULL;
866 return 0; 928
929 return ret;
867} 930}
868 931
869/* Find probe point from its line number */ 932/* Find probe point from its line number */
@@ -899,7 +962,7 @@ static int find_probe_point_by_line(struct probe_finder *pf)
899 (int)i, lineno, (uintmax_t)addr); 962 (int)i, lineno, (uintmax_t)addr);
900 pf->addr = addr; 963 pf->addr = addr;
901 964
902 ret = convert_probe_point(NULL, pf); 965 ret = call_probe_finder(NULL, pf);
903 /* Continuing, because target line might be inlined. */ 966 /* Continuing, because target line might be inlined. */
904 } 967 }
905 return ret; 968 return ret;
@@ -1012,7 +1075,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1012 (int)i, lineno, (unsigned long long)addr); 1075 (int)i, lineno, (unsigned long long)addr);
1013 pf->addr = addr; 1076 pf->addr = addr;
1014 1077
1015 ret = convert_probe_point(sp_die, pf); 1078 ret = call_probe_finder(sp_die, pf);
1016 /* Continuing, because target line might be inlined. */ 1079 /* Continuing, because target line might be inlined. */
1017 } 1080 }
1018 /* TODO: deallocate lines, but how? */ 1081 /* TODO: deallocate lines, but how? */
@@ -1047,7 +1110,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1047 pr_debug("found inline addr: 0x%jx\n", 1110 pr_debug("found inline addr: 0x%jx\n",
1048 (uintmax_t)pf->addr); 1111 (uintmax_t)pf->addr);
1049 1112
1050 param->retval = convert_probe_point(in_die, pf); 1113 param->retval = call_probe_finder(in_die, pf);
1051 if (param->retval < 0) 1114 if (param->retval < 0)
1052 return DWARF_CB_ABORT; 1115 return DWARF_CB_ABORT;
1053 } 1116 }
@@ -1085,7 +1148,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1085 } 1148 }
1086 pf->addr += pp->offset; 1149 pf->addr += pp->offset;
1087 /* TODO: Check the address in this function */ 1150 /* TODO: Check the address in this function */
1088 param->retval = convert_probe_point(sp_die, pf); 1151 param->retval = call_probe_finder(sp_die, pf);
1089 } 1152 }
1090 } else { 1153 } else {
1091 struct dwarf_callback_param _param = {.data = (void *)pf, 1154 struct dwarf_callback_param _param = {.data = (void *)pf,
@@ -1107,70 +1170,229 @@ static int find_probe_point_by_func(struct probe_finder *pf)
1107 return _param.retval; 1170 return _param.retval;
1108} 1171}
1109 1172
1110/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1173/* Find probe points from debuginfo */
1111int find_probe_trace_events(int fd, struct perf_probe_event *pev, 1174static int find_probes(int fd, struct probe_finder *pf)
1112 struct probe_trace_event **tevs, int max_tevs)
1113{ 1175{
1114 struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs}; 1176 struct perf_probe_point *pp = &pf->pev->point;
1115 struct perf_probe_point *pp = &pev->point;
1116 Dwarf_Off off, noff; 1177 Dwarf_Off off, noff;
1117 size_t cuhl; 1178 size_t cuhl;
1118 Dwarf_Die *diep; 1179 Dwarf_Die *diep;
1119 Dwarf *dbg; 1180 Dwarf *dbg;
1120 int ret = 0; 1181 int ret = 0;
1121 1182
1122 pf.tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
1123 if (pf.tevs == NULL)
1124 return -ENOMEM;
1125 *tevs = pf.tevs;
1126 pf.ntevs = 0;
1127
1128 dbg = dwarf_begin(fd, DWARF_C_READ); 1183 dbg = dwarf_begin(fd, DWARF_C_READ);
1129 if (!dbg) { 1184 if (!dbg) {
1130 pr_warning("No dwarf info found in the vmlinux - " 1185 pr_warning("No dwarf info found in the vmlinux - "
1131 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1186 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1132 free(pf.tevs);
1133 *tevs = NULL;
1134 return -EBADF; 1187 return -EBADF;
1135 } 1188 }
1136 1189
1137#if _ELFUTILS_PREREQ(0, 142) 1190#if _ELFUTILS_PREREQ(0, 142)
1138 /* Get the call frame information from this dwarf */ 1191 /* Get the call frame information from this dwarf */
1139 pf.cfi = dwarf_getcfi(dbg); 1192 pf->cfi = dwarf_getcfi(dbg);
1140#endif 1193#endif
1141 1194
1142 off = 0; 1195 off = 0;
1143 line_list__init(&pf.lcache); 1196 line_list__init(&pf->lcache);
1144 /* Loop on CUs (Compilation Unit) */ 1197 /* Loop on CUs (Compilation Unit) */
1145 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) && 1198 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1146 ret >= 0) { 1199 ret >= 0) {
1147 /* Get the DIE(Debugging Information Entry) of this CU */ 1200 /* Get the DIE(Debugging Information Entry) of this CU */
1148 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die); 1201 diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die);
1149 if (!diep) 1202 if (!diep)
1150 continue; 1203 continue;
1151 1204
1152 /* Check if target file is included. */ 1205 /* Check if target file is included. */
1153 if (pp->file) 1206 if (pp->file)
1154 pf.fname = cu_find_realpath(&pf.cu_die, pp->file); 1207 pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
1155 else 1208 else
1156 pf.fname = NULL; 1209 pf->fname = NULL;
1157 1210
1158 if (!pp->file || pf.fname) { 1211 if (!pp->file || pf->fname) {
1159 if (pp->function) 1212 if (pp->function)
1160 ret = find_probe_point_by_func(&pf); 1213 ret = find_probe_point_by_func(pf);
1161 else if (pp->lazy_line) 1214 else if (pp->lazy_line)
1162 ret = find_probe_point_lazy(NULL, &pf); 1215 ret = find_probe_point_lazy(NULL, pf);
1163 else { 1216 else {
1164 pf.lno = pp->line; 1217 pf->lno = pp->line;
1165 ret = find_probe_point_by_line(&pf); 1218 ret = find_probe_point_by_line(pf);
1166 } 1219 }
1167 } 1220 }
1168 off = noff; 1221 off = noff;
1169 } 1222 }
1170 line_list__free(&pf.lcache); 1223 line_list__free(&pf->lcache);
1171 dwarf_end(dbg); 1224 dwarf_end(dbg);
1172 1225
1173 return (ret < 0) ? ret : pf.ntevs; 1226 return ret;
1227}
1228
1229/* Add a found probe point into trace event list */
1230static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1231{
1232 struct trace_event_finder *tf =
1233 container_of(pf, struct trace_event_finder, pf);
1234 struct probe_trace_event *tev;
1235 int ret, i;
1236
1237 /* Check number of tevs */
1238 if (tf->ntevs == tf->max_tevs) {
1239 pr_warning("Too many( > %d) probe point found.\n",
1240 tf->max_tevs);
1241 return -ERANGE;
1242 }
1243 tev = &tf->tevs[tf->ntevs++];
1244
1245 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
1246 &tev->point);
1247 if (ret < 0)
1248 return ret;
1249
1250 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1251 tev->point.offset);
1252
1253 /* Find each argument */
1254 tev->nargs = pf->pev->nargs;
1255 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1256 if (tev->args == NULL)
1257 return -ENOMEM;
1258 for (i = 0; i < pf->pev->nargs; i++) {
1259 pf->pvar = &pf->pev->args[i];
1260 pf->tvar = &tev->args[i];
1261 ret = find_variable(sp_die, pf);
1262 if (ret != 0)
1263 return ret;
1264 }
1265
1266 return 0;
1267}
1268
1269/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1270int find_probe_trace_events(int fd, struct perf_probe_event *pev,
1271 struct probe_trace_event **tevs, int max_tevs)
1272{
1273 struct trace_event_finder tf = {
1274 .pf = {.pev = pev, .callback = add_probe_trace_event},
1275 .max_tevs = max_tevs};
1276 int ret;
1277
1278 /* Allocate result tevs array */
1279 *tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
1280 if (*tevs == NULL)
1281 return -ENOMEM;
1282
1283 tf.tevs = *tevs;
1284 tf.ntevs = 0;
1285
1286 ret = find_probes(fd, &tf.pf);
1287 if (ret < 0) {
1288 free(*tevs);
1289 *tevs = NULL;
1290 return ret;
1291 }
1292
1293 return (ret < 0) ? ret : tf.ntevs;
1294}
1295
1296#define MAX_VAR_LEN 64
1297
1298/* Collect available variables in this scope */
1299static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1300{
1301 struct available_var_finder *af = data;
1302 struct variable_list *vl;
1303 char buf[MAX_VAR_LEN];
1304 int tag, ret;
1305
1306 vl = &af->vls[af->nvls - 1];
1307
1308 tag = dwarf_tag(die_mem);
1309 if (tag == DW_TAG_formal_parameter ||
1310 tag == DW_TAG_variable) {
1311 ret = convert_variable_location(die_mem, af->pf.addr,
1312 af->pf.fb_ops, NULL);
1313 if (ret == 0) {
1314 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
1315 if (ret > 0)
1316 strlist__add(vl->vars, buf);
1317 }
1318 }
1319
1320 if (dwarf_haspc(die_mem, af->pf.addr))
1321 return DIE_FIND_CB_CONTINUE;
1322 else
1323 return DIE_FIND_CB_SIBLING;
1324}
1325
1326/* Add a found vars into available variables list */
1327static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1328{
1329 struct available_var_finder *af =
1330 container_of(pf, struct available_var_finder, pf);
1331 struct variable_list *vl;
1332 Dwarf_Die die_mem;
1333 int ret;
1334
1335 /* Check number of tevs */
1336 if (af->nvls == af->max_vls) {
1337 pr_warning("Too many( > %d) probe point found.\n", af->max_vls);
1338 return -ERANGE;
1339 }
1340 vl = &af->vls[af->nvls++];
1341
1342 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
1343 &vl->point);
1344 if (ret < 0)
1345 return ret;
1346
1347 pr_debug("Probe point found: %s+%lu\n", vl->point.symbol,
1348 vl->point.offset);
1349
1350 /* Find local variables */
1351 vl->vars = strlist__new(true, NULL);
1352 if (vl->vars == NULL)
1353 return -ENOMEM;
1354 die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem);
1355
1356 if (strlist__empty(vl->vars)) {
1357 strlist__delete(vl->vars);
1358 vl->vars = NULL;
1359 }
1360
1361 return ret;
1362}
1363
1364/* Find available variables at given probe point */
1365int find_available_vars_at(int fd, struct perf_probe_event *pev,
1366 struct variable_list **vls, int max_vls)
1367{
1368 struct available_var_finder af = {
1369 .pf = {.pev = pev, .callback = add_available_vars},
1370 .max_vls = max_vls};
1371 int ret;
1372
1373 /* Allocate result vls array */
1374 *vls = zalloc(sizeof(struct variable_list) * max_vls);
1375 if (*vls == NULL)
1376 return -ENOMEM;
1377
1378 af.vls = *vls;
1379 af.nvls = 0;
1380
1381 ret = find_probes(fd, &af.pf);
1382 if (ret < 0) {
1383 /* Free vlist for error */
1384 while (af.nvls--) {
1385 if (af.vls[af.nvls].point.symbol)
1386 free(af.vls[af.nvls].point.symbol);
1387 if (af.vls[af.nvls].vars)
1388 strlist__delete(af.vls[af.nvls].vars);
1389 }
1390 free(af.vls);
1391 *vls = NULL;
1392 return ret;
1393 }
1394
1395 return (ret < 0) ? ret : af.nvls;
1174} 1396}
1175 1397
1176/* Reverse search */ 1398/* Reverse search */