Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1470968 > unrolled thread

Re: [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled without optimization

Started byArnaldo Carvalho de Melo <acme@kernel.org>
First post2016-08-26 21:50 +0200
Last post2016-08-29 10:10 +0200
Articles 10 — 4 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled  without optimization Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-08-26 21:50 +0200
    Re: [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled  without optimization Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-08-26 22:10 +0200
      Re: [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled  without optimization Masami Hiramatsu <mhiramat@kernel.org> - 2016-08-27 02:30 +0200
        [PATCH] perf probe: Move dwarf specific functions to dwarf-aux.c Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> - 2016-08-29 17:20 +0200
          Re: [PATCH] perf probe: Move dwarf specific functions to  dwarf-aux.c Masami Hiramatsu <mhiramat@kernel.org> - 2016-08-30 01:00 +0200
            [PATCH v2] perf probe: Move dwarf specific functions to dwarf-aux.c Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> - 2016-08-30 10:50 +0200
              Re: [PATCH v2] perf probe: Move dwarf specific functions to  dwarf-aux.c Masami Hiramatsu <mhiramat@kernel.org> - 2016-08-30 16:30 +0200
              [tip:perf/core] perf probe: Move dwarf specific functions to  dwarf-aux.c tip-bot for Ravi Bangoria <tipbot@zytor.com> - 2016-09-05 15:30 +0200
      Re: [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled  without optimization Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> - 2016-08-29 10:10 +0200
    Re: [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled  without optimization Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> - 2016-08-29 10:10 +0200

#1470968 — Re: [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled without optimization

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2016-08-26 21:50 +0200
SubjectRe: [PATCH v2 2/2] perf uprobe: Skip prologue if program compiled without optimization
Message-ID<saviy-2VG-25@gated-at.bofh.it>
Em Wed, Aug 03, 2016 at 02:28:45PM +0530, Ravi Bangoria escreveu:
> +++ b/tools/perf/util/probe-finder.c
> @@ -892,6 +892,169 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
>  	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
>  }
  
> +static bool var_has_loclist(Dwarf_Die *die)

So, the variable 'die' cause the build to fail in multiple systems, I'm
renaming it to 'cu_die', there are some more problems when cross compiling it
to some arches, I'm trying to fix them all now:

[root@jouet ~]# dm
 1 65.668882867 alpine:3.4: Ok
 2 24.327143744 android-ndk:r12b-arm: Ok
 3 76.000455817 archlinux:latest: Ok
 4 40.905282317 centos:5: Ok
 5 28.799284950 centos:6: FAIL
cc1: warnings being treated as errors
util/probe-finder.c: In function 'var_has_loclist':
util/probe-finder.c:904: error: declaration of 'die' shadows a global declaration
util/util.h:137: error: shadowed declaration is here
util/probe-finder.c: In function 'optimized_target':
util/probe-finder.c:921: error: declaration of 'die' shadows a global declaration
util/util.h:137: error: shadowed declaration is here
-----------------------------------------------------------------------------
 6 68.157498673 centos:7: Ok
 7 32.814597820 debian:7: FAIL
util/probe-finder.c: In function 'var_has_loclist':
util/probe-finder.c:904:40: error: declaration of 'die' shadows a global declaration [-Werror=shadow]
In file included from util/probe-finder.c:39:0:
util/util.h:137:6: error: shadowed declaration is here [-Werror=shadow]
util/probe-finder.c: In function 'optimized_target':
util/probe-finder.c:921:41: error: declaration of 'die' shadows a global declaration [-Werror=shadow]
In file included from util/probe-finder.c:39:0:
util/util.h:137:6: error: shadowed declaration is here [-Werror=shadow]
-----------------------------------------------------------------------------
 8 69.535114125 debian:8: Ok
 9 71.524733936 debian:experimental: Ok
10 66.956671932 fedora:20: Ok
11 72.127804972 fedora:21: Ok
12 75.767022465 fedora:22: Ok
13 72.244964710 fedora:23: Ok
14 75.556712624 fedora:24: Ok
15 30.825802615 fedora:24-x-ARC-uClibc: Ok
16 76.874903316 fedora:rawhide: Ok
17 76.756388879 mageia:5: Ok
18 71.700493646 opensuse:13.2: Ok
19 69.974649379 opensuse:42.1: Ok
20 75.265305896 opensuse:tumbleweed: Ok
21 28.800283739 ubuntu:12.04.5: FAIL
util/probe-finder.c: In function 'var_has_loclist':
util/probe-finder.c:904:40: error: declaration of 'die' shadows a global declaration [-Werror=shadow]
util/util.h:137:6: error: shadowed declaration is here [-Werror=shadow]
util/probe-finder.c: In function 'optimized_target':
util/probe-finder.c:921:41: error: declaration of 'die' shadows a global declaration [-Werror=shadow]
util/util.h:137:6: error: shadowed declaration is here [-Werror=shadow]
-----------------------------------------------------------------------------
22 66.514504455 ubuntu:14.04.4: Ok
23 69.100413367 ubuntu:15.10: Ok
24 64.414190947 ubuntu:16.04: Ok
25 29.481652689 ubuntu:16.04-x-arm: FAIL
util/probe-finder.c: In function '__skip_prologue':
util/probe-finder.c:1022:45: error: passing argument 3 of 'dwarf_getsrclines' from incompatible pointer type [-Werror=incompatible-pointer-types]
  if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
                                             ^
In file included from util/dwarf-aux.h:23:0,
                 from util/probe-finder.h:24,
                 from util/probe-finder.c:41:
/usr/arm-linux-gnueabihf/include/elfutils/libdw.h:592:12: note: expected 'size_t * {aka unsigned int *}' but argument is of type 'long unsigned int *'
 extern int dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines,
            ^
In file included from util/probe-finder.c:37:0:
util/probe-finder.c: In function 'skip_prologue':
util/probe-finder.c:1060:10: error: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'Dwarf_Addr {aka long long unsigned int}' [-Werror=format=]
  pr_info("Target program is compiled without optimization. Skipping prologue.\n"
          ^
util/debug.h:18:21: note: in definition of macro 'pr_fmt'
 #define pr_fmt(fmt) fmt
                     ^
util/probe-finder.c:1060:2: note: in expansion of macro 'pr_info'
  pr_info("Target program is compiled without optimization. Skipping prologue.\n"
  ^
-----------------------------------------------------------------------------
26 51.979875334 ubuntu:16.04-x-arm64: Ok
27 28.808591224 ubuntu:16.04-x-powerpc64: FAIL
  CC       /tmp/build/perf/tests/bp_signal.o
util/probe-finder.c: In function '__skip_prologue':
util/probe-finder.c:1022:45: error: passing argument 3 of 'dwarf_getsrclines' from incompatible pointer type [-Werror=incompatible-pointer-types]
  if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
                                             ^
In file included from util/dwarf-aux.h:23:0,
                 from util/probe-finder.h:24,
                 from util/probe-finder.c:41:
/usr/powerpc-linux-gnu/include/elfutils/libdw.h:592:12: note: expected 'size_t * {aka unsigned int *}' but argument is of type 'long unsigned int *'
 extern int dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines,
            ^
In file included from util/probe-finder.c:37:0:
util/probe-finder.c: In function 'skip_prologue':
util/probe-finder.c:1060:10: error: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'Dwarf_Addr {aka long long unsigned int}' [-Werror=format=]
  pr_info("Target program is compiled without optimization. Skipping prologue.\n"
          ^
util/debug.h:18:21: note: in definition of macro 'pr_fmt'
 #define pr_fmt(fmt) fmt
                     ^
util/probe-finder.c:1060:2: note: in expansion of macro 'pr_info'
-----------------------------------------------------------------------------
28 53.372615706 ubuntu:16.04-x-powerpc64el: Ok
29 71.550573752 ubuntu:16.10: Ok
30 52.727886240 ubuntu:16.10-x-s390: Ok

[toc] | [next] | [standalone]


#1470974

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2016-08-26 22:10 +0200
Message-ID<savBT-3hs-1@gated-at.bofh.it>
In reply to#1470968
Em Fri, Aug 26, 2016 at 04:30:27PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Wed, Aug 03, 2016 at 02:28:45PM +0530, Ravi Bangoria escreveu:
> > +++ b/tools/perf/util/probe-finder.c
> > @@ -892,6 +892,169 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
> >  	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
> >  }
>   
> > +static bool var_has_loclist(Dwarf_Die *die)
> 
> So, the variable 'die' cause the build to fail in multiple systems, I'm
> renaming it to 'cu_die', there are some more problems when cross compiling it
> to some arches, I'm trying to fix them all now:

Fixed, please check:

http://git.kernel.org/cgit/linux/kernel/git/acme/linux.git/commit/?h=perf/urgent&id=3866e3762da3291613dfb8b193885a8ed3836669

- Arnaldo

[toc] | [prev] | [next] | [standalone]


#1471052

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-08-27 02:30 +0200
Message-ID<sazFv-5RO-9@gated-at.bofh.it>
In reply to#1470974
On Fri, 26 Aug 2016 16:54:52 -0300
Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> Em Fri, Aug 26, 2016 at 04:30:27PM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Wed, Aug 03, 2016 at 02:28:45PM +0530, Ravi Bangoria escreveu:
> > > +++ b/tools/perf/util/probe-finder.c
> > > @@ -892,6 +892,169 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
> > >  	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
> > >  }
> >   
> > > +static bool var_has_loclist(Dwarf_Die *die)
> > 
> > So, the variable 'die' cause the build to fail in multiple systems, I'm
> > renaming it to 'cu_die', there are some more problems when cross compiling it
> > to some arches, I'm trying to fix them all now:
> 
> Fixed, please check:
> 
> http://git.kernel.org/cgit/linux/kernel/git/acme/linux.git/commit/?h=perf/urgent&id=3866e3762da3291613dfb8b193885a8ed3836669

Hmm I think var_has_loclist(cu_die) should be vr_die(means Variable DIE) not
cu_die (Compile Unit DIE == object file itself) since user must pass the
DIE for local variable. And revisiting on the code, it seems this has several
generic dwarf related functions, which can be put into dwarf-aux.c/.h as
other APIs. 
But anyway it is a trivial & cleanup thing.

At first we should fix this bug for helping users ASAP. So I'm OK.

Thank you!

-- 
Masami Hiramatsu <mhiramat@kernel.org>

[toc] | [prev] | [next] | [standalone]


#1471915 — [PATCH] perf probe: Move dwarf specific functions to dwarf-aux.c

FromRavi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Date2016-08-29 17:20 +0200
Subject[PATCH] perf probe: Move dwarf specific functions to dwarf-aux.c
Message-ID<sbwvT-v8-23@gated-at.bofh.it>
In reply to#1471052
Move generic dwarf related functions from util/probe-finder.c to
util/dwarf-aux.c. Function names and their prototype are also
changed accordingly. No functionality changes.

Suggested-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
 tools/perf/util/dwarf-aux.c    | 135 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/dwarf-aux.h    |   5 ++
 tools/perf/util/probe-finder.c | 136 +----------------------------------------
 3 files changed, 142 insertions(+), 134 deletions(-)

diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index a347b19..8d595b9 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -1085,3 +1085,138 @@ int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
 	return -ENOTSUP;
 }
 #endif
+
+static bool die_has_loclist(Dwarf_Die *var_die)
+{
+	Dwarf_Attribute loc;
+	int tag = dwarf_tag(var_die);
+
+	if (tag != DW_TAG_formal_parameter &&
+	    tag != DW_TAG_variable)
+		return false;
+
+	return (dwarf_attr_integrate(var_die, DW_AT_location, &loc) &&
+		dwarf_whatform(&loc) == DW_FORM_sec_offset);
+}
+
+/*
+ * For any object in given CU whose DW_AT_location is a location list,
+ * target program is compiled with optimization.
+ */
+bool die_is_optimized_target(Dwarf_Die *cu_die)
+{
+	Dwarf_Die tmp_die;
+
+	if (die_has_loclist(cu_die))
+		return true;
+
+	if (!dwarf_child(cu_die, &tmp_die) &&
+	    die_is_optimized_target(&tmp_die))
+		return true;
+
+	if (!dwarf_siblingof(cu_die, &tmp_die) &&
+	    die_is_optimized_target(&tmp_die))
+		return true;
+
+	return false;
+}
+
+static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
+			   Dwarf_Addr pf_addr, unsigned long *idx)
+{
+	unsigned long i;
+	Dwarf_Addr addr;
+
+	for (i = 0; i < nr_lines; i++) {
+		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &addr))
+			return false;
+
+		if (addr == pf_addr) {
+			*idx = i;
+			return true;
+		}
+	}
+	return false;
+}
+
+static bool die_get_postprologue_addr(unsigned long entrypc_idx,
+				      Dwarf_Lines *lines,
+				      unsigned long nr_lines,
+				      Dwarf_Addr highpc,
+				      Dwarf_Addr *postprologue_addr)
+{
+	unsigned long i;
+	int entrypc_lno, lno;
+	Dwarf_Line *line;
+	Dwarf_Addr addr;
+	bool p_end;
+
+	/* entrypc_lno is actual source line number */
+	line = dwarf_onesrcline(lines, entrypc_idx);
+	if (dwarf_lineno(line, &entrypc_lno))
+		return false;
+
+	for (i = entrypc_idx; i < nr_lines; i++) {
+		line = dwarf_onesrcline(lines, i);
+
+		if (dwarf_lineaddr(line, &addr) ||
+		    dwarf_lineno(line, &lno)    ||
+		    dwarf_lineprologueend(line, &p_end))
+			return false;
+
+		/* highpc is exclusive. [entrypc,highpc) */
+		if (addr >= highpc)
+			break;
+
+		/* clang supports prologue-end marker */
+		if (p_end)
+			break;
+
+		/* Actual next line in source */
+		if (lno != entrypc_lno)
+			break;
+
+		/*
+		 * Single source line can have multiple line records.
+		 * For Example,
+		 *     void foo() { printf("hello\n"); }
+		 * contains two line records. One points to declaration and
+		 * other points to printf() line. Variable 'lno' won't get
+		 * incremented in this case but 'i' will.
+		 */
+		if (i != entrypc_idx)
+			break;
+	}
+
+	dwarf_lineaddr(line, postprologue_addr);
+	if (*postprologue_addr >= highpc)
+		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
+			       postprologue_addr);
+
+	return true;
+}
+
+void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
+		       Dwarf_Addr *entrypc)
+{
+	size_t nr_lines = 0;
+	unsigned long entrypc_idx = 0;
+	Dwarf_Lines *lines = NULL;
+	Dwarf_Addr postprologue_addr;
+	Dwarf_Addr highpc;
+
+	if (dwarf_highpc(sp_die, &highpc))
+		return;
+
+	if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
+		return;
+
+	if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
+		return;
+
+	if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
+				       highpc, &postprologue_addr))
+		return;
+
+	*entrypc = postprologue_addr;
+}
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index dc0ce1a..791884a 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -125,4 +125,9 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
 /* Get the name and type of given variable DIE, stored as "type\tname" */
 int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
 int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);
