mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-24 21:24:00 +08:00
1934adf78e
We currently fail the MMAP event processing if we don't have the MMAP event's specific arch unwind support compiled in. That's wrong and can lead to unresolved mmaps in report output for 32bit binaries on 64bit server, like in this example on x86_64 server: $ cat ex.c int main(int argc, char **argv) { while (1) {} } $ gcc -o ex -m32 ex.c $ perf record ./ex ^C[ perf record: Woken up 2 times to write data ] [ perf record: Captured and wrote 0.371 MB perf.data (9322 samples) ] Before: $ perf report --stdio SNIP # Overhead Command Shared Object Symbol # ........ ....... ................ ...................... # 100.00% ex [unknown] [.] 0x00000000080483de 0.00% ex [unknown] [.] 0x00000000f76dba4f 0.00% ex [unknown] [.] 0x00000000f76e4c11 0.00% ex [unknown] [.] 0x00000000f76daa30 After: $ perf report --stdio SNIP # Overhead Command Shared Object Symbol # ........ ....... ............. ............... # 100.00% ex ex [.] main 0.00% ex ld-2.24.so [.] _dl_start 0.00% ex ld-2.24.so [.] do_lookup_x 0.00% ex ld-2.24.so [.] _start The fix is not to fail, just warn if there's not unwind support compiled in. Reported-by: Michael Lyle <mlyle@lyle.org> Signed-off-by: Jiri Olsa <jolsa@kernel.org> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: David Ahern <dsahern@gmail.com> Cc: He Kuang <hekuang@huawei.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/20170704131131.27508-1-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
84 lines
2.1 KiB
C
84 lines
2.1 KiB
C
#include "unwind.h"
|
|
#include "thread.h"
|
|
#include "session.h"
|
|
#include "debug.h"
|
|
#include "arch/common.h"
|
|
|
|
struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops;
|
|
struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops;
|
|
struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops;
|
|
|
|
static void unwind__register_ops(struct thread *thread,
|
|
struct unwind_libunwind_ops *ops)
|
|
{
|
|
thread->unwind_libunwind_ops = ops;
|
|
}
|
|
|
|
int unwind__prepare_access(struct thread *thread, struct map *map,
|
|
bool *initialized)
|
|
{
|
|
const char *arch;
|
|
enum dso_type dso_type;
|
|
struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops;
|
|
int err;
|
|
|
|
if (thread->addr_space) {
|
|
pr_debug("unwind: thread map already set, dso=%s\n",
|
|
map->dso->name);
|
|
if (initialized)
|
|
*initialized = true;
|
|
return 0;
|
|
}
|
|
|
|
/* env->arch is NULL for live-mode (i.e. perf top) */
|
|
if (!thread->mg->machine->env || !thread->mg->machine->env->arch)
|
|
goto out_register;
|
|
|
|
dso_type = dso__type(map->dso, thread->mg->machine);
|
|
if (dso_type == DSO__TYPE_UNKNOWN)
|
|
return 0;
|
|
|
|
arch = normalize_arch(thread->mg->machine->env->arch);
|
|
|
|
if (!strcmp(arch, "x86")) {
|
|
if (dso_type != DSO__TYPE_64BIT)
|
|
ops = x86_32_unwind_libunwind_ops;
|
|
} else if (!strcmp(arch, "arm64") || !strcmp(arch, "arm")) {
|
|
if (dso_type == DSO__TYPE_64BIT)
|
|
ops = arm64_unwind_libunwind_ops;
|
|
}
|
|
|
|
if (!ops) {
|
|
pr_err("unwind: target platform=%s is not supported\n", arch);
|
|
return 0;
|
|
}
|
|
out_register:
|
|
unwind__register_ops(thread, ops);
|
|
|
|
err = thread->unwind_libunwind_ops->prepare_access(thread);
|
|
if (initialized)
|
|
*initialized = err ? false : true;
|
|
return err;
|
|
}
|
|
|
|
void unwind__flush_access(struct thread *thread)
|
|
{
|
|
if (thread->unwind_libunwind_ops)
|
|
thread->unwind_libunwind_ops->flush_access(thread);
|
|
}
|
|
|
|
void unwind__finish_access(struct thread *thread)
|
|
{
|
|
if (thread->unwind_libunwind_ops)
|
|
thread->unwind_libunwind_ops->finish_access(thread);
|
|
}
|
|
|
|
int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
|
|
struct thread *thread,
|
|
struct perf_sample *data, int max_stack)
|
|
{
|
|
if (thread->unwind_libunwind_ops)
|
|
return thread->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
|
|
return 0;
|
|
}
|