diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2010-04-14 16:44:00 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-04-14 16:44:00 -0400 |
commit | de1439d8a521d22c3219fc007a570fcf944ac789 (patch) | |
tree | 17bc608b33d09bbd23fccf8d4b3fcc007b26b1a6 /tools/perf/util/probe-finder.c | |
parent | dda4ab34fe1905d3d590572b776dd92aa0866558 (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.c | 37 |
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 */ | ||
253 | static 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 */ |
253 | enum { | 280 | enum { |
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 | } |