diff options
Diffstat (limited to 'tools')
| -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 | } |
