diff options
author | Guo Ren <ren_guo@c-sky.com> | 2018-12-09 14:18:05 +0800 |
---|---|---|
committer | Guo Ren <ren_guo@c-sky.com> | 2018-12-31 23:12:22 +0800 |
commit | 0ea2dc7cd668be5475babecaf6fdeaa464e2847b (patch) | |
tree | 733fef9d2126b7323d4ec80e62e0c3ea583e01f7 /arch/csky/kernel/process.c | |
parent | 859e5f45cbb33fe5d591a8e429667f0b7d4f4be8 (diff) | |
download | linux-0ea2dc7cd668be5475babecaf6fdeaa464e2847b.tar.gz linux-0ea2dc7cd668be5475babecaf6fdeaa464e2847b.tar.bz2 linux-0ea2dc7cd668be5475babecaf6fdeaa464e2847b.zip |
csky: stacktrace supported.
The gcc option "-mbacktrace" will push fp(r8),lr into stack and we could
unwind the stack with:
fp = *fp
lr = (unsigned int *)fp[1]
Signed-off-by: Guo Ren <ren_guo@c-sky.com>
Diffstat (limited to 'arch/csky/kernel/process.c')
-rw-r--r-- | arch/csky/kernel/process.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/arch/csky/kernel/process.c b/arch/csky/kernel/process.c index 8ed20028b160..e555740c0be5 100644 --- a/arch/csky/kernel/process.c +++ b/arch/csky/kernel/process.c @@ -93,26 +93,31 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *pr_regs) unsigned long get_wchan(struct task_struct *p) { - unsigned long esp, pc; - unsigned long stack_page; + unsigned long lr; + unsigned long *fp, *stack_start, *stack_end; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)p; - esp = p->thread.esp0; + stack_start = (unsigned long *)end_of_stack(p); + stack_end = (unsigned long *)(task_stack_page(p) + THREAD_SIZE); + + fp = (unsigned long *) thread_saved_fp(p); do { - if (esp < stack_page+sizeof(struct task_struct) || - esp >= 8184+stack_page) + if (fp < stack_start || fp > stack_end) return 0; - /*FIXME: There's may be error here!*/ - pc = ((unsigned long *)esp)[1]; - /* FIXME: This depends on the order of these functions. */ - if (!in_sched_functions(pc)) - return pc; - esp = *(unsigned long *) esp; +#ifdef CONFIG_STACKTRACE + lr = fp[1]; + fp = (unsigned long *)fp[0]; +#else + lr = *fp++; +#endif + if (!in_sched_functions(lr) && + __kernel_text_address(lr)) + return lr; } while (count++ < 16); + return 0; } EXPORT_SYMBOL(get_wchan); |