+
+bool die_is_optimized_target(Dwarf_Die *cu_die);
+void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
+		       Dwarf_Addr *entrypc);
+
 #endif
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 945cf7a..72f1152 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -901,138 +901,6 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
 	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
 }
 
-static bool var_has_loclist(Dwarf_Die *cu_die)
-{
-	Dwarf_Attribute loc;
-	int tag = dwarf_tag(cu_die);
-
-	if (tag != DW_TAG_formal_parameter &&
-	    tag != DW_TAG_variable)
-		return false;
-
-	return (dwarf_attr_integrate(cu_die, DW_AT_location, &loc) &&
-		dwarf_whatform(&loc) == DW_FORM_sec_offset);
-}
-
-/*
- * For any object in given CU whose DW_AT_location is a location list,
- * target program is compiled with optimization.
- */
-static bool optimized_target(Dwarf_Die *cu_die)
-{
-	Dwarf_Die tmp_die;
-
-	if (var_has_loclist(cu_die))
-		return true;
-
-	if (!dwarf_child(cu_die, &tmp_die) && optimized_target(&tmp_die))
-		return true;
-
-	if (!dwarf_siblingof(cu_die, &tmp_die) && optimized_target(&tmp_die))
-		return true;
-
-	return false;
-}
-
-static bool get_entrypc_idx(Dwarf_Lines *lines, unsigned long nr_lines,
-			    Dwarf_Addr pf_addr, unsigned long *entrypc_idx)
-{
-	unsigned long i;
-	Dwarf_Addr addr;
-
-	for (i = 0; i < nr_lines; i++) {
-		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &addr))
-			return false;
-
-		if (addr == pf_addr) {
-			*entrypc_idx = i;
-			return true;
-		}
-	}
-	return false;
-}
-
-static bool get_postprologue_addr(unsigned long entrypc_idx,
-				  Dwarf_Lines *lines,
-				  unsigned long nr_lines,
-				  Dwarf_Addr highpc,
-				  Dwarf_Addr *postprologue_addr)
-{
-	unsigned long i;
-	int entrypc_lno, lno;
-	Dwarf_Line *line;
-	Dwarf_Addr addr;
-	bool p_end;
-
-	/* entrypc_lno is actual source line number */
-	line = dwarf_onesrcline(lines, entrypc_idx);
-	if (dwarf_lineno(line, &entrypc_lno))
-		return false;
-
-	for (i = entrypc_idx; i < nr_lines; i++) {
-		line = dwarf_onesrcline(lines, i);
-
-		if (dwarf_lineaddr(line, &addr) ||
-		    dwarf_lineno(line, &lno)    ||
-		    dwarf_lineprologueend(line, &p_end))
-			return false;
-
-		/* highpc is exclusive. [entrypc,highpc) */
-		if (addr >= highpc)
-			break;
-
-		/* clang supports prologue-end marker */
-		if (p_end)
-			break;
-
-		/* Actual next line in source */
-		if (lno != entrypc_lno)
-			break;
-
-		/*
-		 * Single source line can have multiple line records.
-		 * For Example,
-		 *     void foo() { printf("hello\n"); }
-		 * contains two line records. One points to declaration and
-		 * other points to printf() line. Variable 'lno' won't get
-		 * incremented in this case but 'i' will.
-		 */
-		if (i != entrypc_idx)
-			break;
-	}
-
-	dwarf_lineaddr(line, postprologue_addr);
-	if (*postprologue_addr >= highpc)
-		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
-			       postprologue_addr);
-
-	return true;
-}
-
-static void __skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
-{
-	size_t nr_lines = 0;
-	unsigned long entrypc_idx = 0;
-	Dwarf_Lines *lines = NULL;
-	Dwarf_Addr postprologue_addr;
-	Dwarf_Addr highpc;
-
-	if (dwarf_highpc(sp_die, &highpc))
-		return;
-
-	if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
-		return;
-
-	if (!get_entrypc_idx(lines, nr_lines, pf->addr, &entrypc_idx))
-		return;
-
-	if (!get_postprologue_addr(entrypc_idx, lines, nr_lines,
-				   highpc, &postprologue_addr))
-		return;
-
-	pf->addr = postprologue_addr;
-}
-
 static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
 	struct perf_probe_point *pp = &pf->pev->point;
