}
 #endif
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+static struct orc_entry *orc_find(unsigned long ip);
+
+/*
+ * Ftrace dynamic trampolines do not have orc entries of their own.
+ * But they are copies of the ftrace entries that are static and
+ * defined in ftrace_*.S, which do have orc entries.
+ *
+ * If the undwinder comes across a ftrace trampoline, then find the
+ * ftrace function that was used to create it, and use that ftrace
+ * function's orc entrie, as the placement of the return code in
+ * the stack will be identical.
+ */
+static struct orc_entry *orc_ftrace_find(unsigned long ip)
+{
+       struct ftrace_ops *ops;
+       unsigned long caller;
+
+       ops = ftrace_ops_trampoline(ip);
+       if (!ops)
+               return NULL;
+
+       if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
+               caller = (unsigned long)ftrace_regs_call;
+       else
+               caller = (unsigned long)ftrace_call;
+
+       /* Prevent unlikely recursion */
+       if (ip == caller)
+               return NULL;
+
+       return orc_find(caller);
+}
+#else
+static struct orc_entry *orc_ftrace_find(unsigned long ip)
+{
+       return NULL;
+}
+#endif
+
 static struct orc_entry *orc_find(unsigned long ip)
 {
+       static struct orc_entry *orc;
+
        if (!orc_init)
                return NULL;
 
                                  __stop_orc_unwind_ip - __start_orc_unwind_ip, ip);
 
        /* Module lookup: */
-       return orc_module_find(ip);
+       orc = orc_module_find(ip);
+       if (orc)
+               return orc;
+
+       return orc_ftrace_find(ip);
 }
 
 static void orc_sort_swap(void *_a, void *_b, int size)
 
 };
 
 /*
- * This is used by __kernel_text_address() to return true if the
- * address is on a dynamically allocated trampoline that would
- * not return true for either core_kernel_text() or
- * is_module_text_address().
+ * Used by the stack undwinder to know about dynamic ftrace trampolines.
  */
-bool is_ftrace_trampoline(unsigned long addr)
+struct ftrace_ops *ftrace_ops_trampoline(unsigned long addr)
 {
-       struct ftrace_ops *op;
-       bool ret = false;
+       struct ftrace_ops *op = NULL;
 
        /*
         * Some of the ops may be dynamically allocated,
                if (op->trampoline && op->trampoline_size)
                        if (addr >= op->trampoline &&
                            addr < op->trampoline + op->trampoline_size) {
-                               ret = true;
-                               goto out;
+                               preempt_enable_notrace();
+                               return op;
                        }
        } while_for_each_ftrace_op(op);
-
- out:
        preempt_enable_notrace();
 
-       return ret;
+       return NULL;
+}
+
+/*
+ * This is used by __kernel_text_address() to return true if the
+ * address is on a dynamically allocated trampoline that would
+ * not return true for either core_kernel_text() or
+ * is_module_text_address().
+ */
+bool is_ftrace_trampoline(unsigned long addr)
+{
+       return ftrace_ops_trampoline(addr) != NULL;
 }
 
 struct ftrace_page {