probe-finder.c (632941c4f8fbd5b90dcb1672cd0422dfd7332bc9) probe-finder.c (cf6eb489e5c04c8f8d5fd7bf90b8346c987688bc)
1/*
2 * probe-finder.c : C expression to kprobe event converter
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or

--- 158 unchanged lines hidden (view full) ---

167
168 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
169 dwarf_formref_die(&attr, die_mem))
170 return die_mem;
171 else
172 return NULL;
173}
174
1/*
2 * probe-finder.c : C expression to kprobe event converter
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or

--- 158 unchanged lines hidden (view full) ---

167
168 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
169 dwarf_formref_die(&attr, die_mem))
170 return die_mem;
171 else
172 return NULL;
173}
174
175/* Get type die, but skip qualifiers and typedef */
176static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
175/* Get a type die, but skip qualifiers */
176static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
177{
178 int tag;
179
180 do {
181 vr_die = die_get_type(vr_die, die_mem);
182 if (!vr_die)
183 break;
184 tag = dwarf_tag(vr_die);
185 } while (tag == DW_TAG_const_type ||
186 tag == DW_TAG_restrict_type ||
187 tag == DW_TAG_volatile_type ||
177{
178 int tag;
179
180 do {
181 vr_die = die_get_type(vr_die, die_mem);
182 if (!vr_die)
183 break;
184 tag = dwarf_tag(vr_die);
185 } while (tag == DW_TAG_const_type ||
186 tag == DW_TAG_restrict_type ||
187 tag == DW_TAG_volatile_type ||
188 tag == DW_TAG_shared_type ||
189 tag == DW_TAG_typedef);
188 tag == DW_TAG_shared_type);
190
191 return vr_die;
192}
193
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);
199
200 return vr_die;
201}
202
194static bool die_is_signed_type(Dwarf_Die *tp_die)
195{
196 Dwarf_Attribute attr;
197 Dwarf_Word ret;
198
199 if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
200 dwarf_formudata(&attr, &ret) != 0)
201 return false;

--- 173 unchanged lines hidden (view full) ---

375/* Find a member called 'name' */
376static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
377 Dwarf_Die *die_mem)
378{
379 return die_find_child(st_die, __die_find_member_cb, (void *)name,
380 die_mem);
381}
382
203static bool die_is_signed_type(Dwarf_Die *tp_die)
204{
205 Dwarf_Attribute attr;
206 Dwarf_Word ret;
207
208 if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
209 dwarf_formudata(&attr, &ret) != 0)
210 return false;

--- 173 unchanged lines hidden (view full) ---