@@ -1042,7 +910,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 		return;
 
 	/* Compiled with optimization? */
-	if (optimized_target(&pf->cu_die))
+	if (die_is_optimized_target(&pf->cu_die))
 		return;
 
 	/* Don't know entrypc? */
@@ -1062,7 +930,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 		"Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
 		pf->addr);
 
-	__skip_prologue(sp_die, pf);
+	die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
 }
 
 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1472151 — Re: [PATCH] perf probe: Move dwarf specific functions to dwarf-aux.c

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-08-30 01:00 +0200
SubjectRe: [PATCH] perf probe: Move dwarf specific functions to dwarf-aux.c
Message-ID<sbDH3-4VF-7@gated-at.bofh.it>
In reply to#1471915
On Mon, 29 Aug 2016 20:40:01 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> Move generic dwarf related functions from util/probe-finder.c to
> util/dwarf-aux.c. Function names and their prototype are also
> changed accordingly. No functionality changes.

Code looks OK, could you please add usage comments as same as
other functions, and one-line comments for prototypes?

Thanks,

> 
> Suggested-by: Masami Hiramatsu <mhiramat@kernel.org>
> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> ---
>  tools/perf/util/dwarf-aux.c    | 135 ++++++++++++++++++++++++++++++++++++++++
>  tools/perf/util/dwarf-aux.h    |   5 ++
>  tools/perf/util/probe-finder.c | 136 +----------------------------------------
>  3 files changed, 142 insertions(+), 134 deletions(-)
> 
> diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
> index a347b19..8d595b9 100644
> --- a/tools/perf/util/dwarf-aux.c
> +++ b/tools/perf/util/dwarf-aux.c
> @@ -1085,3 +1085,138 @@ int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
>  	return -ENOTSUP;
>  }
>  #endif
> +
> +static bool die_has_loclist(Dwarf_Die *var_die)
> +{
> +	Dwarf_Attribute loc;
> +	int tag = dwarf_tag(var_die);
> +
> +	if (tag != DW_TAG_formal_parameter &&
> +	    tag != DW_TAG_variable)
> +		return false;
> +
> +	return (dwarf_attr_integrate(var_die, DW_AT_location, &loc) &&
> +		dwarf_whatform(&loc) == DW_FORM_sec_offset);
> +}
> +
> +/*
> + * For any object in given CU whose DW_AT_location is a location list,
> + * target program is compiled with optimization.
> + */
> +bool die_is_optimized_target(Dwarf_Die *cu_die)
> +{
> +	Dwarf_Die tmp_die;
> +
> +	if (die_has_loclist(cu_die))
> +		return true;
> +
> +	if (!dwarf_child(cu_die, &tmp_die) &&
> +	    die_is_optimized_target(&tmp_die))
> +		return true;
> +
> +	if (!dwarf_siblingof(cu_die, &tmp_die) &&
> +	    die_is_optimized_target(&tmp_die))
> +		return true;
> +
> +	return false;
> +}
> +
> +static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
> +			   Dwarf_Addr pf_addr, unsigned long *idx)
> +{
> +	unsigned long i;
> +	Dwarf_Addr addr;
> +
> +	for (i = 0; i < nr_lines; i++) {
> +		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &addr))
> +			return false;
> +
> +		if (addr == pf_addr) {
> +			*idx = i;
> +			return true;
> +		}
> +	}
> +	return false;
> +}
> +
> +static bool die_get_postprologue_addr(unsigned long entrypc_idx,
> +				      Dwarf_Lines *lines,
> +				      unsigned long nr_lines,
> +				      Dwarf_Addr highpc,
> +				      Dwarf_Addr *postprologue_addr)
> +{
> +	unsigned long i;
> +	int entrypc_lno, lno;
> +	Dwarf_Line *line;
> +	Dwarf_Addr addr;
> +	bool p_end;
> +
> +	/* entrypc_lno is actual source line number */
> +	line = dwarf_onesrcline(lines, entrypc_idx);
> +	if (dwarf_lineno(line, &entrypc_lno))
> +		return false;
> +
> +	for (i = entrypc_idx; i < nr_lines; i++) {
> +		line = dwarf_onesrcline(lines, i);
> +
> +		if (dwarf_lineaddr(line, &addr) ||
> +		    dwarf_lineno(line, &lno)    ||
> +		    dwarf_lineprologueend(line, &p_end))
> +			return false;
> +
> +		/* highpc is exclusive. [entrypc,highpc) */
> +		if (addr >= highpc)
> +			break;
> +
> +		/* clang supports prologue-end marker */
> +		if (p_end)
> +			break;
> +
> +		/* Actual next line in source */
> +		if (lno != entrypc_lno)
> +			break;
> +
> +		/*
> +		 * Single source line can have multiple line records.
> +		 * For Example,
> +		 *     void foo() { printf("hello\n"); }
> +		 * contains two line records. One points to declaration and
> +		 * other points to printf() line. Variable 'lno' won't get
> +		 * incremented in this case but 'i' will.
> +		 */
> +		if (i != entrypc_idx)
> +			break;
> +	}
> +
> +	dwarf_lineaddr(line, postprologue_addr);
> +	if (*postprologue_addr >= highpc)
> +		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
> +			       postprologue_addr);
> +
> +	return true;
> +}
> +
> +void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
> +		       Dwarf_Addr *entrypc)
> +{
> +	size_t nr_lines = 0;
> +	unsigned long entrypc_idx = 0;
> +	Dwarf_Lines *lines = NULL;
> +	Dwarf_Addr postprologue_addr;
> +	Dwarf_Addr highpc;
> +
> +	if (dwarf_highpc(sp_die, &highpc))
> +		return;
> +
> +	if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
> +		return;
> +
> +	if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
> +		return;
> +
> +	if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
> +				       highpc, &postprologue_addr))
> +		return;
> +
> +	*entrypc = postprologue_addr;
> +}
> diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
> index dc0ce1a..791884a 100644
> --- a/tools/perf/util/dwarf-aux.h
> +++ b/tools/perf/util/dwarf-aux.h
> @@ -125,4 +125,9 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
>  /* Get the name and type of given variable DIE, stored as "type\tname" */
>  int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
>  int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);
> +
> +bool die_is_optimized_target(Dwarf_Die *cu_die);
> +void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
> +		       Dwarf_Addr *entrypc);
> +
>  #endif
> diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
> index 945cf7a..72f1152 100644
> --- a/tools/perf/util/probe-finder.c
> +++ b/tools/perf/util/probe-finder.c
> @@ -901,138 +901,6 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
>  	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
>  }
>  
> -static bool var_has_loclist(Dwarf_Die *cu_die)
> -{
> -	Dwarf_Attribute loc;
> -	int tag = dwarf_tag(cu_die);
> -
> -	if (tag != DW_TAG_formal_parameter &&
> -	    tag != DW_TAG_variable)
> -		return false;
> -
> -	return (dwarf_attr_integrate(cu_die, DW_AT_location, &loc) &&
> -		dwarf_whatform(&loc) == DW_FORM_sec_offset);
> -}
> -
> -/*
> - * For any object in given CU whose DW_AT_location is a location list,
> - * target program is compiled with optimization.
> - */
> -static bool optimized_target(Dwarf_Die *cu_die)
> -{
> -	Dwarf_Die tmp_die;
> -
> -	if (var_has_loclist(cu_die))
> -		return true;
> -
> -	if (!dwarf_child(cu_die, &tmp_die) && optimized_target(&tmp_die))
> -		return true;
> -
> -	if (!dwarf_siblingof(cu_die, &tmp_die) && optimized_target(&tmp_die))
> -		return true;
> -
> -	return false;
> -}
> -
> -static bool get_entrypc_idx(Dwarf_Lines *lines, unsigned long nr_lines,
> -			    Dwarf_Addr pf_addr, unsigned long *entrypc_idx)
> -{
> -	unsigned long i;
> -	Dwarf_Addr addr;
> -
> -	for (i = 0; i < nr_lines; i++) {
> -		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &addr))
> -			return false;
> -
> -		if (addr == pf_addr) {
> -			*entrypc_idx = i;
> -			return true;
> -		}
> -	}
> -	return false;
> -}
> -
> -static bool get_postprologue_addr(unsigned long entrypc_idx,
> -				  Dwarf_Lines *lines,
> -				  unsigned long nr_lines,
> -				  Dwarf_Addr highpc,
> -				  Dwarf_Addr *postprologue_addr)
> -{
> -	unsigned long i;
> -	int entrypc_lno, lno;
> -	Dwarf_Line *line;
> -	Dwarf_Addr addr;
> -	bool p_end;
> -
> -	/* entrypc_lno is actual source line number */
> -	line = dwarf_onesrcline(lines, entrypc_idx);
> -	if (dwarf_lineno(line, &entrypc_lno))
> -		return false;
> -
> -	for (i = entrypc_idx; i < nr_lines; i++) {
> -		line = dwarf_onesrcline(lines, i);
> -
> -		if (dwarf_lineaddr(line, &addr) ||
> -		    dwarf_lineno(line, &lno)    ||
> -		    dwarf_lineprologueend(line, &p_end))
> -			return false;
> -
> -		/* highpc is exclusive. [entrypc,highpc) */
> -		if (addr >= highpc)
> -			break;
> -
> -		/* clang supports prologue-end marker */
> -		if (p_end)
> -			break;
> -
> -		/* Actual next line in source */
> -		if (lno != entrypc_lno)
> -			break;
> -
> -		/*
> -		 * Single source line can have multiple line records.
> -		 * For Example,
> -		 *     void foo() { printf("hello\n"); }
> -		 * contains two line records. One points to declaration and
> -		 * other points to printf() line. Variable 'lno' won't get
> -		 * incremented in this case but 'i' will.
> -		 */
> -		if (i != entrypc_idx)
> -			break;
> -	}
> -
> -	dwarf_lineaddr(line, postprologue_addr);
> -	if (*postprologue_addr >= highpc)
> -		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
> -			       postprologue_addr);
> -
> -	return true;
> -}
> -
> -static void __skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
> -{
> -	size_t nr_lines = 0;
> -	unsigned long entrypc_idx = 0;
> -	Dwarf_Lines *lines = NULL;
> -	Dwarf_Addr postprologue_addr;
> -	Dwarf_Addr highpc;
> -
> -	if (dwarf_highpc(sp_die, &highpc))
> -		return;
> -
> -	if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
> -		return;
> -
> -	if (!get_entrypc_idx(lines, nr_lines, pf->addr, &entrypc_idx))
> -		return;
> -
> -	if (!get_postprologue_addr(entrypc_idx, lines, nr_lines,
> -				   highpc, &postprologue_addr))
> -		return;
> -
> -	pf->addr = postprologue_addr;
> -}
> -
>  static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
>  {
>  	struct perf_probe_point *pp = &pf->pev->point;
> @@ -1042,7 +910,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
>  		return;
>  
>  	/* Compiled with optimization? */
> -	if (optimized_target(&pf->cu_die))
> +	if (die_is_optimized_target(&pf->cu_die))
>  		return;
>  
>  	/* Don't know entrypc? */
> @@ -1062,7 +930,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
>  		"Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
>  		pf->addr);
>  
> -	__skip_prologue(sp_die, pf);
> +	die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
>  }
>  
>  static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
> -- 
> 2.5.5
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

