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