diff options
author | Igor Nabirushkin <inabirushkin@nvidia.com> | 2014-08-22 19:46:15 +0400 |
---|---|---|
committer | Winnie Hsu <whsu@nvidia.com> | 2015-01-29 22:01:31 -0800 |
commit | 6fb43a5f1c04e04b83cef5c1fa22d9f460596efa (patch) | |
tree | 82c062e0634441390365cb15458be21ef9de5207 /drivers/misc/tegra-profiler/backtrace.c | |
parent | 35bf638737a5f9d09ea420c4fee690a76f6f2b2a (diff) |
misc: tegra-profiler: support dwarf unwinding
Add implementation of a dwarf unwinding for AArch64.
Bug 1465331
Bug 1598009
Change-Id: I1ff0c5411fe63ea5b7291c53c1d5a1d1cde59c25
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/486989
(cherry picked from commit f00783180ee09c5698463a39bed62c08ef17802a)
Reviewed-on: http://git-master/r/672019
GVS: Gerrit_Virtual_Submit
Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Diffstat (limited to 'drivers/misc/tegra-profiler/backtrace.c')
-rw-r--r-- | drivers/misc/tegra-profiler/backtrace.c | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/drivers/misc/tegra-profiler/backtrace.c b/drivers/misc/tegra-profiler/backtrace.c index f16cdabc8f77..e9f01471a594 100644 --- a/drivers/misc/tegra-profiler/backtrace.c +++ b/drivers/misc/tegra-profiler/backtrace.c @@ -1,7 +1,7 @@ /* * drivers/misc/tegra-profiler/backtrace.c * - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -25,6 +25,7 @@ #include "quadd.h" #include "backtrace.h" #include "eh_unwind.h" +#include "dwarf_unwind.h" static inline int is_thumb_mode(struct pt_regs *regs) @@ -47,8 +48,8 @@ quadd_user_stack_pointer(struct pt_regs *regs) return user_stack_pointer(regs); } -static inline unsigned long -get_user_frame_pointer(struct pt_regs *regs) +unsigned long +quadd_get_user_frame_pointer(struct pt_regs *regs) { unsigned long fp; @@ -111,6 +112,19 @@ quadd_callchain_store(struct quadd_callchain *cc, return 1; } +static int +is_ex_entry_exist(struct pt_regs *regs, + unsigned long addr, + struct task_struct *task) +{ +#ifdef CONFIG_ARM64 + if (!compat_user_mode(regs)) + return quadd_aarch64_is_ex_entry_exist(regs, addr, task); +#endif + + return quadd_aarch32_is_ex_entry_exist(regs, addr, task); +} + static unsigned long __user * user_backtrace(struct pt_regs *regs, unsigned long __user *tail, @@ -170,7 +184,7 @@ user_backtrace(struct pt_regs *regs, return NULL; if (cc->unw_method == QUADD_UNW_METHOD_MIXED && - quadd_is_ex_entry_exist(regs, value_lr, task)) + is_ex_entry_exist(regs, value_lr, task)) return NULL; if (fp_prev <= tail) @@ -199,7 +213,7 @@ get_user_callchain_fp(struct pt_regs *regs, sp = quadd_user_stack_pointer(regs); pc = instruction_pointer(regs); - fp = get_user_frame_pointer(regs); + fp = quadd_get_user_frame_pointer(regs); if (fp == 0 || fp < sp || fp & 0x3) return 0; @@ -357,7 +371,7 @@ user_backtrace_compat(struct pt_regs *regs, return NULL; if (cc->unw_method == QUADD_UNW_METHOD_MIXED && - quadd_is_ex_entry_exist(regs, value_lr, task)) + is_ex_entry_exist(regs, value_lr, task)) return NULL; if (fp_prev <= tail) @@ -386,7 +400,7 @@ get_user_callchain_fp_compat(struct pt_regs *regs, sp = quadd_user_stack_pointer(regs); pc = instruction_pointer(regs); - fp = get_user_frame_pointer(regs); + fp = quadd_get_user_frame_pointer(regs); if (fp == 0 || fp < sp || fp & 0x3) return 0; @@ -516,6 +530,18 @@ __get_user_callchain_fp(struct pt_regs *regs, } static unsigned int +get_user_callchain_ut(struct pt_regs *regs, + struct quadd_callchain *cc, + struct task_struct *task) +{ +#ifdef CONFIG_ARM64 + if (!compat_user_mode(regs)) + return quadd_aarch64_get_user_callchain_ut(regs, cc, task); +#endif + return quadd_aarch32_get_user_callchain_ut(regs, cc, task); +} + +static unsigned int get_user_callchain_mixed(struct pt_regs *regs, struct quadd_callchain *cc, struct task_struct *task) @@ -525,7 +551,7 @@ get_user_callchain_mixed(struct pt_regs *regs, do { nr_prev = cc->nr; - quadd_get_user_callchain_ut(regs, cc, task); + get_user_callchain_ut(regs, cc, task); if (nr_prev > 0 && cc->nr == nr_prev) break; @@ -570,7 +596,7 @@ quadd_get_user_callchain(struct pt_regs *regs, break; case QUADD_UNW_METHOD_EHT: - quadd_get_user_callchain_ut(regs, cc, task); + get_user_callchain_ut(regs, cc, task); break; case QUADD_UNW_METHOD_MIXED: |