[toc] | [prev] | [next] | [standalone]


#1472328 — [PATCH v2] perf probe: Move dwarf specific functions to dwarf-aux.c

FromRavi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Date2016-08-30 10:50 +0200
Subject[PATCH v2] perf probe: Move dwarf specific functions to dwarf-aux.c
Message-ID<sbMU2-2tK-9@gated-at.bofh.it>
In reply to#1472151
Move generic dwarf related functions from util/probe-finder.c to
util/dwarf-aux.c. Functions name and their prototype are also
changed accordingly. No functionality changes.

Suggested-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
Changes in v2:
  - Add comments about functions prototype and their usage
  - Replace function parameter names with more generic names

 tools/perf/util/dwarf-aux.c    | 179 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/dwarf-aux.h    |   8 ++
 tools/perf/util/probe-finder.c | 136 +------------------------------
 3 files changed, 189 insertions(+), 134 deletions(-)

diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index a347b19..faec899 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -1085,3 +1085,182 @@ int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
 	return -ENOTSUP;
 }
 #endif
+
+/*
+ * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
+ * @vr_die: a variable DIE
+ */
+static bool die_has_loclist(Dwarf_Die *vr_die)
+{
+	Dwarf_Attribute loc;
+	int tag = dwarf_tag(vr_die);
+
+	if (tag != DW_TAG_formal_parameter &&
+	    tag != DW_TAG_variable)
+		return false;
+
+	return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
+		dwarf_whatform(&loc) == DW_FORM_sec_offset);
+}
+
+/*
+ * die_is_optimized_target - Check if target program is compiled with
+ * optimization
+ * @cu_die: a CU DIE
+ *
+ * For any object in given CU whose DW_AT_location is a location list,
+ * target program is compiled with optimization. This is applicable to
+ * clang as well.
+ */
+bool die_is_optimized_target(Dwarf_Die *cu_die)
+{
+	Dwarf_Die tmp_die;
+
+	if (die_has_loclist(cu_die))
+		return true;
+
+	if (!dwarf_child(cu_die, &tmp_die) &&
+	    die_is_optimized_target(&tmp_die))
+		return true;
+
+	if (!dwarf_siblingof(cu_die, &tmp_die) &&
+	    die_is_optimized_target(&tmp_die))
+		return true;
+
+	return false;
+}
+
+/*
+ * die_search_idx - Search index of given line address
+ * @lines: Line records of single CU
+ * @nr_lines: Number of @lines
+ * @addr: address we are looking for
+ * @idx: index to be set by this function (return value)
+ *
+ * Search for @addr by looping over every lines of CU. If address
+ * matches, set index of that line in @idx. Note that single source
+ * line can have multiple line records. i.e. single source line can
+ * have multiple index.
+ */
+static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
+			   Dwarf_Addr addr, unsigned long *idx)
+{
+	unsigned long i;
+	Dwarf_Addr tmp;
+
+	for (i = 0; i < nr_lines; i++) {
+		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
+			return false;
+
+		if (tmp == addr) {
+			*idx = i;
+			return true;
+		}
+	}
+	return false;
+}
+
+/*
+ * die_get_postprologue_addr - Search next address after function prologue
+ * @entrypc_idx: entrypc index
+ * @lines: Line records of single CU
+ * @nr_lines: Number of @lines
+ * @hignpc: high PC address of function
+ * @postprologue_addr: Next address after function prologue (return value)
+ *
+ * Look for prologue-end marker. If there is no explicit marker, return
+ * address of next line record or next source line.
+ */
+static bool die_get_postprologue_addr(unsigned long entrypc_idx,
+				      Dwarf_Lines *lines,
+				      unsigned long nr_lines,
+				      Dwarf_Addr highpc,
+				      Dwarf_Addr *postprologue_addr)
+{
+	unsigned long i;
+	int entrypc_lno, lno;
+	Dwarf_Line *line;
+	Dwarf_Addr addr;
+	bool p_end;
+
+	/* entrypc_lno is actual source line number */
+	line = dwarf_onesrcline(lines, entrypc_idx);
+	if (dwarf_lineno(line, &entrypc_lno))
+		return false;
+
+	for (i = entrypc_idx; i < nr_lines; i++) {
+		line = dwarf_onesrcline(lines, i);
+
+		if (dwarf_lineaddr(line, &addr) ||
+		    dwarf_lineno(line, &lno)    ||
+		    dwarf_lineprologueend(line, &p_end))
+			return false;
+
+		/* highpc is exclusive. [entrypc,highpc) */
+		if (addr >= highpc)
+			break;
+
+		/* clang supports prologue-end marker */
+		if (p_end)
+			break;
+
+		/* Actual next line in source */
+		if (lno != entrypc_lno)
+			break;
+
+		/*
+		 * Single source line can have multiple line records.
+		 * For Example,
+		 *     void foo() { printf("hello\n"); }
+		 * contains two line records. One points to declaration and
+		 * other points to printf() line. Variable 'lno' won't get
+		 * incremented in this case but 'i' will.
+		 */
+		if (i != entrypc_idx)
+			break;
+	}
+
+	dwarf_lineaddr(line, postprologue_addr);
+	if (*postprologue_addr >= highpc)
+		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
+			       postprologue_addr);
+
+	return true;
+}
+
+/*
+ * die_skip_prologue - Use next address after prologue as probe location
+ * @sp_die: a subprogram DIE
+ * @cu_die: a CU DIE
+ * @entrypc: entrypc of the function
+ *
+ * Function prologue prepares stack and registers before executing function
+ * logic. When target program is compiled without optimization, function
+ * parameter information is only valid after prologue. When we probe entrypc
+ * of the function, and try to record function parameter, it contains
+ * garbage value.
+ */
+void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
+		       Dwarf_Addr *entrypc)
+{
+	size_t nr_lines = 0;
+	unsigned long entrypc_idx = 0;
+	Dwarf_Lines *lines = NULL;
+	Dwarf_Addr postprologue_addr;
+	Dwarf_Addr highpc;
+
+	if (dwarf_highpc(sp_die, &highpc))
+		return;
+
+	if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
+		return;
+
+	if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
+		return;
+
+	if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
+				       highpc, &postprologue_addr))
+		return;
+
+	*entrypc = postprologue_addr;
+}
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index dc0ce1a..8b6d2f8 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -125,4 +125,12 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
 /* Get the name and type of given variable DIE, stored as "type\tname" */
 int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
 int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);
