[tip:perf/core] perf probe: Introduce die_find_child() function

From: tip-bot for Masami Hiramatsu
Date: Wed Mar 17 2010 - 07:29:57 EST


Commit-ID: 016f262e4fb10c6ecff709317098912f94a21efa
Gitweb: http://git.kernel.org/tip/016f262e4fb10c6ecff709317098912f94a21efa
Author: Masami Hiramatsu <mhiramat@xxxxxxxxxx>
AuthorDate: Tue, 16 Mar 2010 18:05:58 -0400
Committer: Ingo Molnar <mingo@xxxxxxx>
CommitDate: Wed, 17 Mar 2010 11:32:31 +0100

perf probe: Introduce die_find_child() function

Introduce die_find_child() function to integrate DIE-tree
searching functions.

Signed-off-by: Masami Hiramatsu <mhiramat@xxxxxxxxxx>
Cc: systemtap <systemtap@xxxxxxxxxxxxxxxxxx>
Cc: DLE <dle-develop@xxxxxxxxxxxxxxxxxxxxx>
Cc: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Cc: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Cc: Paul Mackerras <paulus@xxxxxxxxx>
Cc: Mike Galbraith <efault@xxxxxx>
Cc: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
LKML-Reference: <20100316220558.32050.7905.stgit@xxxxxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Ingo Molnar <mingo@xxxxxxx>
---
tools/perf/util/probe-finder.c | 136 +++++++++++++++++++++++----------------
1 files changed, 80 insertions(+), 56 deletions(-)

diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index c91a960..3942e14 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -186,6 +186,62 @@ static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
return src;
}

+/* Compare diename and tname */
+static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
+{
+ const char *name;
+ name = dwarf_diename(dw_die);
+ DIE_IF(name == NULL);
+ return strcmp(tname, name);
+}
+
+/* Get entry pc(or low pc, 1st entry of ranges) of the die */
+static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
+{
+ Dwarf_Addr epc;
+ int ret;
+
+ ret = dwarf_entrypc(dw_die, &epc);
+ DIE_IF(ret == -1);
+ return epc;
+}
+
+/* Return values for die_find callbacks */
+enum {
+ DIE_FIND_CB_FOUND = 0, /* End of Search */
+ DIE_FIND_CB_CHILD = 1, /* Search only children */
+ DIE_FIND_CB_SIBLING = 2, /* Search only siblings */
+ DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */
+};
+
+/* Search a child die */
+static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
+ int (*callback)(Dwarf_Die *, void *),
+ void *data, Dwarf_Die *die_mem)
+{
+ Dwarf_Die child_die;
+ int ret;
+
+ ret = dwarf_child(rt_die, die_mem);
+ if (ret != 0)
+ return NULL;
+
+ do {
+ ret = callback(die_mem, data);
+ if (ret == DIE_FIND_CB_FOUND)
+ return die_mem;
+
+ if ((ret & DIE_FIND_CB_CHILD) &&
+ die_find_child(die_mem, callback, data, &child_die)) {
+ memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
+ return die_mem;
+ }
+ } while ((ret & DIE_FIND_CB_SIBLING) &&
+ dwarf_siblingof(die_mem, die_mem) == 0);
+
+ return NULL;
+}
+
struct __addr_die_search_param {
Dwarf_Addr addr;
Dwarf_Die *die_mem;
@@ -217,77 +273,45 @@ static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
return die_mem;
}

-/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
-static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
- Dwarf_Die *die_mem)
+/* die_find callback for inline function search */
+static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
{
- Dwarf_Die child_die;
- int ret;
+ Dwarf_Addr *addr = data;

- ret = dwarf_child(sp_die, die_mem);
- if (ret != 0)
- return NULL;
-
- do {
- if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
- dwarf_haspc(die_mem, addr))
- return die_mem;
+ if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
+ dwarf_haspc(die_mem, *addr))
+ return DIE_FIND_CB_FOUND;

- if (die_find_inlinefunc(die_mem, addr, &child_die)) {
- memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
- return die_mem;
- }
- } while (dwarf_siblingof(die_mem, die_mem) == 0);
-
- return NULL;
+ return DIE_FIND_CB_CONTINUE;
}

-/* Compare diename and tname */
-static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
+/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
+static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
+ Dwarf_Die *die_mem)
{
- const char *name;
- name = dwarf_diename(dw_die);
- DIE_IF(name == NULL);
- return strcmp(tname, name);
+ return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
}

-/* Get entry pc(or low pc, 1st entry of ranges) of the die */
-static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
+static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
{
- Dwarf_Addr epc;
- int ret;
+ const char *name = data;
+ int tag;

- ret = dwarf_entrypc(dw_die, &epc);
- DIE_IF(ret == -1);
- return epc;
+ tag = dwarf_tag(die_mem);
+ if ((tag == DW_TAG_formal_parameter ||
+ tag == DW_TAG_variable) &&
+ (die_compare_name(die_mem, name) == 0))
+ return DIE_FIND_CB_FOUND;
+
+ return DIE_FIND_CB_CONTINUE;
}

-/* Get a variable die */
+/* Find a variable called 'name' */
static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name,
Dwarf_Die *die_mem)
{
- Dwarf_Die child_die;
- int tag;
- int ret;
-
- ret = dwarf_child(sp_die, die_mem);
- if (ret != 0)
- return NULL;
-
- do {
- tag = dwarf_tag(die_mem);
- if ((tag == DW_TAG_formal_parameter ||
- tag == DW_TAG_variable) &&
- (die_compare_name(die_mem, name) == 0))
- return die_mem;
-
- if (die_find_variable(die_mem, name, &child_die)) {
- memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
- return die_mem;
- }
- } while (dwarf_siblingof(die_mem, die_mem) == 0);
-
- return NULL;
+ return die_find_child(sp_die, __die_find_variable_cb, (void *)name,
+ die_mem);
}

/*
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/