diff options
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r-- | tools/perf/util/probe-finder.c | 248 |
1 files changed, 190 insertions, 58 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index d964cb199c67..840f1aabbb74 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "event.h" | 37 | #include "event.h" |
38 | #include "debug.h" | 38 | #include "debug.h" |
39 | #include "util.h" | 39 | #include "util.h" |
40 | #include "symbol.h" | ||
40 | #include "probe-finder.h" | 41 | #include "probe-finder.h" |
41 | 42 | ||
42 | /* Kprobe tracer basic type is up to u64 */ | 43 | /* Kprobe tracer basic type is up to u64 */ |
@@ -143,12 +144,21 @@ static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname) | |||
143 | return src; | 144 | return src; |
144 | } | 145 | } |
145 | 146 | ||
147 | /* Get DW_AT_comp_dir (should be NULL with older gcc) */ | ||
148 | static const char *cu_get_comp_dir(Dwarf_Die *cu_die) | ||
149 | { | ||
150 | Dwarf_Attribute attr; | ||
151 | if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL) | ||
152 | return NULL; | ||
153 | return dwarf_formstring(&attr); | ||
154 | } | ||
155 | |||
146 | /* Compare diename and tname */ | 156 | /* Compare diename and tname */ |
147 | static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) | 157 | static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) |
148 | { | 158 | { |
149 | const char *name; | 159 | const char *name; |
150 | name = dwarf_diename(dw_die); | 160 | name = dwarf_diename(dw_die); |
151 | return name ? strcmp(tname, name) : -1; | 161 | return name ? (strcmp(tname, name) == 0) : false; |
152 | } | 162 | } |
153 | 163 | ||
154 | /* Get type die, but skip qualifiers and typedef */ | 164 | /* Get type die, but skip qualifiers and typedef */ |
@@ -319,7 +329,7 @@ static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) | |||
319 | tag = dwarf_tag(die_mem); | 329 | tag = dwarf_tag(die_mem); |
320 | if ((tag == DW_TAG_formal_parameter || | 330 | if ((tag == DW_TAG_formal_parameter || |
321 | tag == DW_TAG_variable) && | 331 | tag == DW_TAG_variable) && |
322 | (die_compare_name(die_mem, name) == 0)) | 332 | die_compare_name(die_mem, name)) |
323 | return DIE_FIND_CB_FOUND; | 333 | return DIE_FIND_CB_FOUND; |
324 | 334 | ||
325 | return DIE_FIND_CB_CONTINUE; | 335 | return DIE_FIND_CB_CONTINUE; |
@@ -338,7 +348,7 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data) | |||
338 | const char *name = data; | 348 | const char *name = data; |
339 | 349 | ||
340 | if ((dwarf_tag(die_mem) == DW_TAG_member) && | 350 | if ((dwarf_tag(die_mem) == DW_TAG_member) && |
341 | (die_compare_name(die_mem, name) == 0)) | 351 | die_compare_name(die_mem, name)) |
342 | return DIE_FIND_CB_FOUND; | 352 | return DIE_FIND_CB_FOUND; |
343 | 353 | ||
344 | return DIE_FIND_CB_SIBLING; | 354 | return DIE_FIND_CB_SIBLING; |
@@ -356,14 +366,50 @@ static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, | |||
356 | * Probe finder related functions | 366 | * Probe finder related functions |
357 | */ | 367 | */ |
358 | 368 | ||
369 | static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs) | ||
370 | { | ||
371 | struct probe_trace_arg_ref *ref; | ||
372 | ref = zalloc(sizeof(struct probe_trace_arg_ref)); | ||
373 | if (ref != NULL) | ||
374 | ref->offset = offs; | ||
375 | return ref; | ||
376 | } | ||
377 | |||
359 | /* Show a location */ | 378 | /* Show a location */ |
360 | static int convert_location(Dwarf_Op *op, struct probe_finder *pf) | 379 | static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf) |
361 | { | 380 | { |
381 | Dwarf_Attribute attr; | ||
382 | Dwarf_Op *op; | ||
383 | size_t nops; | ||
362 | unsigned int regn; | 384 | unsigned int regn; |
363 | Dwarf_Word offs = 0; | 385 | Dwarf_Word offs = 0; |
364 | bool ref = false; | 386 | bool ref = false; |
365 | const char *regs; | 387 | const char *regs; |
366 | struct kprobe_trace_arg *tvar = pf->tvar; | 388 | struct probe_trace_arg *tvar = pf->tvar; |
389 | int ret; | ||
390 | |||
391 | /* TODO: handle more than 1 exprs */ | ||
392 | if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL || | ||
393 | dwarf_getlocation_addr(&attr, pf->addr, &op, &nops, 1) <= 0 || | ||
394 | nops == 0) { | ||
395 | /* TODO: Support const_value */ | ||
396 | pr_err("Failed to find the location of %s at this address.\n" | ||
397 | " Perhaps, it has been optimized out.\n", pf->pvar->var); | ||
398 | return -ENOENT; | ||
399 | } | ||
400 | |||
401 | if (op->atom == DW_OP_addr) { | ||
402 | /* Static variables on memory (not stack), make @varname */ | ||
403 | ret = strlen(dwarf_diename(vr_die)); | ||
404 | tvar->value = zalloc(ret + 2); | ||
405 | if (tvar->value == NULL) | ||
406 | return -ENOMEM; | ||
407 | snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die)); | ||
408 | tvar->ref = alloc_trace_arg_ref((long)offs); | ||
409 | if (tvar->ref == NULL) | ||
410 | return -ENOMEM; | ||
411 | return 0; | ||
412 | } | ||
367 | 413 | ||
368 | /* If this is based on frame buffer, set the offset */ | 414 | /* If this is based on frame buffer, set the offset */ |
369 | if (op->atom == DW_OP_fbreg) { | 415 | if (op->atom == DW_OP_fbreg) { |
@@ -405,27 +451,72 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf) | |||
405 | return -ENOMEM; | 451 | return -ENOMEM; |
406 | 452 | ||
407 | if (ref) { | 453 | if (ref) { |
408 | tvar->ref = zalloc(sizeof(struct kprobe_trace_arg_ref)); | 454 | tvar->ref = alloc_trace_arg_ref((long)offs); |
409 | if (tvar->ref == NULL) | 455 | if (tvar->ref == NULL) |
410 | return -ENOMEM; | 456 | return -ENOMEM; |
411 | tvar->ref->offset = (long)offs; | ||
412 | } | 457 | } |
413 | return 0; | 458 | return 0; |
414 | } | 459 | } |
415 | 460 | ||
416 | static int convert_variable_type(Dwarf_Die *vr_die, | 461 | static int convert_variable_type(Dwarf_Die *vr_die, |
417 | struct kprobe_trace_arg *targ) | 462 | struct probe_trace_arg *tvar, |
463 | const char *cast) | ||
418 | { | 464 | { |
465 | struct probe_trace_arg_ref **ref_ptr = &tvar->ref; | ||
419 | Dwarf_Die type; | 466 | Dwarf_Die type; |
420 | char buf[16]; | 467 | char buf[16]; |
421 | int ret; | 468 | int ret; |
422 | 469 | ||
470 | /* TODO: check all types */ | ||
471 | if (cast && strcmp(cast, "string") != 0) { | ||
472 | /* Non string type is OK */ | ||
473 | tvar->type = strdup(cast); | ||
474 | return (tvar->type == NULL) ? -ENOMEM : 0; | ||
475 | } | ||
476 | |||
423 | if (die_get_real_type(vr_die, &type) == NULL) { | 477 | if (die_get_real_type(vr_die, &type) == NULL) { |
424 | pr_warning("Failed to get a type information of %s.\n", | 478 | pr_warning("Failed to get a type information of %s.\n", |
425 | dwarf_diename(vr_die)); | 479 | dwarf_diename(vr_die)); |
426 | return -ENOENT; | 480 | return -ENOENT; |
427 | } | 481 | } |
428 | 482 | ||
483 | pr_debug("%s type is %s.\n", | ||
484 | dwarf_diename(vr_die), dwarf_diename(&type)); | ||
485 | |||
486 | if (cast && strcmp(cast, "string") == 0) { /* String type */ | ||
487 | ret = dwarf_tag(&type); | ||
488 | if (ret != DW_TAG_pointer_type && | ||
489 | ret != DW_TAG_array_type) { | ||
490 | pr_warning("Failed to cast into string: " | ||
491 | "%s(%s) is not a pointer nor array.", | ||
492 | dwarf_diename(vr_die), dwarf_diename(&type)); | ||
493 | return -EINVAL; | ||
494 | } | ||
495 | if (ret == DW_TAG_pointer_type) { | ||
496 | if (die_get_real_type(&type, &type) == NULL) { | ||
497 | pr_warning("Failed to get a type information."); | ||
498 | return -ENOENT; | ||
499 | } | ||
500 | while (*ref_ptr) | ||
501 | ref_ptr = &(*ref_ptr)->next; | ||
502 | /* Add new reference with offset +0 */ | ||
503 | *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref)); | ||
504 | if (*ref_ptr == NULL) { | ||
505 | pr_warning("Out of memory error\n"); | ||
506 | return -ENOMEM; | ||
507 | } | ||
508 | } | ||
509 | if (!die_compare_name(&type, "char") && | ||
510 | !die_compare_name(&type, "unsigned char")) { | ||
511 | pr_warning("Failed to cast into string: " | ||
512 | "%s is not (unsigned) char *.", | ||
513 | dwarf_diename(vr_die)); | ||
514 | return -EINVAL; | ||
515 | } | ||
516 | tvar->type = strdup(cast); | ||
517 | return (tvar->type == NULL) ? -ENOMEM : 0; | ||
518 | } | ||
519 | |||
429 | ret = die_get_byte_size(&type) * 8; | 520 | ret = die_get_byte_size(&type) * 8; |
430 | if (ret) { | 521 | if (ret) { |
431 | /* Check the bitwidth */ | 522 | /* Check the bitwidth */ |
@@ -445,8 +536,8 @@ static int convert_variable_type(Dwarf_Die *vr_die, | |||
445 | strerror(-ret)); | 536 | strerror(-ret)); |
446 | return ret; | 537 | return ret; |
447 | } | 538 | } |
448 | targ->type = strdup(buf); | 539 | tvar->type = strdup(buf); |
449 | if (targ->type == NULL) | 540 | if (tvar->type == NULL) |
450 | return -ENOMEM; | 541 | return -ENOMEM; |
451 | } | 542 | } |
452 | return 0; | 543 | return 0; |
@@ -454,22 +545,50 @@ static int convert_variable_type(Dwarf_Die *vr_die, | |||
454 | 545 | ||
455 | static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | 546 | static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, |
456 | struct perf_probe_arg_field *field, | 547 | struct perf_probe_arg_field *field, |
457 | struct kprobe_trace_arg_ref **ref_ptr, | 548 | struct probe_trace_arg_ref **ref_ptr, |
458 | Dwarf_Die *die_mem) | 549 | Dwarf_Die *die_mem) |
459 | { | 550 | { |
460 | struct kprobe_trace_arg_ref *ref = *ref_ptr; | 551 | struct probe_trace_arg_ref *ref = *ref_ptr; |
461 | Dwarf_Die type; | 552 | Dwarf_Die type; |
462 | Dwarf_Word offs; | 553 | Dwarf_Word offs; |
463 | int ret; | 554 | int ret, tag; |
464 | 555 | ||
465 | pr_debug("converting %s in %s\n", field->name, varname); | 556 | pr_debug("converting %s in %s\n", field->name, varname); |
466 | if (die_get_real_type(vr_die, &type) == NULL) { | 557 | if (die_get_real_type(vr_die, &type) == NULL) { |
467 | pr_warning("Failed to get the type of %s.\n", varname); | 558 | pr_warning("Failed to get the type of %s.\n", varname); |
468 | return -ENOENT; | 559 | return -ENOENT; |
469 | } | 560 | } |
470 | 561 | pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); | |
471 | /* Check the pointer and dereference */ | 562 | tag = dwarf_tag(&type); |
472 | if (dwarf_tag(&type) == DW_TAG_pointer_type) { | 563 | |
564 | if (field->name[0] == '[' && | ||
565 | (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { | ||
566 | if (field->next) | ||
567 | /* Save original type for next field */ | ||
568 | memcpy(die_mem, &type, sizeof(*die_mem)); | ||
569 | /* Get the type of this array */ | ||
570 | if (die_get_real_type(&type, &type) == NULL) { | ||
571 | pr_warning("Failed to get the type of %s.\n", varname); | ||
572 | return -ENOENT; | ||
573 | } | ||
574 | pr_debug2("Array real type: (%x)\n", | ||
575 | (unsigned)dwarf_dieoffset(&type)); | ||
576 | if (tag == DW_TAG_pointer_type) { | ||
577 | ref = zalloc(sizeof(struct probe_trace_arg_ref)); | ||
578 | if (ref == NULL) | ||
579 | return -ENOMEM; | ||
580 | if (*ref_ptr) | ||
581 | (*ref_ptr)->next = ref; | ||
582 | else | ||
583 | *ref_ptr = ref; | ||
584 | } | ||
585 | ref->offset += die_get_byte_size(&type) * field->index; | ||
586 | if (!field->next) | ||
587 | /* Save vr_die for converting types */ | ||
588 | memcpy(die_mem, vr_die, sizeof(*die_mem)); | ||
589 | goto next; | ||
590 | } else if (tag == DW_TAG_pointer_type) { | ||
591 | /* Check the pointer and dereference */ | ||
473 | if (!field->ref) { | 592 | if (!field->ref) { |
474 | pr_err("Semantic error: %s must be referred by '->'\n", | 593 | pr_err("Semantic error: %s must be referred by '->'\n", |
475 | field->name); | 594 | field->name); |
@@ -486,7 +605,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
486 | return -EINVAL; | 605 | return -EINVAL; |
487 | } | 606 | } |
488 | 607 | ||
489 | ref = zalloc(sizeof(struct kprobe_trace_arg_ref)); | 608 | ref = zalloc(sizeof(struct probe_trace_arg_ref)); |
490 | if (ref == NULL) | 609 | if (ref == NULL) |
491 | return -ENOMEM; | 610 | return -ENOMEM; |
492 | if (*ref_ptr) | 611 | if (*ref_ptr) |
@@ -495,10 +614,15 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
495 | *ref_ptr = ref; | 614 | *ref_ptr = ref; |
496 | } else { | 615 | } else { |
497 | /* Verify it is a data structure */ | 616 | /* Verify it is a data structure */ |
498 | if (dwarf_tag(&type) != DW_TAG_structure_type) { | 617 | if (tag != DW_TAG_structure_type) { |
499 | pr_warning("%s is not a data structure.\n", varname); | 618 | pr_warning("%s is not a data structure.\n", varname); |
500 | return -EINVAL; | 619 | return -EINVAL; |
501 | } | 620 | } |
621 | if (field->name[0] == '[') { | ||
622 | pr_err("Semantic error: %s is not a pointor nor array.", | ||
623 | varname); | ||
624 | return -EINVAL; | ||
625 | } | ||
502 | if (field->ref) { | 626 | if (field->ref) { |
503 | pr_err("Semantic error: %s must be referred by '.'\n", | 627 | pr_err("Semantic error: %s must be referred by '.'\n", |
504 | field->name); | 628 | field->name); |
@@ -525,6 +649,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
525 | } | 649 | } |
526 | ref->offset += (long)offs; | 650 | ref->offset += (long)offs; |
527 | 651 | ||
652 | next: | ||
528 | /* Converting next field */ | 653 | /* Converting next field */ |
529 | if (field->next) | 654 | if (field->next) |
530 | return convert_variable_fields(die_mem, field->name, | 655 | return convert_variable_fields(die_mem, field->name, |
@@ -536,51 +661,32 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
536 | /* Show a variables in kprobe event format */ | 661 | /* Show a variables in kprobe event format */ |
537 | static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) | 662 | static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) |
538 | { | 663 | { |
539 | Dwarf_Attribute attr; | ||
540 | Dwarf_Die die_mem; | 664 | Dwarf_Die die_mem; |
541 | Dwarf_Op *expr; | ||
542 | size_t nexpr; | ||
543 | int ret; | 665 | int ret; |
544 | 666 | ||
545 | if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) | 667 | pr_debug("Converting variable %s into trace event.\n", |
546 | goto error; | 668 | dwarf_diename(vr_die)); |
547 | /* TODO: handle more than 1 exprs */ | ||
548 | ret = dwarf_getlocation_addr(&attr, pf->addr, &expr, &nexpr, 1); | ||
549 | if (ret <= 0 || nexpr == 0) | ||
550 | goto error; | ||
551 | 669 | ||
552 | ret = convert_location(expr, pf); | 670 | ret = convert_variable_location(vr_die, pf); |
553 | if (ret == 0 && pf->pvar->field) { | 671 | if (ret == 0 && pf->pvar->field) { |
554 | ret = convert_variable_fields(vr_die, pf->pvar->var, | 672 | ret = convert_variable_fields(vr_die, pf->pvar->var, |
555 | pf->pvar->field, &pf->tvar->ref, | 673 | pf->pvar->field, &pf->tvar->ref, |
556 | &die_mem); | 674 | &die_mem); |
557 | vr_die = &die_mem; | 675 | vr_die = &die_mem; |
558 | } | 676 | } |
559 | if (ret == 0) { | 677 | if (ret == 0) |
560 | if (pf->pvar->type) { | 678 | ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type); |
561 | pf->tvar->type = strdup(pf->pvar->type); | ||
562 | if (pf->tvar->type == NULL) | ||
563 | ret = -ENOMEM; | ||
564 | } else | ||
565 | ret = convert_variable_type(vr_die, pf->tvar); | ||
566 | } | ||
567 | /* *expr will be cached in libdw. Don't free it. */ | 679 | /* *expr will be cached in libdw. Don't free it. */ |
568 | return ret; | 680 | return ret; |
569 | error: | ||
570 | /* TODO: Support const_value */ | ||
571 | pr_err("Failed to find the location of %s at this address.\n" | ||
572 | " Perhaps, it has been optimized out.\n", pf->pvar->var); | ||
573 | return -ENOENT; | ||
574 | } | 681 | } |
575 | 682 | ||
576 | /* Find a variable in a subprogram die */ | 683 | /* Find a variable in a subprogram die */ |
577 | static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) | 684 | static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) |
578 | { | 685 | { |
579 | Dwarf_Die vr_die; | 686 | Dwarf_Die vr_die, *scopes; |
580 | char buf[32], *ptr; | 687 | char buf[32], *ptr; |
581 | int ret; | 688 | int ret, nscopes; |
582 | 689 | ||
583 | /* TODO: Support arrays */ | ||
584 | if (pf->pvar->name) | 690 | if (pf->pvar->name) |
585 | pf->tvar->name = strdup(pf->pvar->name); | 691 | pf->tvar->name = strdup(pf->pvar->name); |
586 | else { | 692 | else { |
@@ -607,18 +713,32 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) | |||
607 | pr_debug("Searching '%s' variable in context.\n", | 713 | pr_debug("Searching '%s' variable in context.\n", |
608 | pf->pvar->var); | 714 | pf->pvar->var); |
609 | /* Search child die for local variables and parameters. */ | 715 | /* Search child die for local variables and parameters. */ |
610 | if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) { | 716 | if (die_find_variable(sp_die, pf->pvar->var, &vr_die)) |
717 | ret = convert_variable(&vr_die, pf); | ||
718 | else { | ||
719 | /* Search upper class */ | ||
720 | nscopes = dwarf_getscopes_die(sp_die, &scopes); | ||
721 | if (nscopes > 0) { | ||
722 | ret = dwarf_getscopevar(scopes, nscopes, pf->pvar->var, | ||
723 | 0, NULL, 0, 0, &vr_die); | ||
724 | if (ret >= 0) | ||
725 | ret = convert_variable(&vr_die, pf); | ||
726 | else | ||
727 | ret = -ENOENT; | ||
728 | free(scopes); | ||
729 | } else | ||
730 | ret = -ENOENT; | ||
731 | } | ||
732 | if (ret < 0) | ||
611 | pr_warning("Failed to find '%s' in this function.\n", | 733 | pr_warning("Failed to find '%s' in this function.\n", |
612 | pf->pvar->var); | 734 | pf->pvar->var); |
613 | return -ENOENT; | 735 | return ret; |
614 | } | ||
615 | return convert_variable(&vr_die, pf); | ||
616 | } | 736 | } |
617 | 737 | ||
618 | /* Show a probe point to output buffer */ | 738 | /* Show a probe point to output buffer */ |
619 | static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) | 739 | static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) |
620 | { | 740 | { |
621 | struct kprobe_trace_event *tev; | 741 | struct probe_trace_event *tev; |
622 | Dwarf_Addr eaddr; | 742 | Dwarf_Addr eaddr; |
623 | Dwarf_Die die_mem; | 743 | Dwarf_Die die_mem; |
624 | const char *name; | 744 | const char *name; |
@@ -683,7 +803,7 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) | |||
683 | 803 | ||
684 | /* Find each argument */ | 804 | /* Find each argument */ |
685 | tev->nargs = pf->pev->nargs; | 805 | tev->nargs = pf->pev->nargs; |
686 | tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); | 806 | tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); |
687 | if (tev->args == NULL) | 807 | if (tev->args == NULL) |
688 | return -ENOMEM; | 808 | return -ENOMEM; |
689 | for (i = 0; i < pf->pev->nargs; i++) { | 809 | for (i = 0; i < pf->pev->nargs; i++) { |
@@ -897,7 +1017,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) | |||
897 | 1017 | ||
898 | /* Check tag and diename */ | 1018 | /* Check tag and diename */ |
899 | if (dwarf_tag(sp_die) != DW_TAG_subprogram || | 1019 | if (dwarf_tag(sp_die) != DW_TAG_subprogram || |
900 | die_compare_name(sp_die, pp->function) != 0) | 1020 | !die_compare_name(sp_die, pp->function)) |
901 | return DWARF_CB_OK; | 1021 | return DWARF_CB_OK; |
902 | 1022 | ||
903 | pf->fname = dwarf_decl_file(sp_die); | 1023 | pf->fname = dwarf_decl_file(sp_die); |
@@ -940,9 +1060,9 @@ static int find_probe_point_by_func(struct probe_finder *pf) | |||
940 | return _param.retval; | 1060 | return _param.retval; |
941 | } | 1061 | } |
942 | 1062 | ||
943 | /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ | 1063 | /* Find probe_trace_events specified by perf_probe_event from debuginfo */ |
944 | int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, | 1064 | int find_probe_trace_events(int fd, struct perf_probe_event *pev, |
945 | struct kprobe_trace_event **tevs, int max_tevs) | 1065 | struct probe_trace_event **tevs, int max_tevs) |
946 | { | 1066 | { |
947 | struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs}; | 1067 | struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs}; |
948 | struct perf_probe_point *pp = &pev->point; | 1068 | struct perf_probe_point *pp = &pev->point; |
@@ -952,7 +1072,7 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, | |||
952 | Dwarf *dbg; | 1072 | Dwarf *dbg; |
953 | int ret = 0; | 1073 | int ret = 0; |
954 | 1074 | ||
955 | pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * max_tevs); | 1075 | pf.tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs); |
956 | if (pf.tevs == NULL) | 1076 | if (pf.tevs == NULL) |
957 | return -ENOMEM; | 1077 | return -ENOMEM; |
958 | *tevs = pf.tevs; | 1078 | *tevs = pf.tevs; |
@@ -1096,7 +1216,7 @@ end: | |||
1096 | static int line_range_add_line(const char *src, unsigned int lineno, | 1216 | static int line_range_add_line(const char *src, unsigned int lineno, |
1097 | struct line_range *lr) | 1217 | struct line_range *lr) |
1098 | { | 1218 | { |
1099 | /* Copy real path */ | 1219 | /* Copy source path */ |
1100 | if (!lr->path) { | 1220 | if (!lr->path) { |
1101 | lr->path = strdup(src); | 1221 | lr->path = strdup(src); |
1102 | if (lr->path == NULL) | 1222 | if (lr->path == NULL) |
@@ -1220,7 +1340,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) | |||
1220 | struct line_range *lr = lf->lr; | 1340 | struct line_range *lr = lf->lr; |
1221 | 1341 | ||
1222 | if (dwarf_tag(sp_die) == DW_TAG_subprogram && | 1342 | if (dwarf_tag(sp_die) == DW_TAG_subprogram && |
1223 | die_compare_name(sp_die, lr->function) == 0) { | 1343 | die_compare_name(sp_die, lr->function)) { |
1224 | lf->fname = dwarf_decl_file(sp_die); | 1344 | lf->fname = dwarf_decl_file(sp_die); |
1225 | dwarf_decl_line(sp_die, &lr->offset); | 1345 | dwarf_decl_line(sp_die, &lr->offset); |
1226 | pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); | 1346 | pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); |
@@ -1263,6 +1383,7 @@ int find_line_range(int fd, struct line_range *lr) | |||
1263 | size_t cuhl; | 1383 | size_t cuhl; |
1264 | Dwarf_Die *diep; | 1384 | Dwarf_Die *diep; |
1265 | Dwarf *dbg; | 1385 | Dwarf *dbg; |
1386 | const char *comp_dir; | ||
1266 | 1387 | ||
1267 | dbg = dwarf_begin(fd, DWARF_C_READ); | 1388 | dbg = dwarf_begin(fd, DWARF_C_READ); |
1268 | if (!dbg) { | 1389 | if (!dbg) { |
@@ -1298,7 +1419,18 @@ int find_line_range(int fd, struct line_range *lr) | |||
1298 | } | 1419 | } |
1299 | off = noff; | 1420 | off = noff; |
1300 | } | 1421 | } |
1301 | pr_debug("path: %lx\n", (unsigned long)lr->path); | 1422 | |
1423 | /* Store comp_dir */ | ||
1424 | if (lf.found) { | ||
1425 | comp_dir = cu_get_comp_dir(&lf.cu_die); | ||
1426 | if (comp_dir) { | ||
1427 | lr->comp_dir = strdup(comp_dir); | ||
1428 | if (!lr->comp_dir) | ||
1429 | ret = -ENOMEM; | ||
1430 | } | ||
1431 | } | ||
1432 | |||
1433 | pr_debug("path: %s\n", lr->path); | ||
1302 | dwarf_end(dbg); | 1434 | dwarf_end(dbg); |
1303 | 1435 | ||
1304 | return (ret < 0) ? ret : lf.found; | 1436 | return (ret < 0) ? ret : lf.found; |