x86/dumpstack: Add get_stack_pointer() and get_frame_pointer()
authorJosh Poimboeuf <jpoimboe@redhat.com>
Wed, 24 Aug 2016 16:50:17 +0000 (11:50 -0500)
committerIngo Molnar <mingo@kernel.org>
Thu, 8 Sep 2016 06:58:40 +0000 (08:58 +0200)
The various functions involved in dumping the stack all do similar
things with regard to getting the stack pointer and the frame pointer
based on the regs and task arguments.  Create helper functions to
do that instead.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Byungchul Park <byungchul.park@lge.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Nilay Vaish <nilayvaish@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/f448914885a35f333fe04da1b97a6c2cc1f80974.1472057064.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/include/asm/stacktrace.h
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack_32.c
arch/x86/kernel/dumpstack_64.c

index 7646fb2772f801a0950ec7c9ecbbcf4122e9ebcd..3552f5e7189e74b54ada5bee83dcc4dc47a155f0 100644 (file)
@@ -50,36 +50,41 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
 
 #ifdef CONFIG_X86_32
 #define STACKSLOTS_PER_LINE 8
-#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :)
 #else
 #define STACKSLOTS_PER_LINE 4
-#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
 #endif
 
 #ifdef CONFIG_FRAME_POINTER
-static inline unsigned long
-stack_frame(struct task_struct *task, struct pt_regs *regs)
+static inline unsigned long *
+get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
 {
-       unsigned long bp;
-
        if (regs)
-               return regs->bp;
+               return (unsigned long *)regs->bp;
 
-       if (task == current) {
-               /* Grab bp right from our regs */
-               get_bp(bp);
-               return bp;
-       }
+       if (!task || task == current)
+               return __builtin_frame_address(0);
 
-       return ((struct inactive_task_frame *)task->thread.sp)->bp;
+       return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;
 }
 #else
-static inline unsigned long
-stack_frame(struct task_struct *task, struct pt_regs *regs)
+static inline unsigned long *
+get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
 {
-       return 0;
+       return NULL;
+}
+#endif /* CONFIG_FRAME_POINTER */
+
+static inline unsigned long *
+get_stack_pointer(struct task_struct *task, struct pt_regs *regs)
+{
+       if (regs)
+               return (unsigned long *)kernel_stack_pointer(regs);
+
+       if (!task || task == current)
+               return __builtin_frame_address(0);
+
+       return (unsigned long *)task->thread.sp;
 }
-#endif
 
 extern void
 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
@@ -106,7 +111,7 @@ static inline unsigned long caller_frame_pointer(void)
 {
        struct stack_frame *frame;
 
-       get_bp(frame);
+       frame = __builtin_frame_address(0);
 
 #ifdef CONFIG_FRAME_POINTER
        frame = frame->next_frame;
index f0ddf855957e30773dbe756d44ea2807d31e1884..6d6f46837eeab1f7cf6982071447f290cd21b7ae 100644 (file)
@@ -170,15 +170,14 @@ show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
 void show_stack(struct task_struct *task, unsigned long *sp)
 {
        unsigned long bp = 0;
-       unsigned long stack;
 
        /*
         * Stack frames below this one aren't interesting.  Don't show them
         * if we're printing for %current.
         */
        if (!sp && (!task || task == current)) {
-               sp = &stack;
-               bp = stack_frame(current, NULL);
+               sp = get_stack_pointer(current, NULL);
+               bp = (unsigned long)get_frame_pointer(current, NULL);
        }
 
        show_stack_log_lvl(task, NULL, sp, bp, "");
index 09675712eba807a8470962c53102ad1e7dc32afa..358fe1cd4e5bc7d2399db9ac5aa0c1f09cfb454f 100644 (file)
@@ -46,19 +46,9 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
        int graph = 0;
        u32 *prev_esp;
 
-       if (!task)
-               task = current;
-
-       if (!stack) {
-               unsigned long dummy;
-
-               stack = &dummy;
-               if (task != current)
-                       stack = (unsigned long *)task->thread.sp;
-       }
-
-       if (!bp)
-               bp = stack_frame(task, regs);
+       task = task ? : current;
+       stack = stack ? : get_stack_pointer(task, regs);
+       bp = bp ? : (unsigned long)get_frame_pointer(task, regs);
 
        for (;;) {
                void *end_stack;
@@ -95,14 +85,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
        unsigned long *stack;
        int i;
 
-       if (sp == NULL) {
-               if (regs)
-                       sp = (unsigned long *)regs->sp;
-               else if (task)
-                       sp = (unsigned long *)task->thread.sp;
-               else
-                       sp = (unsigned long *)&sp;
-       }
+       sp = sp ? : get_stack_pointer(task, regs);
 
        stack = sp;
        for (i = 0; i < kstack_depth_to_print; i++) {
index 066eb5c77fd66e8eeeecfc22d20a65c1f82ddecd..7f3b8066f719c09210d2c5378e79534e2f538444 100644 (file)
@@ -151,25 +151,14 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
 {
        const unsigned cpu = get_cpu();
        unsigned long *irq_stack = (unsigned long *)per_cpu(irq_stack_ptr, cpu);
-       unsigned long dummy;
        unsigned used = 0;
        int graph = 0;
        int done = 0;
 
-       if (!task)
-               task = current;
+       task = task ? : current;
+       stack = stack ? : get_stack_pointer(task, regs);
+       bp = bp ? : (unsigned long)get_frame_pointer(task, regs);
 
-       if (!stack) {
-               if (regs)
-                       stack = (unsigned long *)regs->sp;
-               else if (task != current)
-                       stack = (unsigned long *)task->thread.sp;
-               else
-                       stack = &dummy;
-       }
-
-       if (!bp)
-               bp = stack_frame(task, regs);
        /*
         * Print function call entries in all stacks, starting at the
         * current stack address. If the stacks consist of nested
@@ -256,18 +245,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
        irq_stack_end = (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
        irq_stack     = irq_stack_end - (IRQ_STACK_SIZE / sizeof(long));
 
-       /*
-        * Debugging aid: "show_stack(NULL, NULL);" prints the
-        * back trace for this cpu:
-        */
-       if (sp == NULL) {
-               if (regs)
-                       sp = (unsigned long *)regs->sp;
-               else if (task)
-                       sp = (unsigned long *)task->thread.sp;
-               else
-                       sp = (unsigned long *)&sp;
-       }
+       sp = sp ? : get_stack_pointer(task, regs);
 
        stack = sp;
        for (i = 0; i < kstack_depth_to_print; i++) {