Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1470968 > unrolled thread
| Started by | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| First post | 2016-08-26 21:50 +0200 |
| Last post | 2016-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.
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
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-08-26 21:50 +0200 |
| Subject | Re: [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]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-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]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-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]
| From | Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-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]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-08-30 01:00 +0200 |
| Subject | Re: [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]
| From | Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-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]
| From | Masami Hiramatsu <mhiramat@kernel.org> |
|---|---|
| Date | 2016-08-30 16:30 +0200 |
| Subject | Re: [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]
| From | tip-bot for Ravi Bangoria <tipbot@zytor.com> |
|---|---|
| Date | 2016-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]
| From | Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-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]
| From | Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-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