384/* Find a member called 'name' */
385static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
386 Dwarf_Die *die_mem)
387{
388 return die_find_child(st_die, __die_find_member_cb, (void *)name,
389 die_mem);
390}
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/*
384 * Probe finder related functions
385 */
386
387static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
388{
389 struct probe_trace_arg_ref *ref;
390 ref = zalloc(sizeof(struct probe_trace_arg_ref));
391 if (ref != NULL)
392 ref->offset = offs;
393 return ref;
394}
395
446/*
447 * Probe finder related functions
448 */
449
450static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
451{
452 struct probe_trace_arg_ref *ref;
453 ref = zalloc(sizeof(struct probe_trace_arg_ref));
454 if (ref != NULL)
455 ref->offset = offs;
456 return ref;
457}
458
396/* Show a location */
397static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf)
459/*
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{
399 Dwarf_Attribute attr;
400 Dwarf_Op *op;
401 size_t nops;
402 unsigned int regn;
403 Dwarf_Word offs = 0;
404 bool ref = false;
405 const char *regs;
466{
467 Dwarf_Attribute attr;
468 Dwarf_Op *op;
469 size_t nops;
470 unsigned int regn;
471 Dwarf_Word offs = 0;
472 bool ref = false;
473 const char *regs;
406 struct probe_trace_arg *tvar = pf->tvar;
407 int ret;
408
409 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
410 goto static_var;
411
412 /* TODO: handle more than 1 exprs */
413 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
474 int ret;
475
476 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
477 goto static_var;
478
479 /* TODO: handle more than 1 exprs */
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) {
416 /* TODO: Support const_value */
482 nops == 0) {
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;
420 }
421
422 if (op->atom == DW_OP_addr) {
423static_var:
484 return -ENOENT;
485 }
486
487 if (op->atom == DW_OP_addr) {
488static_var:
489 if (!tvar)
490 return 0;
424 /* Static variables on memory (not stack), make @varname */
425 ret = strlen(dwarf_diename(vr_die));
426 tvar->value = zalloc(ret + 2);
427 if (tvar->value == NULL)
428 return -ENOMEM;
429 snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
430 tvar->ref = alloc_trace_arg_ref((long)offs);
431 if (tvar->ref == NULL)
432 return -ENOMEM;
433 return 0;
434 }
435
436 /* If this is based on frame buffer, set the offset */
437 if (op->atom == DW_OP_fbreg) {
491 /* Static variables on memory (not stack), make @varname */
492 ret = strlen(dwarf_diename(vr_die));
493 tvar->value = zalloc(ret + 2);
494 if (tvar->value == NULL)
495 return -ENOMEM;
496 snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
497 tvar->ref = alloc_trace_arg_ref((long)offs);
498 if (tvar->ref == NULL)
499 return -ENOMEM;
500 return 0;
501 }
502
503 /* If this is based on frame buffer, set the offset */
504 if (op->atom == DW_OP_fbreg) {
438 if (pf->fb_ops == NULL) {
439 pr_warning("The attribute of frame base is not "
440 "supported.\n");
505 if (fb_ops == NULL)
441 return -ENOTSUP;
506 return -ENOTSUP;
442 }
443 ref = true;
444 offs = op->number;
507 ref = true;
508 offs = op->number;
445 op = &pf->fb_ops[0];
509 op = &fb_ops[0];
446 }
447
448 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
449 regn = op->atom - DW_OP_breg0;
450 offs += op->number;
451 ref = true;
452 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
453 regn = op->atom - DW_OP_reg0;
454 } else if (op->atom == DW_OP_bregx) {
455 regn = op->number;
456 offs += op->number2;
457 ref = true;
458 } else if (op->atom == DW_OP_regx) {
459 regn = op->number;
460 } else {
510 }
511
512 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
513 regn = op->atom - DW_OP_breg0;
514 offs += op->number;
515 ref = true;
516 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
517 regn = op->atom - DW_OP_reg0;
518 } else if (op->atom == DW_OP_bregx) {
519 regn = op->number;
520 offs += op->number2;
521 ref = true;
522 } else if (op->atom == DW_OP_regx) {
523 regn = op->number;
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;
463 }
464
526 return -ENOTSUP;
527 }
528
529 if (!tvar)
530 return 0;
531
465 regs = get_arch_regstr(regn);
466 if (!regs) {
532 regs = get_arch_regstr(regn);
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;
469 }
470
471 tvar->value = strdup(regs);
472 if (tvar->value == NULL)
473 return -ENOMEM;
474
475 if (ref) {

--- 208 unchanged lines hidden (view full) ---

684static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
685{
686 Dwarf_Die die_mem;
687 int ret;
688
689 pr_debug("Converting variable %s into trace event.\n",
690 dwarf_diename(vr_die));
691
537 return -ERANGE;
538 }
539
540 tvar->value = strdup(regs);
541 if (tvar->value == NULL)
542 return -ENOMEM;
543
544 if (ref) {

--- 208 unchanged lines hidden (view full) ---

753static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
754{
755 Dwarf_Die die_mem;
756 int ret;
757
758 pr_debug("Converting variable %s into trace event.\n",
759 dwarf_diename(vr_die));
760
692 ret = convert_variable_location(vr_die, pf);
693 if (ret == 0 && pf->pvar->field) {
761 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
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,
695 pf->pvar->field, &pf->tvar->ref,
696 &die_mem);
697 vr_die = &die_mem;
698 }
699 if (ret == 0)
700 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
701 /* *expr will be cached in libdw. Don't free it. */

--- 65 unchanged lines hidden (view full) ---

767 }
768found:
769 if (ret < 0)
770 pr_warning("Failed to find '%s' in this function.\n",
771 pf->pvar->var);
772 return ret;
773}
774
769 ret = convert_variable_fields(vr_die, pf->pvar->var,
770 pf->pvar->field, &pf->tvar->ref,
771 &die_mem);
772 vr_die = &die_mem;
773 }
774 if (ret == 0)
775 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
776 /* *expr will be cached in libdw. Don't free it. */

