Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf probe: Fix to track down unnamed union/structure members

Fix 'perf probe' to track down unnamed union/structure members.

perf probe did not track down the tree of unnamed union/structure
members, since it just failed to find given "name" in a parent
structure/union. To solve this issue, I've introduced 2 changes.

- Fix die_find_member() to track down the type-DIE if it is
unnamed, and if it contains the specified member, returns the
unnamed member.
(note that we don't return found member, since unnamed member
has the offset in the parent structure)
- Fix convert_variable_fields() to track down the unnamed union/
structure (one-by-one).

With this patch, perf probe can access unnamed fields:
-----
#./perf probe -nfx ./perf lock__delete ops 'locked_ops=ops->locked.ops'
Added new event:
probe_perf:lock__delete (on lock__delete in /home/mhiramat/ksrc/linux-3/tools/perf/perf with ops locked_ops=ops->locked.ops)

You can now use it in all perf tools, such as:

perf record -e probe_perf:lock__delete -aR sleep 1
-----

Reported-by: Arnaldo Carvalho de Melo <acme@kernel.org>
Report-Link: https://lkml.org/lkml/2015/3/5/431
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150402073312.14482.37942.stgit@localhost.localdomain
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Masami Hiramatsu and committed by
Arnaldo Carvalho de Melo
c7273835 b83e868d

+17 -5
+10 -4
tools/perf/util/dwarf-aux.c
··· 801 801 { 802 802 const char *name = data; 803 803 804 - if ((dwarf_tag(die_mem) == DW_TAG_member) && 805 - die_compare_name(die_mem, name)) 806 - return DIE_FIND_CB_END; 807 - 804 + if (dwarf_tag(die_mem) == DW_TAG_member) { 805 + if (die_compare_name(die_mem, name)) 806 + return DIE_FIND_CB_END; 807 + else if (!dwarf_diename(die_mem)) { /* Unnamed structure */ 808 + Dwarf_Die type_die, tmp_die; 809 + if (die_get_type(die_mem, &type_die) && 810 + die_find_member(&type_die, name, &tmp_die)) 811 + return DIE_FIND_CB_END; 812 + } 813 + } 808 814 return DIE_FIND_CB_SIBLING; 809 815 } 810 816
+7 -1
tools/perf/util/probe-finder.c
··· 460 460 " nor array.\n", varname); 461 461 return -EINVAL; 462 462 } 463 - if (field->ref) { 463 + /* While prcessing unnamed field, we don't care about this */ 464 + if (field->ref && dwarf_diename(vr_die)) { 464 465 pr_err("Semantic error: %s must be referred by '.'\n", 465 466 field->name); 466 467 return -EINVAL; ··· 491 490 } 492 491 } 493 492 ref->offset += (long)offs; 493 + 494 + /* If this member is unnamed, we need to reuse this field */ 495 + if (!dwarf_diename(die_mem)) 496 + return convert_variable_fields(die_mem, varname, field, 497 + &ref, die_mem); 494 498 495 499 next: 496 500 /* Converting next field */