aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-04-14 16:44:00 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-04-14 16:44:00 -0400
commitde1439d8a521d22c3219fc007a570fcf944ac789 (patch)
tree17bc608b33d09bbd23fccf8d4b3fcc007b26b1a6 /tools/perf/util/probe-finder.c
parentdda4ab34fe1905d3d590572b776dd92aa0866558 (diff)
perf probe: Support DW_OP_plus_uconst in DW_AT_data_member_location
DW_OP_plus_uconst can be used for DW_AT_data_member_location. This patch adds DW_OP_plus_uconst support when getting structure member offset. Commiter note: Fixed up the size_t format specifier in one case: cc1: warnings being treated as errors util/probe-finder.c: In function ‘die_get_data_member_location’: util/probe-finder.c:270: error: format ‘%d’ expects type ‘int’, but argument 4 has type ‘size_t’ make: *** [/home/acme/git/build/perf/util/probe-finder.o] Error 1 LKML-Reference: <20100414223958.14630.5230.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r--tools/perf/util/probe-finder.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index b4c93659929a..03b469197a03 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -249,6 +249,33 @@ static int die_get_byte_size(Dwarf_Die *tp_die)
249 return (int)ret; 249 return (int)ret;
250} 250}
251 251
252/* Get data_member_location offset */
253static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
254{
255 Dwarf_Attribute attr;
256 Dwarf_Op *expr;
257 size_t nexpr;
258 int ret;
259
260 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
261 return -ENOENT;
262
263 if (dwarf_formudata(&attr, offs) != 0) {
264 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
265 ret = dwarf_getlocation(&attr, &expr, &nexpr);
266 if (ret < 0 || nexpr == 0)
267 return -ENOENT;
268
269 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
270 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
271 expr[0].atom, nexpr);
272 return -ENOTSUP;
273 }
274 *offs = (Dwarf_Word)expr[0].number;
275 }
276 return 0;
277}
278
252/* Return values for die_find callbacks */ 279/* Return values for die_find callbacks */
253enum { 280enum {
254 DIE_FIND_CB_FOUND = 0, /* End of Search */ 281 DIE_FIND_CB_FOUND = 0, /* End of Search */
@@ -482,9 +509,9 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
482 Dwarf_Die *die_mem) 509 Dwarf_Die *die_mem)
483{ 510{
484 struct kprobe_trace_arg_ref *ref = *ref_ptr; 511 struct kprobe_trace_arg_ref *ref = *ref_ptr;
485 Dwarf_Attribute attr;
486 Dwarf_Die type; 512 Dwarf_Die type;
487 Dwarf_Word offs; 513 Dwarf_Word offs;
514 int ret;
488 515
489 pr_debug("converting %s in %s\n", field->name, varname); 516 pr_debug("converting %s in %s\n", field->name, varname);
490 if (die_get_real_type(vr_die, &type) == NULL) { 517 if (die_get_real_type(vr_die, &type) == NULL) {
@@ -542,17 +569,17 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
542 } 569 }
543 570
544 /* Get the offset of the field */ 571 /* Get the offset of the field */
545 if (dwarf_attr(die_mem, DW_AT_data_member_location, &attr) == NULL || 572 ret = die_get_data_member_location(die_mem, &offs);
546 dwarf_formudata(&attr, &offs) != 0) { 573 if (ret < 0) {
547 pr_warning("Failed to get the offset of %s.\n", field->name); 574 pr_warning("Failed to get the offset of %s.\n", field->name);
548 return -ENOENT; 575 return ret;
549 } 576 }
550 ref->offset += (long)offs; 577 ref->offset += (long)offs;
551 578
552 /* Converting next field */ 579 /* Converting next field */
553 if (field->next) 580 if (field->next)
554 return convert_variable_fields(die_mem, field->name, 581 return convert_variable_fields(die_mem, field->name,
555 field->next, &ref, die_mem); 582 field->next, &ref, die_mem);
556 else 583 else
557 return 0; 584 return 0;
558} 585}