--- 65 unchanged lines hidden (view full) ---

842 }
843found:
844 if (ret < 0)
845 pr_warning("Failed to find '%s' in this function.\n",
846 pf->pvar->var);
847 return ret;
848}
849
775/* Show a probe point to output buffer */
776static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
850/* Convert subprogram DIE to trace point */
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
856
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
804 /* Copy the name of probe point */
805 name = dwarf_diename(sp_die);
806 if (name) {
807 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
808 pr_warning("Failed to get entry pc of %s\n",
809 dwarf_diename(sp_die));
810 return -ENOENT;
811 }
857 /* Copy the name of probe point */
858 name = dwarf_diename(sp_die);
859 if (name) {
860 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
861 pr_warning("Failed to get entry pc of %s\n",
862 dwarf_diename(sp_die));
863 return -ENOENT;
864 }
812 tev->point.symbol = strdup(name);
813 if (tev->point.symbol == NULL)
865 tp->symbol = strdup(name);
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
817 /* This function has no name. */
869 } else
870 /* This function has no name. */
818 tev->point.offset = (unsigned long)pf->addr;
871 tp->offset = (unsigned long)paddr;
819
820 /* Return probe must be on the head of a subprogram */
872
873 /* Return probe must be on the head of a subprogram */
821 if (pf->pev->point.retprobe) {
822 if (tev->point.offset != 0) {
874 if (retprobe) {
875 if (eaddr != paddr) {
823 pr_warning("Return probe must be on the head of"
824 " a real function\n");
825 return -EINVAL;
826 }
876 pr_warning("Return probe must be on the head of"
877 " a real function\n");
878 return -EINVAL;
879 }
827 tev->point.retprobe = true;
880 tp->retprobe = true;
828 }
829
881 }
882
830 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
831 tev->point.offset);
883 return 0;
884}
832
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 }
904
833 /* Get the frame base attribute/ops */
834 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
835 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
836 if (ret <= 0 || nops == 0) {
837 pf->fb_ops = NULL;
838#if _ELFUTILS_PREREQ(0, 142)
839 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
840 pf->cfi != NULL) {
841 Dwarf_Frame *frame;
842 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
843 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
844 pr_warning("Failed to get CFA on 0x%jx\n",
845 (uintmax_t)pf->addr);
846 return -ENOENT;
847 }
848#endif
849 }
850
905 /* Get the frame base attribute/ops */
906 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
907 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
908 if (ret <= 0 || nops == 0) {
909 pf->fb_ops = NULL;
910#if _ELFUTILS_PREREQ(0, 142)
911 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
912 pf->cfi != NULL) {
913 Dwarf_Frame *frame;
914 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
915 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
916 pr_warning("Failed to get CFA on 0x%jx\n",
917 (uintmax_t)pf->addr);
918 return -ENOENT;
919 }
920#endif
921 }
922
851 /* Find each argument */
852 tev->nargs = pf->pev->nargs;
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 }
923 /* Call finder's callback handler */
924 ret = pf->callback(sp_die, pf);
863
864 /* *pf->fb_ops will be cached in libdw. Don't free it. */
865 pf->fb_ops = NULL;
925
926 /* *pf->fb_ops will be cached in libdw. Don't free it. */
927 pf->fb_ops = NULL;
866 return 0;
928
929 return ret;
867}
868
869/* Find probe point from its line number */
870static int find_probe_point_by_line(struct probe_finder *pf)
871{
872 Dwarf_Lines *lines;
873 Dwarf_Line *line;
874 size_t nlines, i;

--- 19 unchanged lines hidden (view full) ---

894 if (dwarf_lineaddr(line, &addr) != 0) {
895 pr_warning("Failed to get the address of the line.\n");
896 return -ENOENT;
897 }
898 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
899 (int)i, lineno, (uintmax_t)addr);
900 pf->addr = addr;
901
930}
931
932/* Find probe point from its line number */
933static int find_probe_point_by_line(struct probe_finder *pf)
934{
935 Dwarf_Lines *lines;
936 Dwarf_Line *line;
937 size_t nlines, i;

--- 19 unchanged lines hidden (view full) ---

957 if (dwarf_lineaddr(line, &addr) != 0) {
958 pr_warning("Failed to get the address of the line.\n");
959 return -ENOENT;
960 }
961 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
962 (int)i, lineno, (uintmax_t)addr);
963 pf->addr = addr;
964
902 ret = convert_probe_point(NULL, pf);
965 ret = call_probe_finder(NULL, pf);
903 /* Continuing, because target line might be inlined. */
904 }
905 return ret;
906}
907
908/* Find lines which match lazy pattern */
909static int find_lazy_match_lines(struct list_head *head,
910 const char *fname, const char *pat)