+
+/* Check if target program is compiled with optimization */
+bool die_is_optimized_target(Dwarf_Die *cu_die);
+
+/* Use next address after prologue as probe location */
+void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
+		       Dwarf_Addr *entrypc);
+
 #endif
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 945cf7a..72f1152 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -901,138 +901,6 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
 	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
 }
 
-static bool var_has_loclist(Dwarf_Die *cu_die)
-{
-	Dwarf_Attribute loc;
-	int tag = dwarf_tag(cu_die);
-
-	if (tag != DW_TAG_formal_parameter &&
-	    tag != DW_TAG_variable)
-		return false;
-
-	return (dwarf_attr_integrate(cu_die, DW_AT_location, &loc) &&
-		dwarf_whatform(&loc) == DW_FORM_sec_offset);
-}
-
-/*
- * For any object in given CU whose DW_AT_location is a location list,
- * target program is compiled with optimization.
- */
-static bool optimized_target(Dwarf_Die *cu_die)
-{
-	Dwarf_Die tmp_die;
-
-	if (var_has_loclist(cu_die))
-		return true;
-
-	if (!dwarf_child(cu_die, &tmp_die) && optimized_target(&tmp_die))
-		return true;
-
-	if (!dwarf_siblingof(cu_die, &tmp_die) && optimized_target(&tmp_die))
-		return true;
-
-	return false;
-}
-
-static bool get_entrypc_idx(Dwarf_Lines *lines, unsigned long nr_lines,
-			    Dwarf_Addr pf_addr, unsigned long *entrypc_idx)
-{
-	unsigned long i;
-	Dwarf_Addr addr;
-
-	for (i = 0; i < nr_lines; i++) {
-		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &addr))
-			return false;
-
-		if (addr == pf_addr) {
-			*entrypc_idx = i;
-			return true;
-		}
-	}
-	return false;
-}
-
-static bool get_postprologue_addr(unsigned long entrypc_idx,
-				  Dwarf_Lines *lines,
-				  unsigned long nr_lines,
-				  Dwarf_Addr highpc,
-				  Dwarf_Addr *postprologue_addr)
-{
-	unsigned long i;
-	int entrypc_lno, lno;
-	Dwarf_Line *line;
-	Dwarf_Addr addr;
-	bool p_end;
-
-	/* entrypc_lno is actual source line number */
-	line = dwarf_onesrcline(lines, entrypc_idx);
-	if (dwarf_lineno(line, &entrypc_lno))
-		return false;
-
-	for (i = entrypc_idx; i < nr_lines; i++) {
-		line = dwarf_onesrcline(lines, i);
-
-		if (dwarf_lineaddr(line, &addr) ||
-		    dwarf_lineno(line, &lno)    ||
-		    dwarf_lineprologueend(line, &p_end))
-			return false;
-
-		/* highpc is exclusive. [entrypc,highpc) */
-		if (addr >= highpc)
-			break;
-
-		/* clang supports prologue-end marker */
-		if (p_end)
-			break;
-
-		/* Actual next line in source */
-		if (lno != entrypc_lno)
-			break;
-
-		/*
-		 * Single source line can have multiple line records.
-		 * For Example,
-		 *     void foo() { printf("hello\n"); }
-		 * contains two line records. One points to declaration and
-		 * other points to printf() line. Variable 'lno' won't get
-		 * incremented in this case but 'i' will.
-		 */
-		if (i != entrypc_idx)
-			break;
-	}
-
-	dwarf_lineaddr(line, postprologue_addr);
-	if (*postprologue_addr >= highpc)
-		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
-			       postprologue_addr);
-
-	return true;
-}
-
-static void __skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
-{
-	size_t nr_lines = 0;
-	unsigned long entrypc_idx = 0;
-	Dwarf_Lines *lines = NULL;
-	Dwarf_Addr postprologue_addr;
-	Dwarf_Addr highpc;
-
-	if (dwarf_highpc(sp_die, &highpc))
-		return;
-
-	if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
-		return;
-
-	if (!get_entrypc_idx(lines, nr_lines, pf->addr, &entrypc_idx))
-		return;
-
-	if (!get_postprologue_addr(entrypc_idx, lines, nr_lines,
-				   highpc, &postprologue_addr))
-		return;
-
-	pf->addr = postprologue_addr;
-}
-
 static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
 	struct perf_probe_point *pp = &pf->pev->point;
@@ -1042,7 +910,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 		return;
 
 	/* Compiled with optimization? */
-	if (optimized_target(&pf->cu_die))
+	if (die_is_optimized_target(&pf->cu_die))
 		return;
 
 	/* Don't know entrypc? */
@@ -1062,7 +930,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 		"Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
 		pf->addr);
 
-	__skip_prologue(sp_die, pf);
+	die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
 }
 
 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
-- 
2.5.5

[toc] | [prev] | [next] | [standalone]


#1472516 — Re: [PATCH v2] perf probe: Move dwarf specific functions to dwarf-aux.c

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-08-30 16:30 +0200
SubjectRe: [PATCH v2] perf probe: Move dwarf specific functions to dwarf-aux.c
Message-ID<sbSd4-64E-25@gated-at.bofh.it>
In reply to#1472328
On Tue, 30 Aug 2016 14:09:37 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> Move generic dwarf related functions from util/probe-finder.c to
> util/dwarf-aux.c. Functions name and their prototype are also
> changed accordingly. No functionality changes.

Great! 
Looks good to me :)

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> 
> Suggested-by: Masami Hiramatsu <mhiramat@kernel.org>
> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> ---
> Changes in v2:
>   - Add comments about functions prototype and their usage
>   - Replace function parameter names with more generic names
> 
>  tools/perf/util/dwarf-aux.c    | 179 +++++++++++++++++++++++++++++++++++++++++
>  tools/perf/util/dwarf-aux.h    |   8 ++
>  tools/perf/util/probe-finder.c | 136 +------------------------------
>  3 files changed, 189 insertions(+), 134 deletions(-)
> 
> diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
> index a347b19..faec899 100644
> --- a/tools/perf/util/dwarf-aux.c
> +++ b/tools/perf/util/dwarf-aux.c
> @@ -1085,3 +1085,182 @@ int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
>  	return -ENOTSUP;
>  }
>  #endif
> +
> +/*
> + * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
> + * @vr_die: a variable DIE
> + */
> +static bool die_has_loclist(Dwarf_Die *vr_die)
> +{
> +	Dwarf_Attribute loc;
> +	int tag = dwarf_tag(vr_die);
> +
> +	if (tag != DW_TAG_formal_parameter &&
> +	    tag != DW_TAG_variable)
> +		return false;
> +
> +	return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
> +		dwarf_whatform(&loc) == DW_FORM_sec_offset);
> +}
> +
> +/*
> + * die_is_optimized_target - Check if target program is compiled with
> + * optimization
> + * @cu_die: a CU DIE
> + *
> + * For any object in given CU whose DW_AT_location is a location list,
> + * target program is compiled with optimization. This is applicable to
> + * clang as well.
> + */
> +bool die_is_optimized_target(Dwarf_Die *cu_die)
> +{
> +	Dwarf_Die tmp_die;
> +
> +	if (die_has_loclist(cu_die))
> +		return true;
> +
> +	if (!dwarf_child(cu_die, &tmp_die) &&
> +	    die_is_optimized_target(&tmp_die))
> +		return true;
> +
> +	if (!dwarf_siblingof(cu_die, &tmp_die) &&
> +	    die_is_optimized_target(&tmp_die))
> +		return true;
> +
> +	return false;
> +}
> +
> +/*
> + * die_search_idx - Search index of given line address
> + * @lines: Line records of single CU
> + * @nr_lines: Number of @lines
> + * @addr: address we are looking for
> + * @idx: index to be set by this function (return value)
> + *
> + * Search for @addr by looping over every lines of CU. If address
> + * matches, set index of that line in @idx. Note that single source
> + * line can have multiple line records. i.e. single source line can
> + * have multiple index.
> + */
> +static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
> +			   Dwarf_Addr addr, unsigned long *idx)
> +{
> +	unsigned long i;
> +	Dwarf_Addr tmp;
> +
> +	for (i = 0; i < nr_lines; i++) {
> +		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
> +			return false;
> +
> +		if (tmp == addr) {
> +			*idx = i;
> +			return true;
> +		}
> +	}
> +	return false;
> +}
> +
> +/*
> + * die_get_postprologue_addr - Search next address after function prologue
> + * @entrypc_idx: entrypc index
> + * @lines: Line records of single CU
> + * @nr_lines: Number of @lines
> + * @hignpc: high PC address of function
> + * @postprologue_addr: Next address after function prologue (return value)
> + *
> + * Look for prologue-end marker. If there is no explicit marker, return
> + * address of next line record or next source line.
> + */
> +static bool die_get_postprologue_addr(unsigned long entrypc_idx,
> +				      Dwarf_Lines *lines,
> +				      unsigned long nr_lines,
> +				      Dwarf_Addr highpc,
> +				      Dwarf_Addr *postprologue_addr)
> +{
> +	unsigned long i;
> +	int entrypc_lno, lno;
> +	Dwarf_Line *line;
> +	Dwarf_Addr addr;
> +	bool p_end;
> +
> +	/* entrypc_lno is actual source line number */
> +	line = dwarf_onesrcline(lines, entrypc_idx);
> +	if (dwarf_lineno(line, &entrypc_lno))
> +		return false;
> +
> +	for (i = entrypc_idx; i < nr_lines; i++) {
> +		line = dwarf_onesrcline(lines, i);
> +
> +		if (dwarf_lineaddr(line, &addr) ||
> +		    dwarf_lineno(line, &lno)    ||
> +		    dwarf_lineprologueend(line, &p_end))
> +			return false;
> +
> +		/* highpc is exclusive. [entrypc,highpc) */
> +		if (addr >= highpc)
> +			break;
> +
> +		/* clang supports prologue-end marker */
> +		if (p_end)
> +			break;
> +
> +		/* Actual next line in source */
> +		if (lno != entrypc_lno)
> +			break;
> +
> +		/*
> +		 * Single source line can have multiple line records.
> +		 * For Example,
> +		 *     void foo() { printf("hello\n"); }
> +		 * contains two line records. One points to declaration and
> +		 * other points to printf() line. Variable 'lno' won't get
> +		 * incremented in this case but 'i' will.
> +		 */
> +		if (i != entrypc_idx)
> +			break;
> +	}
> +
> +	dwarf_lineaddr(line, postprologue_addr);
> +	if (*postprologue_addr >= highpc)
> +		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
> +			       postprologue_addr);
> +
> +	return true;
> +}
> +
> +/*
> + * die_skip_prologue - Use next address after prologue as probe location
> + * @sp_die: a subprogram DIE
> + * @cu_die: a CU DIE
> + * @entrypc: entrypc of the function
> + *
> + * Function prologue prepares stack and registers before executing function
> + * logic. When target program is compiled without optimization, function
> + * parameter information is only valid after prologue. When we probe entrypc
> + * of the function, and try to record function parameter, it contains
> + * garbage value.
> + */
> +void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
> +		       Dwarf_Addr *entrypc)
> +{
> +	size_t nr_lines = 0;
> +	unsigned long entrypc_idx = 0;
> +	Dwarf_Lines *lines = NULL;
> +	Dwarf_Addr postprologue_addr;
> +	Dwarf_Addr highpc;
> +
> +	if (dwarf_highpc(sp_die, &highpc))
> +		return;
> +
> +	if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
> +		return;
> +
> +	if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
> +		return;
> +
> +	if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
> +				       highpc, &postprologue_addr))
> +		return;
> +
> +	*entrypc = postprologue_addr;
> +}
> diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
> index dc0ce1a..8b6d2f8 100644
> --- a/tools/perf/util/dwarf-aux.h
> +++ b/tools/perf/util/dwarf-aux.h
> @@ -125,4 +125,12 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
>  /* Get the name and type of given variable DIE, stored as "type\tname" */
>  int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
>  int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);
> +
> +/* Check if target program is compiled with optimization */
> +bool die_is_optimized_target(Dwarf_Die *cu_die);
> +
> +/* Use next address after prologue as probe location */
> +void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
> +		       Dwarf_Addr *entrypc);
> +
>  #endif
> diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
> index 945cf7a..72f1152 100644
> --- a/tools/perf/util/probe-finder.c
> +++ b/tools/perf/util/probe-finder.c
> @@ -901,138 +901,6 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
>  	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
>  }
>  
> -static bool var_has_loclist(Dwarf_Die *cu_die)
> -{
> -	Dwarf_Attribute loc;
> -	int tag = dwarf_tag(cu_die);
> -
> -	if (tag != DW_TAG_formal_parameter &&
> -	    tag != DW_TAG_variable)
> -		return false;
> -
> -	return (dwarf_attr_integrate(cu_die, DW_AT_location, &loc) &&
> -		dwarf_whatform(&loc) == DW_FORM_sec_offset);
> -}
> -
> -/*
> - * For any object in given CU whose DW_AT_location is a location list,
> - * target program is compiled with optimization.
> - */
> -static bool optimized_target(Dwarf_Die *cu_die)
> -{
> -	Dwarf_Die tmp_die;
> -
> -	if (var_has_loclist(cu_die))
> -		return true;
> -
> -	if (!dwarf_child(cu_die, &tmp_die) && optimized_target(&tmp_die))
> -		return true;
> -
> -	if (!dwarf_siblingof(cu_die, &tmp_die) && optimized_target(&tmp_die))
> -		return true;
> -
> -	return false;
> -}
> -
> -static bool get_entrypc_idx(Dwarf_Lines *lines, unsigned long nr_lines,
> -			    Dwarf_Addr pf_addr, unsigned long *entrypc_idx)
> -{
> -	unsigned long i;
> -	Dwarf_Addr addr;
> -
> -	for (i = 0; i < nr_lines; i++) {
> -		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &addr))
> -			return false;
> -
> -		if (addr == pf_addr) {
> -			*entrypc_idx = i;
> -			return true;
> -		}
> -	}
> -	return false;
> -}
> -
> -static bool get_postprologue_addr(unsigned long entrypc_idx,
> -				  Dwarf_Lines *lines,
> -				  unsigned long nr_lines,
> -				  Dwarf_Addr highpc,
> -				  Dwarf_Addr *postprologue_addr)
> -{
> -	unsigned long i;
> -	int entrypc_lno, lno;
> -	Dwarf_Line *line;
> -	Dwarf_Addr addr;
> -	bool p_end;
> -
> -	/* entrypc_lno is actual source line number */
> -	line = dwarf_onesrcline(lines, entrypc_idx);
> -	if (dwarf_lineno(line, &entrypc_lno))
> -		return false;
> -
> -	for (i = entrypc_idx; i < nr_lines; i++) {
> -		line = dwarf_onesrcline(lines, i);
> -
> -		if (dwarf_lineaddr(line, &addr) ||
> -		    dwarf_lineno(line, &lno)    ||
> -		    dwarf_lineprologueend(line, &p_end))
> -			return false;
> -
> -		/* highpc is exclusive. [entrypc,highpc) */
> -		if (addr >= highpc)
> -			break;
> -
> -		/* clang supports prologue-end marker */
> -		if (p_end)
> -			break;
> -
> -		/* Actual next line in source */
> -		if (lno != entrypc_lno)
> -			break;
> -
> -		/*
> -		 * Single source line can have multiple line records.
> -		 * For Example,
> -		 *     void foo() { printf("hello\n"); }
> -		 * contains two line records. One points to declaration and
> -		 * other points to printf() line. Variable 'lno' won't get
> -		 * incremented in this case but 'i' will.
> -		 */
> -		if (i != entrypc_idx)
> -			break;
> -	}
> -
> -	dwarf_lineaddr(line, postprologue_addr);
> -	if (*postprologue_addr >= highpc)
> -		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
> -			       postprologue_addr);
> -
> -	return true;
> -}
> -
> -static void __skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
> -{
> -	size_t nr_lines = 0;
> -	unsigned long entrypc_idx = 0;
> -	Dwarf_Lines *lines = NULL;
> -	Dwarf_Addr postprologue_addr;
> -	Dwarf_Addr highpc;
> -
> -	if (dwarf_highpc(sp_die, &highpc))
> -		return;
> -
> -	if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
> -		return;
> -
> -	if (!get_entrypc_idx(lines, nr_lines, pf->addr, &entrypc_idx))
> -		return;
> -
> -	if (!get_postprologue_addr(entrypc_idx, lines, nr_lines,
> -				   highpc, &postprologue_addr))
> -		return;
> -
> -	pf->addr = postprologue_addr;
> -}
> -
>  static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
>  {
>  	struct perf_probe_point *pp = &pf->pev->point;
> @@ -1042,7 +910,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
>  		return;
>  
>  	/* Compiled with optimization? */
> -	if (optimized_target(&pf->cu_die))
> +	if (die_is_optimized_target(&pf->cu_die))
>  		return;
>  
>  	/* Don't know entrypc? */
> @@ -1062,7 +930,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
>  		"Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
>  		pf->addr);
>  
> -	__skip_prologue(sp_die, pf);
> +	die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
>  }
>  
>  static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
> -- 
> 2.5.5
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

[toc] | [prev] | [next] | [standalone]


#1476454 — [tip:perf/core] perf probe: Move dwarf specific functions to dwarf-aux.c

Fromtip-bot for Ravi Bangoria <tipbot@zytor.com>
Date2016-09-05 15:30 +0200
Subject[tip:perf/core] perf probe: Move dwarf specific functions to dwarf-aux.c
Message-ID<se28k-4is-79@gated-at.bofh.it>
In reply to#1472328
Commit-ID:  6243b9dc4c991fe8bdc53a0e029908aef3ddb101
Gitweb:     http://git.kernel.org/tip/6243b9dc4c991fe8bdc53a0e029908aef3ddb101
Author:     Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
AuthorDate: Tue, 30 Aug 2016 14:09:37 +0530
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 1 Sep 2016 12:42:26 -0300

perf probe: Move dwarf specific functions to dwarf-aux.c

Move generic dwarf related functions from util/probe-finder.c to
util/dwarf-aux.c. Functions name and their prototype are also changed
accordingly. No functionality changes.

Suggested-and-Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1472546377-25612-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/dwarf-aux.c    | 179 +++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/dwarf-aux.h    |   8 ++
 tools/perf/util/probe-finder.c | 136 +------------------------------
 3 files changed, 189 insertions(+), 134 deletions(-)

diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index a347b19..faec899 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -1085,3 +1085,182 @@ int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
 	return -ENOTSUP;
 }
 #endif
+
+/*
+ * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
+ * @vr_die: a variable DIE
+ */
+static bool die_has_loclist(Dwarf_Die *vr_die)
+{
+	Dwarf_Attribute loc;
+	int tag = dwarf_tag(vr_die);
+
+	if (tag != DW_TAG_formal_parameter &&
+	    tag != DW_TAG_variable)
+		return false;
+
+	return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
+		dwarf_whatform(&loc) == DW_FORM_sec_offset);
+}
+
+/*
+ * die_is_optimized_target - Check if target program is compiled with
+ * optimization
+ * @cu_die: a CU DIE
+ *
+ * For any object in given CU whose DW_AT_location is a location list,
+ * target program is compiled with optimization. This is applicable to
+ * clang as well.
+ */
+bool die_is_optimized_target(Dwarf_Die *cu_die)
+{
+	Dwarf_Die tmp_die;
+
+	if (die_has_loclist(cu_die))
+		return true;
+
+	if (!dwarf_child(cu_die, &tmp_die) &&
+	    die_is_optimized_target(&tmp_die))
+		return true;
+
+	if (!dwarf_siblingof(cu_die, &tmp_die) &&
+	    die_is_optimized_target(&tmp_die))
+		return true;
+
+	return false;
+}
+
+/*
+ * die_search_idx - Search index of given line address
+ * @lines: Line records of single CU
+ * @nr_lines: Number of @lines
+ * @addr: address we are looking for
+ * @idx: index to be set by this function (return value)
+ *
+ * Search for @addr by looping over every lines of CU. If address
+ * matches, set index of that line in @idx. Note that single source
+ * line can have multiple line records. i.e. single source line can
+ * have multiple index.
+ */
+static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
+			   Dwarf_Addr addr, unsigned long *idx)
+{
+	unsigned long i;
+	Dwarf_Addr tmp;
+
+	for (i = 0; i < nr_lines; i++) {
+		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
+			return false;
+
+		if (tmp == addr) {
+			*idx = i;
+			return true;
+		}
+	}
+	return false;
+}
+
+/*
+ * die_get_postprologue_addr - Search next address after function prologue
+ * @entrypc_idx: entrypc index
+ * @lines: Line records of single CU
+ * @nr_lines: Number of @lines
+ * @hignpc: high PC address of function
+ * @postprologue_addr: Next address after function prologue (return value)
+ *
+ * Look for prologue-end marker. If there is no explicit marker, return
+ * address of next line record or next source line.
+ */
+static bool die_get_postprologue_addr(unsigned long entrypc_idx,
+				      Dwarf_Lines *lines,
+				      unsigned long nr_lines,
+				      Dwarf_Addr highpc,
+				      Dwarf_Addr *postprologue_addr)
+{
+	unsigned long i;
+	int entrypc_lno, lno;
+	Dwarf_Line *line;
+	Dwarf_Addr addr;
+	bool p_end;
+
+	/* entrypc_lno is actual source line number */
+	line = dwarf_onesrcline(lines, entrypc_idx);
+	if (dwarf_lineno(line, &entrypc_lno))
+		return false;
+
+	for (i = entrypc_idx; i < nr_lines; i++) {
+		line = dwarf_onesrcline(lines, i);
+
+		if (dwarf_lineaddr(line, &addr) ||
+		    dwarf_lineno(line, &lno)    ||
+		    dwarf_lineprologueend(line, &p_end))
+			return false;
+
+		/* highpc is exclusive. [entrypc,highpc) */
+		if (addr >= highpc)
+			break;
+
+		/* clang supports prologue-end marker */
+		if (p_end)
+			break;
+
+		/* Actual next line in source */
+		if (lno != entrypc_lno)
+			break;
+
+		/*
+		 * Single source line can have multiple line records.
+		 * For Example,
+		 *     void foo() { printf("hello\n"); }
+		 * contains two line records. One points to declaration and
+		 * other points to printf() line. Variable 'lno' won't get
+		 * incremented in this case but 'i' will.
+		 */
+		if (i != entrypc_idx)
+			break;
+	}
+
+	dwarf_lineaddr(line, postprologue_addr);
+	if (*postprologue_addr >= highpc)
+		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
+			       postprologue_addr);
+
+	return true;
+}
+
+/*
+ * die_skip_prologue - Use next address after prologue as probe location
+ * @sp_die: a subprogram DIE
+ * @cu_die: a CU DIE
+ * @entrypc: entrypc of the function
+ *
+ * Function prologue prepares stack and registers before executing function
+ * logic. When target program is compiled without optimization, function
+ * parameter information is only valid after prologue. When we probe entrypc
+ * of the function, and try to record function parameter, it contains
+ * garbage value.
+ */
+void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
+		       Dwarf_Addr *entrypc)
+{
+	size_t nr_lines = 0;
+	unsigned long entrypc_idx = 0;
+	Dwarf_Lines *lines = NULL;
+	Dwarf_Addr postprologue_addr;
+	Dwarf_Addr highpc;
+
+	if (dwarf_highpc(sp_die, &highpc))
+		return;
+
+	if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
+		return;
+
+	if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
+		return;
+
+	if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
+				       highpc, &postprologue_addr))
+		return;
+
+	*entrypc = postprologue_addr;
+}
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index dc0ce1a..8b6d2f8 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -125,4 +125,12 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
 /* Get the name and type of given variable DIE, stored as "type\tname" */
 int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
 int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);
+
+/* Check if target program is compiled with optimization */
+bool die_is_optimized_target(Dwarf_Die *cu_die);
+
+/* Use next address after prologue as probe location */
+void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
+		       Dwarf_Addr *entrypc);
+
 #endif
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 003ecad..8daca4f 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -907,138 +907,6 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
 	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
 }
 
-static bool var_has_loclist(Dwarf_Die *cu_die)
-{
-	Dwarf_Attribute loc;
-	int tag = dwarf_tag(cu_die);
-
-	if (tag != DW_TAG_formal_parameter &&
-	    tag != DW_TAG_variable)
-		return false;
-
-	return (dwarf_attr_integrate(cu_die, DW_AT_location, &loc) &&
-		dwarf_whatform(&loc) == DW_FORM_sec_offset);
-}
-
-/*
- * For any object in given CU whose DW_AT_location is a location list,
- * target program is compiled with optimization.
- */
-static bool optimized_target(Dwarf_Die *cu_die)
-{
-	Dwarf_Die tmp_die;
-
-	if (var_has_loclist(cu_die))
-		return true;
-
-	if (!dwarf_child(cu_die, &tmp_die) && optimized_target(&tmp_die))
-		return true;
-
-	if (!dwarf_siblingof(cu_die, &tmp_die) && optimized_target(&tmp_die))
-		return true;
-
-	return false;
-}
-
-static bool get_entrypc_idx(Dwarf_Lines *lines, unsigned long nr_lines,
-			    Dwarf_Addr pf_addr, unsigned long *entrypc_idx)
-{
-	unsigned long i;
-	Dwarf_Addr addr;
-
-	for (i = 0; i < nr_lines; i++) {
-		if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &addr))
-			return false;
-
-		if (addr == pf_addr) {
-			*entrypc_idx = i;
-			return true;
-		}
-	}
-	return false;
-}
-
-static bool get_postprologue_addr(unsigned long entrypc_idx,
-				  Dwarf_Lines *lines,
-				  unsigned long nr_lines,
-				  Dwarf_Addr highpc,
-				  Dwarf_Addr *postprologue_addr)
-{
-	unsigned long i;
-	int entrypc_lno, lno;
-	Dwarf_Line *line;
-	Dwarf_Addr addr;
-	bool p_end;
-
-	/* entrypc_lno is actual source line number */
-	line = dwarf_onesrcline(lines, entrypc_idx);
-	if (dwarf_lineno(line, &entrypc_lno))
-		return false;
-
-	for (i = entrypc_idx; i < nr_lines; i++) {
-		line = dwarf_onesrcline(lines, i);
-
-		if (dwarf_lineaddr(line, &addr) ||
-		    dwarf_lineno(line, &lno)    ||
-		    dwarf_lineprologueend(line, &p_end))
-			return false;
-
-		/* highpc is exclusive. [entrypc,highpc) */
-		if (addr >= highpc)
-			break;
-
-		/* clang supports prologue-end marker */
-		if (p_end)
-			break;
-
-		/* Actual next line in source */
-		if (lno != entrypc_lno)
-			break;
-
-		/*
-		 * Single source line can have multiple line records.
-		 * For Example,
-		 *     void foo() { printf("hello\n"); }
-		 * contains two line records. One points to declaration and
-		 * other points to printf() line. Variable 'lno' won't get
-		 * incremented in this case but 'i' will.
-		 */
-		if (i != entrypc_idx)
-			break;
-	}
-
-	dwarf_lineaddr(line, postprologue_addr);
-	if (*postprologue_addr >= highpc)
-		dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
-			       postprologue_addr);
-
-	return true;
-}
-
-static void __skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
-{
-	size_t nr_lines = 0;
-	unsigned long entrypc_idx = 0;
-	Dwarf_Lines *lines = NULL;
-	Dwarf_Addr postprologue_addr;
-	Dwarf_Addr highpc;
-
-	if (dwarf_highpc(sp_die, &highpc))
-		return;
-
-	if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
-		return;
-
-	if (!get_entrypc_idx(lines, nr_lines, pf->addr, &entrypc_idx))
-		return;
-
-	if (!get_postprologue_addr(entrypc_idx, lines, nr_lines,
-				   highpc, &postprologue_addr))
-		return;
-
-	pf->addr = postprologue_addr;
-}
-
 static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
 	struct perf_probe_point *pp = &pf->pev->point;
