+ /*
+ * Stack looks like this:
+ *
+ * [Higher addresses]
+ *
+ * Frame of caller
+ * Extra args for callee
+ * ------------------------
+ * fbt entry probe:
+ * Frame from traced function: <previous sp (e.g. 0x1000), return address>
+ * fbt return probe:
+ * Missing as the return probe has already popped the frame in the callee and
+ * traps with LR set to the return address in caller.
+ * ------------------------
+ * arm_context_t
+ * ------------------------
+ * Frame from trap handler: <previous sp (e.g. 0x1000) , traced PC >
+ * The traced function has either never pushed the frame
+ * or already popped it. So there is no frame in the
+ * backtrace pointing to the frame on the stack containing
+ * the LR in the caller.
+ * ------------------------
+ * |
+ * |
+ * | stack grows this way
+ * |
+ * |
+ * v
+ * [Lower addresses]
+ *
+ * cpu_dtrace_caller compensates for fact that the LR is not stored on stack as explained
+ * above. When walking the stack, when we reach the frame where we extract a PC in the
+ * patched function, we put the cpu_dtrace_caller in the backtrace instead. The next
+ * frame we extract will be in the caller's caller, so we output a backtrace starting
+ * at the caller and going sequentially up the stack.
+ */
+ arm_saved_state_t *regs = (arm_saved_state_t *)(&((arm_context_t *)stack)->ss);
+
+ CPU->cpu_dtrace_caller = get_saved_state_lr(regs);
+
+ /* When fbt_roffset is non-zero, we know we are handling a return probe point. */