--- 96 unchanged lines hidden (view full) ---

1007 if (die_find_inlinefunc(sp_die, addr, &die_mem))
1008 continue;
1009 }
1010
1011 pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
1012 (int)i, lineno, (unsigned long long)addr);
1013 pf->addr = addr;
1014
966 /* Continuing, because target line might be inlined. */
967 }
968 return ret;
969}
970
971/* Find lines which match lazy pattern */
972static int find_lazy_match_lines(struct list_head *head,
973 const char *fname, const char *pat)

--- 96 unchanged lines hidden (view full) ---

1070 if (die_find_inlinefunc(sp_die, addr, &die_mem))
1071 continue;
1072 }
1073
1074 pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
1075 (int)i, lineno, (unsigned long long)addr);
1076 pf->addr = addr;
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. */
1017 }
1018 /* TODO: deallocate lines, but how? */
1019 return ret;
1020}
1021
1022/* Callback parameter with return value */
1023struct dwarf_callback_param {

--- 18 unchanged lines hidden (view full) ---

1042 param->retval = -ENOENT;
1043 return DWARF_CB_ABORT;
1044 }
1045 pf->addr = addr;
1046 pf->addr += pp->offset;
1047 pr_debug("found inline addr: 0x%jx\n",
1048 (uintmax_t)pf->addr);
1049
1079 /* Continuing, because target line might be inlined. */
1080 }
1081 /* TODO: deallocate lines, but how? */
1082 return ret;
1083}
1084
1085/* Callback parameter with return value */
1086struct dwarf_callback_param {

--- 18 unchanged lines hidden (view full) ---

1105 param->retval = -ENOENT;
1106 return DWARF_CB_ABORT;
1107 }
1108 pf->addr = addr;
1109 pf->addr += pp->offset;
1110 pr_debug("found inline addr: 0x%jx\n",
1111 (uintmax_t)pf->addr);
1112
1050 param->retval = convert_probe_point(in_die, pf);
1113 param->retval = call_probe_finder(in_die, pf);
1051 if (param->retval < 0)
1052 return DWARF_CB_ABORT;
1053 }
1054
1055 return DWARF_CB_OK;
1056}
1057
1058/* Search function from function name */

--- 21 unchanged lines hidden (view full) ---

1080 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1081 pr_warning("Failed to get entry pc of %s.\n",
1082 dwarf_diename(sp_die));
1083 param->retval = -ENOENT;
1084 return DWARF_CB_ABORT;
1085 }
1086 pf->addr += pp->offset;
1087 /* TODO: Check the address in this function */
1114 if (param->retval < 0)
1115 return DWARF_CB_ABORT;
1116 }
1117
1118 return DWARF_CB_OK;
1119}
1120
1121/* Search function from function name */

--- 21 unchanged lines hidden (view full) ---

1143 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1144 pr_warning("Failed to get entry pc of %s.\n",
1145 dwarf_diename(sp_die));
1146 param->retval = -ENOENT;
1147 return DWARF_CB_ABORT;
1148 }
1149 pf->addr += pp->offset;
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 }
1090 } else {
1091 struct dwarf_callback_param _param = {.data = (void *)pf,
1092 .retval = 0};
1093 /* Inlined function: search instances */
1094 dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
1095 &_param);
1096 param->retval = _param.retval;

--- 5 unchanged lines hidden (view full) ---

