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

perf probe: Fix to show lines of sys_ functions correctly

"perf probe --lines sys_poll" shows only the first line of sys_poll,
because the SYSCALL_DEFINE macro:

  ----
  SYSCALL_DEFINE*(foo,...)
  {
    body;
  }
  ----

  is expanded as below (on debuginfo)

  ----

  static inline int SYSC_foo(...)
  {
    body;
  }
  int SyS_foo(...) <- is an alias of sys_foo.
  {
    return SYSC_foo(...);
  }
  ----

So, "perf probe --lines sys_foo" decodes SyS_foo function and it also skips
inlined functions(SYSC_foo) inside the target function because those functions
are usually defined somewhere else.

To fix this issue, this fix checks whether the inlined function is defined at
the same point of the target function, and if so, it doesn't skip the inline
function.
Reported-by: default avatarArnaldo Carvalho de Melo <acme@kernel.org>
Signed-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>
Link: http://lkml.kernel.org/r/20150812012406.11811.94691.stgit@localhost.localdomainSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 63ab1749
...@@ -734,15 +734,18 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) ...@@ -734,15 +734,18 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
Dwarf_Lines *lines; Dwarf_Lines *lines;
Dwarf_Line *line; Dwarf_Line *line;
Dwarf_Addr addr; Dwarf_Addr addr;
const char *fname; const char *fname, *decf = NULL;
int lineno, ret = 0; int lineno, ret = 0;
int decl = 0, inl;
Dwarf_Die die_mem, *cu_die; Dwarf_Die die_mem, *cu_die;
size_t nlines, i; size_t nlines, i;
/* Get the CU die */ /* Get the CU die */
if (dwarf_tag(rt_die) != DW_TAG_compile_unit) if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL); cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
else dwarf_decl_line(rt_die, &decl);
decf = dwarf_decl_file(rt_die);
} else
cu_die = rt_die; cu_die = rt_die;
if (!cu_die) { if (!cu_die) {
pr_debug2("Failed to get CU from given DIE.\n"); pr_debug2("Failed to get CU from given DIE.\n");
...@@ -773,9 +776,14 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) ...@@ -773,9 +776,14 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
* The line is included in given function, and * The line is included in given function, and
* no inline block includes it. * no inline block includes it.
*/ */
if (!dwarf_haspc(rt_die, addr) || if (!dwarf_haspc(rt_die, addr))
die_find_inlinefunc(rt_die, addr, &die_mem))
continue; continue;
if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
dwarf_decl_line(&die_mem, &inl);
if (inl != decl ||
decf != dwarf_decl_file(&die_mem))
continue;
}
/* Get source line */ /* Get source line */
fname = dwarf_linesrc(line, NULL, NULL); fname = dwarf_linesrc(line, NULL, NULL);
......
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