diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-10-27 16:43:19 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-29 03:47:49 -0400 |
commit | b0ef07324310d66f660a311d4a8d669eda74f801 (patch) | |
tree | 76ca8d6947e9238254fe8b5b7264ba51bd24d618 /tools/perf/util/probe-finder.c | |
parent | 253977b0d87fbb793f12b1661a763ae264028ccf (diff) |
perf/probes: Support function entry relative line number
Add function-entry relative line number specifying support to
perf-probe. This allows users to define probes by line number
from entry of the function.
e.g.
perf probe schedule:16
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jason Baron <jbaron@redhat.com>
Cc: K.Prasad <prasad@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
LKML-Reference: <20091027204319.30545.30678.stgit@harusame>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r-- | tools/perf/util/probe-finder.c | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 6d3bac9f947..db96186e02a 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -114,7 +114,7 @@ static int strtailcmp(const char *s1, const char *s2) | |||
114 | } | 114 | } |
115 | 115 | ||
116 | /* Find the fileno of the target file. */ | 116 | /* Find the fileno of the target file. */ |
117 | static Dwarf_Unsigned die_get_fileno(Dwarf_Die cu_die, const char *fname) | 117 | static Dwarf_Unsigned cu_find_fileno(Dwarf_Die cu_die, const char *fname) |
118 | { | 118 | { |
119 | Dwarf_Signed cnt, i; | 119 | Dwarf_Signed cnt, i; |
120 | Dwarf_Unsigned found = 0; | 120 | Dwarf_Unsigned found = 0; |
@@ -335,6 +335,36 @@ static int attr_get_locdesc(Dwarf_Attribute attr, Dwarf_Locdesc *desc, | |||
335 | return ret; | 335 | return ret; |
336 | } | 336 | } |
337 | 337 | ||
338 | /* Get decl_file attribute value (file number) */ | ||
339 | static Dwarf_Unsigned die_get_decl_file(Dwarf_Die sp_die) | ||
340 | { | ||
341 | Dwarf_Attribute attr; | ||
342 | Dwarf_Unsigned fno; | ||
343 | int ret; | ||
344 | |||
345 | ret = dwarf_attr(sp_die, DW_AT_decl_file, &attr, &__dw_error); | ||
346 | DIE_IF(ret != DW_DLV_OK); | ||
347 | dwarf_formudata(attr, &fno, &__dw_error); | ||
348 | DIE_IF(ret != DW_DLV_OK); | ||
349 | dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); | ||
350 | return fno; | ||
351 | } | ||
352 | |||
353 | /* Get decl_line attribute value (line number) */ | ||
354 | static Dwarf_Unsigned die_get_decl_line(Dwarf_Die sp_die) | ||
355 | { | ||
356 | Dwarf_Attribute attr; | ||
357 | Dwarf_Unsigned lno; | ||
358 | int ret; | ||
359 | |||
360 | ret = dwarf_attr(sp_die, DW_AT_decl_line, &attr, &__dw_error); | ||
361 | DIE_IF(ret != DW_DLV_OK); | ||
362 | dwarf_formudata(attr, &lno, &__dw_error); | ||
363 | DIE_IF(ret != DW_DLV_OK); | ||
364 | dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); | ||
365 | return lno; | ||
366 | } | ||
367 | |||
338 | /* | 368 | /* |
339 | * Probe finder related functions | 369 | * Probe finder related functions |
340 | */ | 370 | */ |
@@ -501,6 +531,7 @@ static void show_probepoint(Dwarf_Die sp_die, Dwarf_Signed offs, | |||
501 | DIE_IF(ret < 0); | 531 | DIE_IF(ret < 0); |
502 | DIE_IF(ret >= MAX_PROBE_BUFFER); | 532 | DIE_IF(ret >= MAX_PROBE_BUFFER); |
503 | len = ret; | 533 | len = ret; |
534 | pr_debug("Probe point found: %s\n", tmp); | ||
504 | 535 | ||
505 | /* Find each argument */ | 536 | /* Find each argument */ |
506 | get_current_frame_base(sp_die, pf); | 537 | get_current_frame_base(sp_die, pf); |
@@ -536,17 +567,16 @@ static int probeaddr_callback(struct die_link *dlink, void *data) | |||
536 | } | 567 | } |
537 | 568 | ||
538 | /* Find probe point from its line number */ | 569 | /* Find probe point from its line number */ |
539 | static void find_by_line(Dwarf_Die cu_die, struct probe_finder *pf) | 570 | static void find_by_line(struct probe_finder *pf) |
540 | { | 571 | { |
541 | struct probe_point *pp = pf->pp; | 572 | Dwarf_Signed cnt, i, clm; |
542 | Dwarf_Signed cnt, i; | ||
543 | Dwarf_Line *lines; | 573 | Dwarf_Line *lines; |
544 | Dwarf_Unsigned lineno = 0; | 574 | Dwarf_Unsigned lineno = 0; |
545 | Dwarf_Addr addr; | 575 | Dwarf_Addr addr; |
546 | Dwarf_Unsigned fno; | 576 | Dwarf_Unsigned fno; |
547 | int ret; | 577 | int ret; |
548 | 578 | ||
549 | ret = dwarf_srclines(cu_die, &lines, &cnt, &__dw_error); | 579 | ret = dwarf_srclines(pf->cu_die, &lines, &cnt, &__dw_error); |
550 | DIE_IF(ret != DW_DLV_OK); | 580 | DIE_IF(ret != DW_DLV_OK); |
551 | 581 | ||
552 | for (i = 0; i < cnt; i++) { | 582 | for (i = 0; i < cnt; i++) { |
@@ -557,15 +587,20 @@ static void find_by_line(Dwarf_Die cu_die, struct probe_finder *pf) | |||
557 | 587 | ||
558 | ret = dwarf_lineno(lines[i], &lineno, &__dw_error); | 588 | ret = dwarf_lineno(lines[i], &lineno, &__dw_error); |
559 | DIE_IF(ret != DW_DLV_OK); | 589 | DIE_IF(ret != DW_DLV_OK); |
560 | if (lineno != (Dwarf_Unsigned)pp->line) | 590 | if (lineno != pf->lno) |
561 | continue; | 591 | continue; |
562 | 592 | ||
593 | ret = dwarf_lineoff(lines[i], &clm, &__dw_error); | ||
594 | DIE_IF(ret != DW_DLV_OK); | ||
595 | |||
563 | ret = dwarf_lineaddr(lines[i], &addr, &__dw_error); | 596 | ret = dwarf_lineaddr(lines[i], &addr, &__dw_error); |
564 | DIE_IF(ret != DW_DLV_OK); | 597 | DIE_IF(ret != DW_DLV_OK); |
565 | pr_debug("Probe point found: 0x%llx\n", addr); | 598 | pr_debug("Probe line found: line[%d]:%u,%d addr:0x%llx\n", |
599 | (int)i, (unsigned)lineno, (int)clm, addr); | ||
566 | pf->addr = addr; | 600 | pf->addr = addr; |
567 | /* Search a real subprogram including this line, */ | 601 | /* Search a real subprogram including this line, */ |
568 | ret = search_die_from_children(cu_die, probeaddr_callback, pf); | 602 | ret = search_die_from_children(pf->cu_die, |
603 | probeaddr_callback, pf); | ||
569 | if (ret == 0) | 604 | if (ret == 0) |
570 | die("Probe point is not found in subprograms.\n"); | 605 | die("Probe point is not found in subprograms.\n"); |
571 | /* Continuing, because target line might be inlined. */ | 606 | /* Continuing, because target line might be inlined. */ |
@@ -587,6 +622,13 @@ static int probefunc_callback(struct die_link *dlink, void *data) | |||
587 | DIE_IF(ret == DW_DLV_ERROR); | 622 | DIE_IF(ret == DW_DLV_ERROR); |
588 | if (tag == DW_TAG_subprogram) { | 623 | if (tag == DW_TAG_subprogram) { |
589 | if (die_compare_name(dlink->die, pp->function) == 0) { | 624 | if (die_compare_name(dlink->die, pp->function) == 0) { |
625 | if (pp->line) { /* Function relative line */ | ||
626 | pf->fno = die_get_decl_file(dlink->die); | ||
627 | pf->lno = die_get_decl_line(dlink->die) | ||
628 | + pp->line; | ||
629 | find_by_line(pf); | ||
630 | return 1; | ||
631 | } | ||
590 | if (die_inlined_subprogram(dlink->die)) { | 632 | if (die_inlined_subprogram(dlink->die)) { |
591 | /* Inlined function, save it. */ | 633 | /* Inlined function, save it. */ |
592 | ret = dwarf_die_CU_offset(dlink->die, | 634 | ret = dwarf_die_CU_offset(dlink->die, |
@@ -631,9 +673,9 @@ found: | |||
631 | return 0; | 673 | return 0; |
632 | } | 674 | } |
633 | 675 | ||
634 | static void find_by_func(Dwarf_Die cu_die, struct probe_finder *pf) | 676 | static void find_by_func(struct probe_finder *pf) |
635 | { | 677 | { |
636 | search_die_from_children(cu_die, probefunc_callback, pf); | 678 | search_die_from_children(pf->cu_die, probefunc_callback, pf); |
637 | } | 679 | } |
638 | 680 | ||
639 | /* Find a probe point */ | 681 | /* Find a probe point */ |
@@ -641,7 +683,6 @@ int find_probepoint(int fd, struct probe_point *pp) | |||
641 | { | 683 | { |
642 | Dwarf_Half addr_size = 0; | 684 | Dwarf_Half addr_size = 0; |
643 | Dwarf_Unsigned next_cuh = 0; | 685 | Dwarf_Unsigned next_cuh = 0; |
644 | Dwarf_Die cu_die = 0; | ||
645 | int cu_number = 0, ret; | 686 | int cu_number = 0, ret; |
646 | struct probe_finder pf = {.pp = pp}; | 687 | struct probe_finder pf = {.pp = pp}; |
647 | 688 | ||
@@ -659,25 +700,27 @@ int find_probepoint(int fd, struct probe_point *pp) | |||
659 | break; | 700 | break; |
660 | 701 | ||
661 | /* Get the DIE(Debugging Information Entry) of this CU */ | 702 | /* Get the DIE(Debugging Information Entry) of this CU */ |
662 | ret = dwarf_siblingof(__dw_debug, 0, &cu_die, &__dw_error); | 703 | ret = dwarf_siblingof(__dw_debug, 0, &pf.cu_die, &__dw_error); |
663 | DIE_IF(ret != DW_DLV_OK); | 704 | DIE_IF(ret != DW_DLV_OK); |
664 | 705 | ||
665 | /* Check if target file is included. */ | 706 | /* Check if target file is included. */ |
666 | if (pp->file) | 707 | if (pp->file) |
667 | pf.fno = die_get_fileno(cu_die, pp->file); | 708 | pf.fno = cu_find_fileno(pf.cu_die, pp->file); |
668 | 709 | ||
669 | if (!pp->file || pf.fno) { | 710 | if (!pp->file || pf.fno) { |
670 | /* Save CU base address (for frame_base) */ | 711 | /* Save CU base address (for frame_base) */ |
671 | ret = dwarf_lowpc(cu_die, &pf.cu_base, &__dw_error); | 712 | ret = dwarf_lowpc(pf.cu_die, &pf.cu_base, &__dw_error); |
672 | DIE_IF(ret == DW_DLV_ERROR); | 713 | DIE_IF(ret == DW_DLV_ERROR); |
673 | if (ret == DW_DLV_NO_ENTRY) | 714 | if (ret == DW_DLV_NO_ENTRY) |
674 | pf.cu_base = 0; | 715 | pf.cu_base = 0; |
675 | if (pp->line) | ||
676 | find_by_line(cu_die, &pf); | ||
677 | if (pp->function) | 716 | if (pp->function) |
678 | find_by_func(cu_die, &pf); | 717 | find_by_func(&pf); |
718 | else { | ||
719 | pf.lno = pp->line; | ||
720 | find_by_line(&pf); | ||
721 | } | ||
679 | } | 722 | } |
680 | dwarf_dealloc(__dw_debug, cu_die, DW_DLA_DIE); | 723 | dwarf_dealloc(__dw_debug, pf.cu_die, DW_DLA_DIE); |
681 | } | 724 | } |
682 | ret = dwarf_finish(__dw_debug, &__dw_error); | 725 | ret = dwarf_finish(__dw_debug, &__dw_error); |
683 | DIE_IF(ret != DW_DLV_OK); | 726 | DIE_IF(ret != DW_DLV_OK); |