Commit c7273835 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Arnaldo Carvalho de Melo

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: default avatarArnaldo Carvalho de Melo <acme@kernel.org>
Report-Link: https://lkml.org/lkml/2015/3/5/431Signed-off-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: default avatarArnaldo 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.localdomainSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent b83e868d
...@@ -801,10 +801,16 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data) ...@@ -801,10 +801,16 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
{ {
const char *name = data; const char *name = data;
if ((dwarf_tag(die_mem) == DW_TAG_member) && if (dwarf_tag(die_mem) == DW_TAG_member) {
die_compare_name(die_mem, name)) if (die_compare_name(die_mem, name))
return DIE_FIND_CB_END; return DIE_FIND_CB_END;
else if (!dwarf_diename(die_mem)) { /* Unnamed structure */
Dwarf_Die type_die, tmp_die;
if (die_get_type(die_mem, &type_die) &&
die_find_member(&type_die, name, &tmp_die))
return DIE_FIND_CB_END;
}
}
return DIE_FIND_CB_SIBLING; return DIE_FIND_CB_SIBLING;
} }
......
...@@ -460,7 +460,8 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, ...@@ -460,7 +460,8 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
" nor array.\n", varname); " nor array.\n", varname);
return -EINVAL; return -EINVAL;
} }
if (field->ref) { /* While prcessing unnamed field, we don't care about this */
if (field->ref && dwarf_diename(vr_die)) {
pr_err("Semantic error: %s must be referred by '.'\n", pr_err("Semantic error: %s must be referred by '.'\n",
field->name); field->name);
return -EINVAL; return -EINVAL;
...@@ -491,6 +492,11 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, ...@@ -491,6 +492,11 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
} }
ref->offset += (long)offs; ref->offset += (long)offs;
/* If this member is unnamed, we need to reuse this field */
if (!dwarf_diename(die_mem))
return convert_variable_fields(die_mem, varname, field,
&ref, die_mem);
next: next:
/* Converting next field */ /* Converting next field */
if (field->next) if (field->next)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment