From: tip-bot for Masami Hiramatsu <mhiramat@redhat.com>
To: linux-tip-commits@vger.kernel.org
Cc: acme@redhat.com, mingo@redhat.com, efault@gmx.de,
peterz@infradead.org, dle-develop@lists.sourceforge.net,
fweisbec@gmail.com, tglx@linutronix.de, mhiramat@redhat.com,
systemtap@sources.redhat.com, hpa@zytor.com, paulus@samba.org,
linux-kernel@vger.kernel.org, drepper@redhat.com,
ananth@in.ibm.com, roland@redhat.com, mingo@elte.hu,
prasad@linux.vnet.ibm.com
Subject: [tip:perf/probes] perf probe: Use libdw callback routines
Date: Thu, 25 Feb 2010 19:31:39 GMT [thread overview]
Message-ID: <tip-e92b85e1ffaa0bd8e5d92e7c378a3909e7f23122@git.kernel.org> (raw)
In-Reply-To: <20100225133549.6725.81499.stgit@localhost6.localdomain6>
Commit-ID: e92b85e1ffaa0bd8e5d92e7c378a3909e7f23122
Gitweb: http://git.kernel.org/tip/e92b85e1ffaa0bd8e5d92e7c378a3909e7f23122
Author: Masami Hiramatsu <mhiramat@redhat.com>
AuthorDate: Thu, 25 Feb 2010 08:35:50 -0500
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Thu, 25 Feb 2010 17:49:29 +0100
perf probe: Use libdw callback routines
Use libdw callback functions aggressively, and remove
local tree-search API. This change simplifies the code.
Changes in v3:
- Cast Dwarf_Addr to uintmax_t for printf-formats.
Changes in v2:
- Cast Dwarf_Addr to unsigned long long for printf-formats.
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: systemtap <systemtap@sources.redhat.com>
Cc: DLE <dle-develop@lists.sourceforge.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: K.Prasad <prasad@linux.vnet.ibm.com>
Cc: Ulrich Drepper <drepper@redhat.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
LKML-Reference: <20100225133549.6725.81499.stgit@localhost6.localdomain6>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
tools/perf/util/probe-finder.c | 262 +++++++++++++---------------------------
tools/perf/util/probe-finder.h | 1 -
2 files changed, 86 insertions(+), 177 deletions(-)
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index c422472..6305f34 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -38,13 +38,6 @@
#include "probe-finder.h"
-/* Dwarf_Die Linkage to parent Die */
-struct die_link {
- struct die_link *parent; /* Parent die */
- Dwarf_Die die; /* Current die */
-};
-
-
/*
* Generic dwarf analysis helpers
*/
@@ -177,26 +170,6 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
return strcmp(tname, name);
}
-/* Check the address is in the subprogram(function). */
-static bool die_within_subprogram(Dwarf_Die *sp_die, Dwarf_Addr addr,
- size_t *offs)
-{
- Dwarf_Addr epc;
- int ret;
-
- ret = dwarf_haspc(sp_die, addr);
- if (ret <= 0)
- return false;
-
- if (offs) {
- ret = dwarf_entrypc(sp_die, &epc);
- DIE_IF(ret == -1);
- *offs = addr - epc;
- }
-
- return true;
-}
-
/* Get entry pc(or low pc, 1st entry of ranges) of the die */
static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
{
@@ -208,70 +181,34 @@ static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
return epc;
}
-/* Check if the abstract origin's address or not */
-static bool die_compare_abstract_origin(Dwarf_Die *in_die, void *origin_addr)
-{
- Dwarf_Attribute attr;
- Dwarf_Die origin;
-
- if (!dwarf_attr(in_die, DW_AT_abstract_origin, &attr))
- return false;
- if (!dwarf_formref_die(&attr, &origin))
- return false;
-
- return origin.addr == origin_addr;
-}
-
-/*
- * Search a Die from Die tree.
- * Note: cur_link->die should be deallocated in this function.
- */
-static int __search_die_tree(struct die_link *cur_link,
- int (*die_cb)(struct die_link *, void *),
- void *data)
+/* Get a variable die */
+static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name,
+ Dwarf_Die *die_mem)
{
- struct die_link new_link;
+ Dwarf_Die child_die;
+ int tag;
int ret;
- if (!die_cb)
- return 0;
-
- /* Check current die */
- while (!(ret = die_cb(cur_link, data))) {
- /* Check child die */
- ret = dwarf_child(&cur_link->die, &new_link.die);
- if (ret == 0) {
- new_link.parent = cur_link;
- ret = __search_die_tree(&new_link, die_cb, data);
- if (ret)
- break;
- }
+ ret = dwarf_child(sp_die, die_mem);
+ if (ret != 0)
+ return NULL;
- /* Move to next sibling */
- ret = dwarf_siblingof(&cur_link->die, &cur_link->die);
- if (ret != 0)
- return 0;
- }
- return ret;
-}
+ 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;
-/* Search a die in its children's die tree */
-static int search_die_from_children(Dwarf_Die *parent_die,
- int (*die_cb)(struct die_link *, void *),
- void *data)
-{
- struct die_link new_link;
- int ret;
+ 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);
- new_link.parent = NULL;
- ret = dwarf_child(parent_die, &new_link.die);
- if (ret == 0)
- return __search_die_tree(&new_link, die_cb, data);
- else
- return 0;
+ return NULL;
}
-
/*
* Probe finder related functions
*/
@@ -347,28 +284,13 @@ error:
" Perhaps, it has been optimized out.", pf->var);
}
-static int variable_search_cb(struct die_link *dlink, void *data)
-{
- struct probe_finder *pf = (struct probe_finder *)data;
- int tag;
-
- tag = dwarf_tag(&dlink->die);
- DIE_IF(tag < 0);
- if ((tag == DW_TAG_formal_parameter ||
- tag == DW_TAG_variable) &&
- (die_compare_name(&dlink->die, pf->var) == 0)) {
- show_variable(&dlink->die, pf);
- return 1;
- }
- /* TODO: Support struct members and arrays */
- return 0;
-}
-
/* Find a variable in a subprogram die */
static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
{
int ret;
+ Dwarf_Die vr_die;
+ /* TODO: Support struct members and arrays */
if (!is_c_varname(pf->var)) {
/* Output raw parameters */
ret = snprintf(pf->buf, pf->len, " %s", pf->var);
@@ -379,31 +301,42 @@ static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
pr_debug("Searching '%s' variable in context.\n", pf->var);
/* Search child die for local variables and parameters. */
- ret = search_die_from_children(sp_die, variable_search_cb, pf);
- if (!ret)
+ if (!die_find_variable(sp_die, pf->var, &vr_die))
die("Failed to find '%s' in this function.", pf->var);
+
+ show_variable(&vr_die, pf);
}
/* Show a probe point to output buffer */
-static void show_probe_point(Dwarf_Die *sp_die, size_t offs,
- struct probe_finder *pf)
+static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
{
struct probe_point *pp = pf->pp;
+ Dwarf_Addr eaddr;
+ Dwarf_Die die_mem;
const char *name;
char tmp[MAX_PROBE_BUFFER];
int ret, i, len;
Dwarf_Attribute fb_attr;
size_t nops;
+ /* If no real subprogram, find a real one */
+ if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
+ sp_die = die_get_real_subprogram(&pf->cu_die,
+ pf->addr, &die_mem);
+ if (!sp_die)
+ die("Probe point is not found in subprograms.");
+ }
+
/* Output name of probe point */
name = dwarf_diename(sp_die);
if (name) {
- ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name,
- (unsigned int)offs);
+ dwarf_entrypc(sp_die, &eaddr);
+ ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%lu", name,
+ (unsigned long)(pf->addr - eaddr));
/* Copy the function name if possible */
if (!pp->function) {
pp->function = strdup(name);
- pp->offset = offs;
+ pp->offset = (size_t)(pf->addr - eaddr);
}
} else {
/* This function has no name. */
@@ -450,10 +383,9 @@ static void find_probe_point_by_line(struct probe_finder *pf)
Dwarf_Lines *lines;
Dwarf_Line *line;
size_t nlines, i;
- Dwarf_Addr addr, epc;
+ Dwarf_Addr addr;
int lineno;
int ret;
- Dwarf_Die *sp_die, die_mem;
ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines);
DIE_IF(ret != 0);
@@ -474,77 +406,57 @@ static void find_probe_point_by_line(struct probe_finder *pf)
(int)i, lineno, (uintmax_t)addr);
pf->addr = addr;
- sp_die = die_get_real_subprogram(&pf->cu_die, addr, &die_mem);
- if (!sp_die)
- die("Probe point is not found in subprograms.");
- dwarf_entrypc(sp_die, &epc);
- show_probe_point(sp_die, (size_t)(addr - epc), pf);
+ show_probe_point(NULL, pf);
/* Continuing, because target line might be inlined. */
}
}
+static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
+{
+ struct probe_finder *pf = (struct probe_finder *)data;
+ struct probe_point *pp = pf->pp;
+
+ /* Get probe address */
+ pf->addr = die_get_entrypc(in_die);
+ pf->addr += pp->offset;
+ pr_debug("found inline addr: 0x%jx\n", (uintmax_t)pf->addr);
+
+ show_probe_point(in_die, pf);
+ return DWARF_CB_OK;
+}
/* Search function from function name */
-static int probe_point_search_cb(struct die_link *dlink, void *data)
+static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
{
struct probe_finder *pf = (struct probe_finder *)data;
struct probe_point *pp = pf->pp;
- struct die_link *lk;
- size_t offs;
- int tag;
- int ret;
- tag = dwarf_tag(&dlink->die);
- if (tag == DW_TAG_subprogram) {
- if (die_compare_name(&dlink->die, pp->function) == 0) {
- if (pp->line) { /* Function relative line */
- pf->fname = dwarf_decl_file(&dlink->die);
- dwarf_decl_line(&dlink->die, &pf->lno);
- pf->lno += pp->line;
- find_probe_point_by_line(pf);
- return 1;
- }
- if (dwarf_func_inline(&dlink->die)) {
- /* Inlined function, save it. */
- pf->origin = dlink->die.addr;
- return 0; /* Continue to search */
- }
- /* Get probe address */
- pf->addr = die_get_entrypc(&dlink->die);
- pf->addr += pp->offset;
- /* TODO: Check the address in this function */
- show_probe_point(&dlink->die, pp->offset, pf);
- return 1; /* Exit; no same symbol in this CU. */
- }
- } else if (tag == DW_TAG_inlined_subroutine && pf->origin) {
- if (die_compare_abstract_origin(&dlink->die, pf->origin)) {
- /* Get probe address */
- pf->addr = die_get_entrypc(&dlink->die);
- pf->addr += pp->offset;
- pr_debug("found inline addr: 0x%jx\n",
- (uintmax_t)pf->addr);
- /* Inlined function. Get a real subprogram */
- for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
- tag = dwarf_tag(&lk->die);
- if (tag == DW_TAG_subprogram &&
- !dwarf_func_inline(&lk->die))
- goto found;
- }
- die("Failed to find real subprogram.");
-found:
- /* Get offset from subprogram */
- ret = die_within_subprogram(&lk->die, pf->addr, &offs);
- DIE_IF(!ret);
- show_probe_point(&lk->die, offs, pf);
- /* Continue to search */
- }
- }
- return 0;
+ /* Check tag and diename */
+ if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
+ die_compare_name(sp_die, pp->function) != 0)
+ return 0;
+
+ if (pp->line) { /* Function relative line */
+ pf->fname = dwarf_decl_file(sp_die);
+ dwarf_decl_line(sp_die, &pf->lno);
+ pf->lno += pp->line;
+ find_probe_point_by_line(pf);
+ } else if (!dwarf_func_inline(sp_die)) {
+ /* Real function */
+ pf->addr = die_get_entrypc(sp_die);
+ pf->addr += pp->offset;
+ /* TODO: Check the address in this function */
+ show_probe_point(sp_die, pf);
+ } else
+ /* Inlined function: search instances */
+ dwarf_func_inline_instances(sp_die, probe_point_inline_cb, pf);
+
+ return 1; /* Exit; no same symbol in this CU. */
}
static void find_probe_point_by_func(struct probe_finder *pf)
{
- search_die_from_children(&pf->cu_die, probe_point_search_cb, pf);
+ dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, pf, 0);
}
/* Find a probe point */
@@ -669,27 +581,25 @@ static void find_line_range_by_line(struct line_finder *lf)
}
/* Search function from function name */
-static int line_range_search_cb(struct die_link *dlink, void *data)
+static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
{
struct line_finder *lf = (struct line_finder *)data;
struct line_range *lr = lf->lr;
- int tag;
int ret;
- tag = dwarf_tag(&dlink->die);
- if (tag == DW_TAG_subprogram &&
- die_compare_name(&dlink->die, lr->function) == 0) {
+ if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
+ die_compare_name(sp_die, lr->function) == 0) {
/* Get the address range of this function */
- ret = dwarf_highpc(&dlink->die, &lf->addr_e);
+ ret = dwarf_highpc(sp_die, &lf->addr_e);
if (ret == 0)
- ret = dwarf_lowpc(&dlink->die, &lf->addr_s);
+ ret = dwarf_lowpc(sp_die, &lf->addr_s);
if (ret != 0) {
lf->addr_s = 0;
lf->addr_e = 0;
}
- lf->fname = dwarf_decl_file(&dlink->die);
- dwarf_decl_line(&dlink->die, &lr->offset);
+ lf->fname = dwarf_decl_file(sp_die);
+ dwarf_decl_line(sp_die, &lr->offset);
pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
lf->lno_s = lr->offset + lr->start;
if (!lr->end)
@@ -706,7 +616,7 @@ static int line_range_search_cb(struct die_link *dlink, void *data)
static void find_line_range_by_func(struct line_finder *lf)
{
- search_die_from_children(&lf->cu_die, line_range_search_cb, lf);
+ dwarf_getfuncs(&lf->cu_die, line_range_search_cb, lf, 0);
}
int find_line_range(int fd, struct line_range *lr)
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 9dd4a88..74525ae 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -66,7 +66,6 @@ struct probe_finder {
Dwarf_Addr addr; /* Address */
const char *fname; /* File name */
int lno; /* Line number */
- void *origin; /* Inline origin addr */
Dwarf_Die cu_die; /* Current CU */
/* For variable searching */
next prev parent reply other threads:[~2010-02-25 19:33 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-25 13:33 [PATCH -tip v3&10 00/18] perf-probe updates - optprobe, elfutils and lazy matching Masami Hiramatsu
2010-02-25 13:33 ` [PATCH -tip v3&10 01/18] kprobes/x86: Cleanup RELATIVEJUMP_INSTRUCTION to RELATIVEJUMP_OPCODE Masami Hiramatsu
2010-02-25 15:10 ` Mathieu Desnoyers
2010-02-25 19:27 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:33 ` [PATCH -tip v3&10 02/18] kprobes: Introduce generic insn_slot framework Masami Hiramatsu
2010-02-25 15:21 ` Mathieu Desnoyers
2010-03-02 2:55 ` Masami Hiramatsu
2010-03-03 0:18 ` Masami Hiramatsu
2010-03-03 0:32 ` Mathieu Desnoyers
2010-03-03 0:35 ` Masami Hiramatsu
2010-02-25 19:28 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 03/18] kprobes: Introduce kprobes jump optimization Masami Hiramatsu
2010-02-25 19:28 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 04/18] kprobes: Jump optimization sysctl interface Masami Hiramatsu
2010-02-25 19:28 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 05/18] kprobes/x86: Boost probes when reentering Masami Hiramatsu
2010-02-25 19:29 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 06/18] kprobes/x86: Cleanup save/restore registers Masami Hiramatsu
2010-02-25 19:29 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 07/18] x86: Add text_poke_smp for SMP cross modifying code Masami Hiramatsu
2010-02-25 15:33 ` Mathieu Desnoyers
2010-02-26 3:53 ` Masami Hiramatsu
2010-03-03 0:48 ` Mathieu Desnoyers
2010-03-03 0:56 ` Masami Hiramatsu
2010-02-25 19:29 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:34 ` [PATCH -tip v3&10 08/18] kprobes/x86: Support kprobes jump optimization on x86 Masami Hiramatsu
2010-02-25 19:29 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 09/18] kprobes: Add documents of jump optimization Masami Hiramatsu
2010-02-25 19:30 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 10/18] perf probe: Do not show --line option without dwarf support Masami Hiramatsu
2010-02-25 19:30 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 11/18] perf probe: Update perf probe document Masami Hiramatsu
2010-02-25 19:30 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 12/18] perf probe: Fix bugs in line range finder Masami Hiramatsu
2010-02-25 19:30 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 13/18] perf probe: Rename probe finder functions Masami Hiramatsu
2010-02-25 19:31 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 14/18] perf probe: Use elfutils-libdw for analyzing debuginfo Masami Hiramatsu
2010-02-25 19:31 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:35 ` [PATCH -tip v3&10 15/18] perf probe: Use libdw callback routines Masami Hiramatsu
2010-02-25 19:31 ` tip-bot for Masami Hiramatsu [this message]
2010-02-25 13:35 ` [PATCH -tip v3&10 16/18] perf probe: Check function address range strictly in line finder Masami Hiramatsu
2010-02-25 19:31 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
2010-02-25 13:36 ` [PATCH -tip v3&10 17/18] perf probe: show more lines after last line Masami Hiramatsu
2010-02-25 19:32 ` [tip:perf/probes] perf probe: Show " tip-bot for Masami Hiramatsu
2010-02-25 13:36 ` [PATCH -tip v3&10 18/18] perf probe: Add lazy line matching support Masami Hiramatsu
2010-02-25 19:32 ` [tip:perf/probes] " tip-bot for Masami Hiramatsu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=tip-e92b85e1ffaa0bd8e5d92e7c378a3909e7f23122@git.kernel.org \
--to=mhiramat@redhat.com \
--cc=acme@redhat.com \
--cc=ananth@in.ibm.com \
--cc=dle-develop@lists.sourceforge.net \
--cc=drepper@redhat.com \
--cc=efault@gmx.de \
--cc=fweisbec@gmail.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tip-commits@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=mingo@redhat.com \
--cc=paulus@samba.org \
--cc=peterz@infradead.org \
--cc=prasad@linux.vnet.ibm.com \
--cc=roland@redhat.com \
--cc=systemtap@sources.redhat.com \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.