1102static int find_probe_point_by_func(struct probe_finder *pf)
1103{
1104 struct dwarf_callback_param _param = {.data = (void *)pf,
1105 .retval = 0};
1106 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
1107 return _param.retval;
1108}
1109
1152 }
1153 } else {
1154 struct dwarf_callback_param _param = {.data = (void *)pf,
1155 .retval = 0};
1156 /* Inlined function: search instances */
1157 dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
1158 &_param);
1159 param->retval = _param.retval;

--- 5 unchanged lines hidden (view full) ---

1165static int find_probe_point_by_func(struct probe_finder *pf)
1166{
1167 struct dwarf_callback_param _param = {.data = (void *)pf,
1168 .retval = 0};
1169 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
1170 return _param.retval;
1171}
1172
1110/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1111int find_probe_trace_events(int fd, struct perf_probe_event *pev,
1112 struct probe_trace_event **tevs, int max_tevs)
1173/* Find probe points from debuginfo */
1174static int find_probes(int fd, struct probe_finder *pf)
1113{
1175{
1114 struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs};
1115 struct perf_probe_point *pp = &pev->point;
1176 struct perf_probe_point *pp = &pf->pev->point;
1116 Dwarf_Off off, noff;
1117 size_t cuhl;
1118 Dwarf_Die *diep;
1119 Dwarf *dbg;
1120 int ret = 0;
1121
1177 Dwarf_Off off, noff;
1178 size_t cuhl;
1179 Dwarf_Die *diep;
1180 Dwarf *dbg;
1181 int ret = 0;
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);
1129 if (!dbg) {
1130 pr_warning("No dwarf info found in the vmlinux - "
1131 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1183 dbg = dwarf_begin(fd, DWARF_C_READ);
1184 if (!dbg) {
1185 pr_warning("No dwarf info found in the vmlinux - "
1186 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1132 free(pf.tevs);
1133 *tevs = NULL;
1134 return -EBADF;
1135 }
1136
1137#if _ELFUTILS_PREREQ(0, 142)
1138 /* Get the call frame information from this dwarf */
1187 return -EBADF;
1188 }
1189
1190#if _ELFUTILS_PREREQ(0, 142)
1191 /* Get the call frame information from this dwarf */
1139 pf.cfi = dwarf_getcfi(dbg);
1192 pf->cfi = dwarf_getcfi(dbg);
1140#endif
1141
1142 off = 0;
1193#endif
1194
1195 off = 0;
1143 line_list__init(&pf.lcache);
1196 line_list__init(&pf->lcache);
1144 /* Loop on CUs (Compilation Unit) */
1145 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1146 ret >= 0) {
1147 /* Get the DIE(Debugging Information Entry) of this CU */
1197 /* Loop on CUs (Compilation Unit) */
1198 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1199 ret >= 0) {
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)
1150 continue;
1151
1152 /* Check if target file is included. */
1153 if (pp->file)
1202 if (!diep)
1203 continue;
1204
1205 /* Check if target file is included. */
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;
1165 ret = find_probe_point_by_line(&pf);
1217 pf->lno = pp->line;
1218 ret = find_probe_point_by_line(pf);
1166 }
1167 }
1168 off = noff;
1169 }
1219 }
1220 }
1221 off = noff;
1222 }
1170 line_list__free(&pf.lcache);
1223 line_list__free(&pf->lcache);
1171 dwarf_end(dbg);
1172
1224 dwarf_end(dbg);
1225
1173 return (ret < 0) ? ret : pf.ntevs;
1226 return ret;
1174}
1175
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;
1396}
1397
1176/* Reverse search */
1177int find_perf_probe_point(int fd, unsigned long addr,
1178 struct perf_probe_point *ppt)
1179{
1180 Dwarf_Die cudie, spdie, indie;
1181 Dwarf *dbg;
1182 Dwarf_Line *line;
1183 Dwarf_Addr laddr, eaddr;

--- 302 unchanged lines hidden ---
1398/* Reverse search */
1399int find_perf_probe_point(int fd, unsigned long addr,
1400 struct perf_probe_point *ppt)
1401{
1402 Dwarf_Die cudie, spdie, indie;
1403 Dwarf *dbg;
1404 Dwarf_Line *line;
1405 Dwarf_Addr laddr, eaddr;

--- 302 unchanged lines hidden ---