@@ -1048,7 +916,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 		return;
 
 	/* Compiled with optimization? */
-	if (optimized_target(&pf->cu_die))
+	if (die_is_optimized_target(&pf->cu_die))
 		return;
 
 	/* Don't know entrypc? */
@@ -1068,7 +936,7 @@ static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
 		"Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
 		pf->addr);
 
-	__skip_prologue(sp_die, pf);
+	die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
 }
 
 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)

[toc] | [prev] | [next] | [standalone]


#1471623

FromRavi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Date2016-08-29 10:10 +0200
Message-ID<sbpNM-4Om-27@gated-at.bofh.it>
In reply to#1470974

On Saturday 27 August 2016 01:24 AM, Arnaldo Carvalho de Melo wrote:
> Em Fri, Aug 26, 2016 at 04:30:27PM -0300, Arnaldo Carvalho de Melo escreveu:
>> Em Wed, Aug 03, 2016 at 02:28:45PM +0530, Ravi Bangoria escreveu:
>>> +++ b/tools/perf/util/probe-finder.c
>>> @@ -892,6 +892,169 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
>>>  	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
>>>  }
>>   
>>> +static bool var_has_loclist(Dwarf_Die *die)
>> So, the variable 'die' cause the build to fail in multiple systems, I'm
>> renaming it to 'cu_die', there are some more problems when cross compiling it
>> to some arches, I'm trying to fix them all now:
> Fixed, please check:
>
> http://git.kernel.org/cgit/linux/kernel/git/acme/linux.git/commit/?h=perf/urgent&id=3866e3762da3291613dfb8b193885a8ed3836669

Thanks Arnaldo,

I've tested it. Looks fine to me.

-Ravi

> - Arnaldo
>

[toc] | [prev] | [next] | [standalone]


#1471625

FromRavi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Date2016-08-29 10:10 +0200
Message-ID<sbpNM-4Om-23@gated-at.bofh.it>
In reply to#1470968

On Saturday 27 August 2016 01:00 AM, Arnaldo Carvalho de Melo wrote:
> Em Wed, Aug 03, 2016 at 02:28:45PM +0530, Ravi Bangoria escreveu:
>> +++ b/tools/perf/util/probe-finder.c
>> @@ -892,6 +892,169 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
>>  	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
>>  }
>   
>> +static bool var_has_loclist(Dwarf_Die *die)
> So, the variable 'die' cause the build to fail in multiple systems, I'm
> renaming it to 'cu_die', there are some more problems when cross compiling it
> to some arches, I'm trying to fix them all now:

Sorry for this. I started using "make -C tools/perf build-test" but I don't have
infrastructure handy to test for cross arch.

If possible, can you please provide that to me. Otherwise I've to create it from
scratch.

-Ravi

> [root@jouet ~]# dm
>  1 65.668882867 alpine:3.4: Ok
>  2 24.327143744 android-ndk:r12b-arm: Ok
>  3 76.000455817 archlinux:latest: Ok
>  4 40.905282317 centos:5: Ok
>  5 28.799284950 centos:6: FAIL
> cc1: warnings being treated as errors
> util/probe-finder.c: In function 'var_has_loclist':
> util/probe-finder.c:904: error: declaration of 'die' shadows a global declaration
> util/util.h:137: error: shadowed declaration is here
> util/probe-finder.c: In function 'optimized_target':
> util/probe-finder.c:921: error: declaration of 'die' shadows a global declaration
> util/util.h:137: error: shadowed declaration is here
> -----------------------------------------------------------------------------
>  6 68.157498673 centos:7: Ok
>  7 32.814597820 debian:7: FAIL
> util/probe-finder.c: In function 'var_has_loclist':
> util/probe-finder.c:904:40: error: declaration of 'die' shadows a global declaration [-Werror=shadow]
> In file included from util/probe-finder.c:39:0:
> util/util.h:137:6: error: shadowed declaration is here [-Werror=shadow]
> util/probe-finder.c: In function 'optimized_target':
> util/probe-finder.c:921:41: error: declaration of 'die' shadows a global declaration [-Werror=shadow]
> In file included from util/probe-finder.c:39:0:
> util/util.h:137:6: error: shadowed declaration is here [-Werror=shadow]
> -----------------------------------------------------------------------------
>  8 69.535114125 debian:8: Ok
>  9 71.524733936 debian:experimental: Ok
> 10 66.956671932 fedora:20: Ok
> 11 72.127804972 fedora:21: Ok
> 12 75.767022465 fedora:22: Ok
> 13 72.244964710 fedora:23: Ok
> 14 75.556712624 fedora:24: Ok
> 15 30.825802615 fedora:24-x-ARC-uClibc: Ok
> 16 76.874903316 fedora:rawhide: Ok
> 17 76.756388879 mageia:5: Ok
> 18 71.700493646 opensuse:13.2: Ok
> 19 69.974649379 opensuse:42.1: Ok
> 20 75.265305896 opensuse:tumbleweed: Ok
> 21 28.800283739 ubuntu:12.04.5: FAIL
> util/probe-finder.c: In function 'var_has_loclist':
> util/probe-finder.c:904:40: error: declaration of 'die' shadows a global declaration [-Werror=shadow]
> util/util.h:137:6: error: shadowed declaration is here [-Werror=shadow]
> util/probe-finder.c: In function 'optimized_target':
> util/probe-finder.c:921:41: error: declaration of 'die' shadows a global declaration [-Werror=shadow]
> util/util.h:137:6: error: shadowed declaration is here [-Werror=shadow]
> -----------------------------------------------------------------------------
> 22 66.514504455 ubuntu:14.04.4: Ok
> 23 69.100413367 ubuntu:15.10: Ok
> 24 64.414190947 ubuntu:16.04: Ok
> 25 29.481652689 ubuntu:16.04-x-arm: FAIL
> util/probe-finder.c: In function '__skip_prologue':
> util/probe-finder.c:1022:45: error: passing argument 3 of 'dwarf_getsrclines' from incompatible pointer type [-Werror=incompatible-pointer-types]
>   if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
>                                              ^
> In file included from util/dwarf-aux.h:23:0,
>                  from util/probe-finder.h:24,
>                  from util/probe-finder.c:41:
> /usr/arm-linux-gnueabihf/include/elfutils/libdw.h:592:12: note: expected 'size_t * {aka unsigned int *}' but argument is of type 'long unsigned int *'
>  extern int dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines,
>             ^
> In file included from util/probe-finder.c:37:0:
> util/probe-finder.c: In function 'skip_prologue':
> util/probe-finder.c:1060:10: error: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'Dwarf_Addr {aka long long unsigned int}' [-Werror=format=]
>   pr_info("Target program is compiled without optimization. Skipping prologue.\n"
>           ^
> util/debug.h:18:21: note: in definition of macro 'pr_fmt'
>  #define pr_fmt(fmt) fmt
>                      ^
> util/probe-finder.c:1060:2: note: in expansion of macro 'pr_info'
>   pr_info("Target program is compiled without optimization. Skipping prologue.\n"
>   ^
> -----------------------------------------------------------------------------
> 26 51.979875334 ubuntu:16.04-x-arm64: Ok
> 27 28.808591224 ubuntu:16.04-x-powerpc64: FAIL
>   CC       /tmp/build/perf/tests/bp_signal.o
> util/probe-finder.c: In function '__skip_prologue':
> util/probe-finder.c:1022:45: error: passing argument 3 of 'dwarf_getsrclines' from incompatible pointer type [-Werror=incompatible-pointer-types]
>   if (dwarf_getsrclines(&pf->cu_die, &lines, &nr_lines))
>                                              ^
> In file included from util/dwarf-aux.h:23:0,
>                  from util/probe-finder.h:24,
>                  from util/probe-finder.c:41:
> /usr/powerpc-linux-gnu/include/elfutils/libdw.h:592:12: note: expected 'size_t * {aka unsigned int *}' but argument is of type 'long unsigned int *'
>  extern int dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines,
>             ^
> In file included from util/probe-finder.c:37:0:
> util/probe-finder.c: In function 'skip_prologue':
> util/probe-finder.c:1060:10: error: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'Dwarf_Addr {aka long long unsigned int}' [-Werror=format=]
>   pr_info("Target program is compiled without optimization. Skipping prologue.\n"
>           ^
> util/debug.h:18:21: note: in definition of macro 'pr_fmt'
>  #define pr_fmt(fmt) fmt
>                      ^
> util/probe-finder.c:1060:2: note: in expansion of macro 'pr_info'
> -----------------------------------------------------------------------------
> 28 53.372615706 ubuntu:16.04-x-powerpc64el: Ok
> 29 71.550573752 ubuntu:16.10: Ok
> 30 52.727886240 ubuntu:16.10-x-s390: Ok
>

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web