perf tests: Fix dwarf unwind for stripped binaries

When we strip the perf binary, dwarf unwind test stop
to work. The reason is that strip will remove static
function symbols, which we need to check for unwind.

This change will keep this test working in cases where
the global symbols are put into dynamic symbol table,
which is the case on x86. It still won't work on powerpc.

Making those 5 local functions global, and adding
'test_dwarf_unwind__' to their names.

Committer testing:

Before:

  # perf test dwarf
  58: DWARF unwind                               : Ok
  # strip ~/bin/perf
  # perf test dwarf
  58: DWARF unwind                               : FAILED!
  # perf test -v dwarf
  58: DWARF unwind                               :
  --- start ---
  test child forked, pid 6590
  unwind: thread map already set, dso=/home/acme/bin/perf
  <SNIP>
  unwind: access_mem addr 0x7ffce6c48098 val 48563f, offset 1144
  unwind: test__dwarf_unwind:ip = 0x4a54e5 (0xa54e5)
  got: test__dwarf_unwind 0xa54e5, expecting test__dwarf_unwind
  unwind: '':ip = 0x4a50bb (0xa50bb)
  failed: got unresolved address 0xa50bb
  unwind failed
  test child finished with -1
  ---- end ----
  DWARF unwind: FAILED!
  #

After:

  # perf test dwarf
  58: DWARF unwind                               : Ok
  # strip ~/bin/perf
  # perf test dwarf
  58: DWARF unwind                               : Ok
  #
  # perf test -v dwarf
  58: DWARF unwind                               :
  --- start ---
  test child forked, pid 7219
  unwind: thread map already set, dso=/home/acme/bin/perf
  <SNIP>
  unwind: access_mem addr 0x7fff007da2c8 val 48575f, offset 1144
  unwind: test__arch_unwind_sample:ip = 0x589044 (0x189044)
  got: test__arch_unwind_sample 0x189044, expecting test__arch_unwind_sample
  unwind: test_dwarf_unwind__thread:ip = 0x4a52f7 (0xa52f7)
  got: test_dwarf_unwind__thread 0xa52f7, expecting test_dwarf_unwind__thread
  unwind: test_dwarf_unwind__compare:ip = 0x4a5468 (0xa5468)
  got: test_dwarf_unwind__compare 0xa5468, expecting test_dwarf_unwind__compare
  unwind: bsearch:ip = 0x7f6608ae94d8 (0x394d8)
  got: bsearch 0x394d8, expecting bsearch
  unwind: test_dwarf_unwind__krava_3:ip = 0x4a54d1 (0xa54d1)
  got: test_dwarf_unwind__krava_3 0xa54d1, expecting test_dwarf_unwind__krava_3
  unwind: test_dwarf_unwind__krava_2:ip = 0x4a550b (0xa550b)
  got: test_dwarf_unwind__krava_2 0xa550b, expecting test_dwarf_unwind__krava_2
  unwind: test_dwarf_unwind__krava_1:ip = 0x4a554b (0xa554b)
  got: test_dwarf_unwind__krava_1 0xa554b, expecting test_dwarf_unwind__krava_1
  unwind: test__dwarf_unwind:ip = 0x4a5605 (0xa5605)
  got: test__dwarf_unwind 0xa5605, expecting test__dwarf_unwind
  test child finished with 0
  ---- end ----
  DWARF unwind: Ok
  #

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180206181813.10943-17-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Jiri Olsa 2018-02-06 19:18:12 +01:00 committed by Arnaldo Carvalho de Melo
parent d9c5f32240
commit fdf7c49c20

View File

@ -37,6 +37,19 @@ static int init_live_machine(struct machine *machine)
mmap_handler, machine, true, 500);
}
/*
* We need to keep these functions global, despite the
* fact that they are used only locally in this object,
* in order to keep them around even if the binary is
* stripped. If they are gone, the unwind check for
* symbol fails.
*/
int test_dwarf_unwind__thread(struct thread *thread);
int test_dwarf_unwind__compare(void *p1, void *p2);
int test_dwarf_unwind__krava_3(struct thread *thread);
int test_dwarf_unwind__krava_2(struct thread *thread);
int test_dwarf_unwind__krava_1(struct thread *thread);
#define MAX_STACK 8
static int unwind_entry(struct unwind_entry *entry, void *arg)
@ -45,12 +58,12 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
char *symbol = entry->sym ? entry->sym->name : NULL;
static const char *funcs[MAX_STACK] = {
"test__arch_unwind_sample",
"unwind_thread",
"compare",
"test_dwarf_unwind__thread",
"test_dwarf_unwind__compare",
"bsearch",
"krava_3",
"krava_2",
"krava_1",
"test_dwarf_unwind__krava_3",
"test_dwarf_unwind__krava_2",
"test_dwarf_unwind__krava_1",
"test__dwarf_unwind"
};
/*
@ -77,7 +90,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
return strcmp((const char *) symbol, funcs[idx]);
}
static noinline int unwind_thread(struct thread *thread)
noinline int test_dwarf_unwind__thread(struct thread *thread)
{
struct perf_sample sample;
unsigned long cnt = 0;
@ -108,7 +121,7 @@ static noinline int unwind_thread(struct thread *thread)
static int global_unwind_retval = -INT_MAX;
static noinline int compare(void *p1, void *p2)
noinline int test_dwarf_unwind__compare(void *p1, void *p2)
{
/* Any possible value should be 'thread' */
struct thread *thread = *(struct thread **)p1;
@ -117,17 +130,17 @@ static noinline int compare(void *p1, void *p2)
/* Call unwinder twice for both callchain orders. */
callchain_param.order = ORDER_CALLER;
global_unwind_retval = unwind_thread(thread);
global_unwind_retval = test_dwarf_unwind__thread(thread);
if (!global_unwind_retval) {
callchain_param.order = ORDER_CALLEE;
global_unwind_retval = unwind_thread(thread);
global_unwind_retval = test_dwarf_unwind__thread(thread);
}
}
return p1 - p2;
}
static noinline int krava_3(struct thread *thread)
noinline int test_dwarf_unwind__krava_3(struct thread *thread)
{
struct thread *array[2] = {thread, thread};
void *fp = &bsearch;
@ -141,18 +154,19 @@ static noinline int krava_3(struct thread *thread)
size_t, int (*)(void *, void *));
_bsearch = fp;
_bsearch(array, &thread, 2, sizeof(struct thread **), compare);
_bsearch(array, &thread, 2, sizeof(struct thread **),
test_dwarf_unwind__compare);
return global_unwind_retval;
}
static noinline int krava_2(struct thread *thread)
noinline int test_dwarf_unwind__krava_2(struct thread *thread)
{
return krava_3(thread);
return test_dwarf_unwind__krava_3(thread);
}
static noinline int krava_1(struct thread *thread)
noinline int test_dwarf_unwind__krava_1(struct thread *thread)
{
return krava_2(thread);
return test_dwarf_unwind__krava_2(thread);
}
int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused)
@ -189,7 +203,7 @@ int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unu
goto out;
}
err = krava_1(thread);
err = test_dwarf_unwind__krava_1(thread);
thread__put(thread);
out: