aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2009-10-27 16:43:19 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-29 03:47:49 -0400
commitb0ef07324310d66f660a311d4a8d669eda74f801 (patch)
tree76ca8d6947e9238254fe8b5b7264ba51bd24d618 /tools/perf/util/probe-finder.c
parent253977b0d87fbb793f12b1661a763ae264028ccf (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.c79
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. */
117static Dwarf_Unsigned die_get_fileno(Dwarf_Die cu_die, const char *fname) 117static 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) */
339static 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) */
354static 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 */
539static void find_by_line(Dwarf_Die cu_die, struct probe_finder *pf) 570static 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
634static void find_by_func(Dwarf_Die cu_die, struct probe_finder *pf) 676static 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);