aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-02-25 08:35:50 -0500
committerIngo Molnar <mingo@elte.hu>2010-02-25 11:49:29 -0500
commite92b85e1ffaa0bd8e5d92e7c378a3909e7f23122 (patch)
tree6bd934ca363a3529ad4ecb1112c1d2c70c13089b
parent804b36068eccd8163ccea420c662fb5d1a21b141 (diff)
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>
-rw-r--r--tools/perf/util/probe-finder.c262
-rw-r--r--tools/perf/util/probe-finder.h1
2 files changed, 86 insertions, 177 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index c422472fe4d1..6305f344f382 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -38,13 +38,6 @@
38#include "probe-finder.h" 38#include "probe-finder.h"
39 39
40 40
41/* Dwarf_Die Linkage to parent Die */
42struct die_link {
43 struct die_link *parent; /* Parent die */
44 Dwarf_Die die; /* Current die */
45};
46
47
48/* 41/*
49 * Generic dwarf analysis helpers 42 * Generic dwarf analysis helpers
50 */ 43 */
@@ -177,26 +170,6 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
177 return strcmp(tname, name); 170 return strcmp(tname, name);
178} 171}
179 172
180/* Check the address is in the subprogram(function). */
181static bool die_within_subprogram(Dwarf_Die *sp_die, Dwarf_Addr addr,
182 size_t *offs)
183{
184 Dwarf_Addr epc;
185 int ret;
186
187 ret = dwarf_haspc(sp_die, addr);
188 if (ret <= 0)
189 return false;
190
191 if (offs) {
192 ret = dwarf_entrypc(sp_die, &epc);
193 DIE_IF(ret == -1);
194 *offs = addr - epc;
195 }
196
197 return true;
198}
199
200/* Get entry pc(or low pc, 1st entry of ranges) of the die */ 173/* Get entry pc(or low pc, 1st entry of ranges) of the die */
201static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die) 174static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
202{ 175{
@@ -208,70 +181,34 @@ static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
208 return epc; 181 return epc;
209} 182}
210 183
211/* Check if the abstract origin's address or not */ 184/* Get a variable die */
212static bool die_compare_abstract_origin(Dwarf_Die *in_die, void *origin_addr) 185static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name,
213{ 186 Dwarf_Die *die_mem)
214 Dwarf_Attribute attr;
215 Dwarf_Die origin;
216
217 if (!dwarf_attr(in_die, DW_AT_abstract_origin, &attr))
218 return false;
219 if (!dwarf_formref_die(&attr, &origin))
220 return false;
221
222 return origin.addr == origin_addr;
223}
224
225/*
226 * Search a Die from Die tree.
227 * Note: cur_link->die should be deallocated in this function.
228 */
229static int __search_die_tree(struct die_link *cur_link,
230 int (*die_cb)(struct die_link *, void *),
231 void *data)
232{ 187{
233 struct die_link new_link; 188 Dwarf_Die child_die;
189 int tag;
234 int ret; 190 int ret;
235 191
236 if (!die_cb) 192 ret = dwarf_child(sp_die, die_mem);
237 return 0; 193 if (ret != 0)
238 194 return NULL;
239 /* Check current die */
240 while (!(ret = die_cb(cur_link, data))) {
241 /* Check child die */
242 ret = dwarf_child(&cur_link->die, &new_link.die);
243 if (ret == 0) {
244 new_link.parent = cur_link;
245 ret = __search_die_tree(&new_link, die_cb, data);
246 if (ret)
247 break;
248 }
249 195
250 /* Move to next sibling */ 196 do {
251 ret = dwarf_siblingof(&cur_link->die, &cur_link->die); 197 tag = dwarf_tag(die_mem);
252 if (ret != 0) 198 if ((tag == DW_TAG_formal_parameter ||
253 return 0; 199 tag == DW_TAG_variable) &&
254 } 200 (die_compare_name(die_mem, name) == 0))
255 return ret; 201 return die_mem;
256}
257 202
258/* Search a die in its children's die tree */ 203 if (die_find_variable(die_mem, name, &child_die)) {
259static int search_die_from_children(Dwarf_Die *parent_die, 204 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
260 int (*die_cb)(struct die_link *, void *), 205 return die_mem;
261 void *data) 206 }
262{ 207 } while (dwarf_siblingof(die_mem, die_mem) == 0);
263 struct die_link new_link;
264 int ret;
265 208
266 new_link.parent = NULL; 209 return NULL;
267 ret = dwarf_child(parent_die, &new_link.die);
268 if (ret == 0)
269 return __search_die_tree(&new_link, die_cb, data);
270 else
271 return 0;
272} 210}
273 211
274
275/* 212/*
276 * Probe finder related functions 213 * Probe finder related functions
277 */ 214 */
@@ -347,28 +284,13 @@ error:
347 " Perhaps, it has been optimized out.", pf->var); 284 " Perhaps, it has been optimized out.", pf->var);
348} 285}
349 286
350static int variable_search_cb(struct die_link *dlink, void *data)
351{
352 struct probe_finder *pf = (struct probe_finder *)data;
353 int tag;
354
355 tag = dwarf_tag(&dlink->die);
356 DIE_IF(tag < 0);
357 if ((tag == DW_TAG_formal_parameter ||
358 tag == DW_TAG_variable) &&
359 (die_compare_name(&dlink->die, pf->var) == 0)) {
360 show_variable(&dlink->die, pf);
361 return 1;
362 }
363 /* TODO: Support struct members and arrays */
364 return 0;
365}
366
367/* Find a variable in a subprogram die */ 287/* Find a variable in a subprogram die */
368static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) 288static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
369{ 289{
370 int ret; 290 int ret;
291 Dwarf_Die vr_die;
371 292
293 /* TODO: Support struct members and arrays */
372 if (!is_c_varname(pf->var)) { 294 if (!is_c_varname(pf->var)) {
373 /* Output raw parameters */ 295 /* Output raw parameters */
374 ret = snprintf(pf->buf, pf->len, " %s", pf->var); 296 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)
379 301
380 pr_debug("Searching '%s' variable in context.\n", pf->var); 302 pr_debug("Searching '%s' variable in context.\n", pf->var);
381 /* Search child die for local variables and parameters. */ 303 /* Search child die for local variables and parameters. */
382 ret = search_die_from_children(sp_die, variable_search_cb, pf); 304 if (!die_find_variable(sp_die, pf->var, &vr_die))
383 if (!ret)
384 die("Failed to find '%s' in this function.", pf->var); 305 die("Failed to find '%s' in this function.", pf->var);
306
307 show_variable(&vr_die, pf);
385} 308}
386 309
387/* Show a probe point to output buffer */ 310/* Show a probe point to output buffer */
388static void show_probe_point(Dwarf_Die *sp_die, size_t offs, 311static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)