diff options
author | Igor Nabirushkin <inabirushkin@nvidia.com> | 2015-02-26 15:16:21 +0400 |
---|---|---|
committer | Winnie Hsu <whsu@nvidia.com> | 2015-05-29 14:25:28 -0700 |
commit | af01aa37409408815278e81aacd9346beb0be1c0 (patch) | |
tree | 0d258bd6ead7ed78508e92d35e30fe8fe965e856 /drivers/misc | |
parent | d18306d725e35e6431e04745d97c3a61c0d1280d (diff) |
misc: tegra-profiler: fix broken call chains
Fix broken call chains for thumb code with dwarf and
arm ehabi information simultaneously.
Bug 1615165
Change-Id: If34ecfac26657546170121c363cf89b8b7256dbb
Signed-off-by: Igor Nabirushkin <inabirushkin@nvidia.com>
Reviewed-on: http://git-master/r/711611
(cherry picked from commit 7d98345d6f2f1ba476161d91853dd82b23a92d1d)
Reviewed-on: http://git-master/r/747749
GVS: Gerrit_Virtual_Submit
Reviewed-by: Andrey Trachenko <atrachenko@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/tegra-profiler/backtrace.c | 17 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/backtrace.h | 1 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/dwarf_unwind.c | 10 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/eh_unwind.c | 7 | ||||
-rw-r--r-- | drivers/misc/tegra-profiler/version.h | 2 |
5 files changed, 26 insertions, 11 deletions
diff --git a/drivers/misc/tegra-profiler/backtrace.c b/drivers/misc/tegra-profiler/backtrace.c index 352095b1cfac..a249bfd30f92 100644 --- a/drivers/misc/tegra-profiler/backtrace.c +++ b/drivers/misc/tegra-profiler/backtrace.c @@ -168,12 +168,12 @@ user_backtrace(struct pt_regs *regs, return NULL; } + if (!is_vma_addr(value_fp, stack_vma, sizeof(value_fp))) + return NULL; + cc->curr_fp = value_fp; cc->curr_sp = (unsigned long)tail + sizeof(value_fp); cc->curr_pc = value_lr = value; - - if (!is_vma_addr(value_fp, stack_vma, sizeof(value_fp))) - return NULL; } fp_prev = (unsigned long __user *)value_fp; @@ -355,12 +355,12 @@ user_backtrace_compat(struct pt_regs *regs, return NULL; } + if (!is_vma_addr(value_fp, stack_vma, sizeof(value_fp))) + return NULL; + cc->curr_fp = value_fp; cc->curr_sp = (unsigned long)tail + sizeof(value_fp); cc->curr_pc = value_lr = value; - - if (!is_vma_addr(value_fp, stack_vma, sizeof(value_fp))) - return NULL; } fp_prev = (u32 __user *)(unsigned long)value_fp; @@ -561,9 +561,11 @@ get_user_callchain_mixed(struct pt_regs *regs, nr_prev = cc->nr; quadd_get_user_cc_dwarf(regs, cc, task); - quadd_get_user_cc_arm32_ehabi(regs, cc, task); + if (nr_prev != cc->nr) + continue; + __get_user_callchain_fp(regs, cc, task); } while (nr_prev != cc->nr); @@ -587,6 +589,7 @@ quadd_get_user_callchain(struct pt_regs *regs, cc->curr_sp = 0; cc->curr_fp = 0; + cc->curr_fp_thumb = 0; cc->curr_pc = 0; #ifdef CONFIG_ARM64 diff --git a/drivers/misc/tegra-profiler/backtrace.h b/drivers/misc/tegra-profiler/backtrace.h index 3046ac60fdb5..5ee544cdd496 100644 --- a/drivers/misc/tegra-profiler/backtrace.h +++ b/drivers/misc/tegra-profiler/backtrace.h @@ -44,6 +44,7 @@ struct quadd_callchain { unsigned long curr_sp; unsigned long curr_fp; + unsigned long curr_fp_thumb; unsigned long curr_pc; struct quadd_hrt_ctx *hrt; diff --git a/drivers/misc/tegra-profiler/dwarf_unwind.c b/drivers/misc/tegra-profiler/dwarf_unwind.c index b5582a7c55e2..72062e66a4ab 100644 --- a/drivers/misc/tegra-profiler/dwarf_unwind.c +++ b/drivers/misc/tegra-profiler/dwarf_unwind.c @@ -1983,8 +1983,13 @@ unwind_backtrace(struct quadd_callchain *cc, pr_debug("[%s]: function at [<%08lx>] from [<%08lx>]\n", is_eh ? "eh" : "debug", where, sf->pc); + cc->curr_sp = sf->vregs[regnum_sp(mode)]; + cc->curr_fp = sf->vregs[regnum_fp(mode)]; + if (mode == DW_MODE_ARM32) + cc->curr_fp_thumb = sf->vregs[ARM32_FP_THUMB]; + cc->curr_pc = sf->pc; nr_added = quadd_callchain_store(cc, sf->pc, unw_type); @@ -2044,7 +2049,7 @@ quadd_get_user_cc_dwarf(struct pt_regs *regs, ip = cc->curr_pc; sp = cc->curr_sp; fp = cc->curr_fp; - fp_thumb = 0; + fp_thumb = cc->curr_fp_thumb; lr = 0; } else { ip = instruction_pointer(regs); @@ -2084,7 +2089,8 @@ quadd_get_user_cc_dwarf(struct pt_regs *regs, sf.vregs[regnum_sp(mode)] = sp; sf.vregs[regnum_fp(mode)] = fp; - sf.vregs[ARM32_FP_THUMB] = fp_thumb; + if (mode == DW_MODE_ARM32) + sf.vregs[ARM32_FP_THUMB] = fp_thumb; cpu_ctx->dw_ptr_size = (mode == DW_MODE_ARM32) ? sizeof(u32) : sizeof(u64); diff --git a/drivers/misc/tegra-profiler/eh_unwind.c b/drivers/misc/tegra-profiler/eh_unwind.c index 888c2d49b037..e97ed5a3e062 100644 --- a/drivers/misc/tegra-profiler/eh_unwind.c +++ b/drivers/misc/tegra-profiler/eh_unwind.c @@ -1120,6 +1120,7 @@ unwind_backtrace(struct quadd_callchain *cc, cc->curr_sp = frame->sp; cc->curr_fp = frame->fp_arm; + cc->curr_fp_thumb = frame->fp_thumb; cc->curr_pc = frame->pc; nr_added = quadd_callchain_store(cc, frame->pc, unw_type); @@ -1159,7 +1160,7 @@ quadd_get_user_cc_arm32_ehabi(struct pt_regs *regs, sp = cc->curr_sp; lr = 0; - frame.fp_thumb = 0; + frame.fp_thumb = cc->curr_fp_thumb; frame.fp_arm = cc->curr_fp; } else { ip = instruction_pointer(regs); @@ -1179,6 +1180,10 @@ quadd_get_user_cc_arm32_ehabi(struct pt_regs *regs, frame.sp = sp; frame.lr = lr; + pr_debug("pc: %#lx, lr: %#lx\n", ip, lr); + pr_debug("sp: %#lx, fp_arm: %#lx, fp_thumb: %#lx\n", + sp, frame.fp_arm, frame.fp_thumb); + vma = find_vma(mm, ip); if (!vma) return 0; diff --git a/drivers/misc/tegra-profiler/version.h b/drivers/misc/tegra-profiler/version.h index 2281ec87dbbb..279861411474 100644 --- a/drivers/misc/tegra-profiler/version.h +++ b/drivers/misc/tegra-profiler/version.h @@ -18,7 +18,7 @@ #ifndef __QUADD_VERSION_H #define __QUADD_VERSION_H -#define QUADD_MODULE_VERSION "1.91" +#define QUADD_MODULE_VERSION "1.92" #define QUADD_MODULE_BRANCH "Dev" #endif /* __QUADD_VERSION_H */ |