m68knommu: add pretty back strace
[firefly-linux-kernel-4.4.55.git] / arch / m68knommu / kernel / traps.c
index 9129b3a5258bc28a8e832eea7dcd809bb7860c44..ec9aea652e79d0665adcb36fe5e9cd49d9625a51 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <linux/ptrace.h>
+#include <linux/kallsyms.h>
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
@@ -62,8 +63,6 @@ static char const * const vec_names[] = {
 
 void __init trap_init(void)
 {
-       if (mach_trap_init)
-               mach_trap_init();
 }
 
 void die_if_kernel(char *str, struct pt_regs *fp, int nr)
@@ -82,7 +81,8 @@ void die_if_kernel(char *str, struct pt_regs *fp, int nr)
 
        printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
                current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
-       show_stack(NULL, (unsigned long *)fp);
+       show_stack(NULL, (unsigned long *)(fp + 1));
+       add_taint(TAINT_DIE);
        do_exit(SIGSEGV);
 }
 
@@ -103,62 +103,53 @@ asmlinkage void buserr_c(struct frame *fp)
        force_sig(SIGSEGV, current);
 }
 
-
 int kstack_depth_to_print = 48;
 
-void show_stack(struct task_struct *task, unsigned long *stack)
+static void __show_stack(struct task_struct *task, unsigned long *stack)
 {
        unsigned long *endstack, addr;
-       extern char _start, _etext;
+       unsigned long *last_stack;
        int i;
 
-       if (!stack) {
-               if (task)
-                       stack = (unsigned long *)task->thread.ksp;
-               else
-                       stack = (unsigned long *)&stack;
-       }
+       if (!stack)
+               stack = (unsigned long *)task->thread.ksp;
 
        addr = (unsigned long) stack;
        endstack = (unsigned long *) PAGE_ALIGN(addr);
 
        printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
        for (i = 0; i < kstack_depth_to_print; i++) {
-               if (stack + 1 > endstack)
+               if (stack + 1 + i > endstack)
                        break;
                if (i % 8 == 0)
                        printk("\n" KERN_EMERG "       ");
-               printk(" %08lx", *stack++);
+               printk(" %08lx", *(stack + i));
        }
        printk("\n");
 
-       printk(KERN_EMERG "Call Trace:");
-       i = 0;
-       while (stack + 1 <= endstack) {
-               addr = *stack++;
-               /*
-                * If the address is either in the text segment of the
-                * kernel, or in the region which contains vmalloc'ed
-                * memory, it *may* be the address of a calling
-                * routine; if so, print it so that someone tracing
-                * down the cause of the crash will be able to figure
-                * out the call path that was taken.
-                */
-               if (((addr >= (unsigned long) &_start) &&
-                    (addr <= (unsigned long) &_etext))) {
-                       if (i % 4 == 0)
-                               printk("\n" KERN_EMERG "       ");
-                       printk(" [<%08lx>]", addr);
-                       i++;
-               }
+#ifdef CONFIG_FRAME_POINTER
+       printk(KERN_EMERG "Call Trace:\n");
+
+       last_stack = stack - 1;
+       while (stack <= endstack && stack > last_stack) {
+
+               addr = *(stack + 1);
+               printk(KERN_EMERG " [%08lx] ", addr);
+               print_symbol(KERN_CONT "%s\n", addr);
+
+               last_stack = stack;
+               stack = (unsigned long *)*stack;
        }
        printk("\n");
+#else
+       printk(KERN_EMERG "CONFIG_FRAME_POINTER disabled, no symbolic call trace\n");
+#endif
 }
 
 void bad_super_trap(struct frame *fp)
 {
        console_verbose();
-       if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
+       if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
                printk (KERN_WARNING "*** %s ***   FORMAT=%X\n",
                        vec_names[(fp->ptregs.vector) >> 2],
                        fp->ptregs.format);
@@ -299,19 +290,47 @@ asmlinkage void set_esp0(unsigned long ssp)
        current->thread.esp0 = ssp;
 }
 
-
 /*
  * The architecture-independent backtrace generator
  */
 void dump_stack(void)
 {
-       unsigned long stack;
+       /*
+        * We need frame pointers for this little trick, which works as follows:
+        *
+        * +------------+ 0x00
+        * | Next SP    |       -> 0x0c
+        * +------------+ 0x04
+        * | Caller     |
+        * +------------+ 0x08
+        * | Local vars |       -> our stack var
+        * +------------+ 0x0c
+        * | Next SP    |       -> 0x18, that is what we pass to show_stack()
+        * +------------+ 0x10
+        * | Caller     |
+        * +------------+ 0x14
+        * | Local vars |
+        * +------------+ 0x18
+        * | ...        |
+        * +------------+
+        */
 
-       show_stack(current, &stack);
-}
+       unsigned long *stack;
 
+       stack = (unsigned long *)&stack;
+       stack++;
+       __show_stack(current, stack);
+}
 EXPORT_SYMBOL(dump_stack);
 
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+       if (!stack && !task)
+               dump_stack();
+       else
+               __show_stack(task, stack);
+}
+
 #ifdef CONFIG_M68KFPU_EMU
 asmlinkage void fpemu_signal(int signal, int code, void *addr)
 {