]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/arm64/fbt_arm.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / dev / arm64 / fbt_arm.c
index 083f98665aff2eea07e0ec934a8f7814cd94521f..15b2a33cf25ed6dce5cd0d2557b25636fc05da43 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2018 Apple Inc. All rights reserved.
  */
 /*
  * CDDL HEADER START
  * Use is subject to license terms.
  */
 
-/* #pragma ident       "@(#)fbt.c      1.15    05/09/19 SMI" */
-
-#ifdef KERNEL
-#ifndef _KERNEL
-#define _KERNEL                 /* Solaris vs. Darwin */
-#endif
-#endif
-
-#define MACH__POSIX_C_SOURCE_PRIVATE 1  /* pulls in suitable savearea from
-                                        * mach/ppc/thread_status.h */
 #include <kern/thread.h>
 #include <mach/thread_status.h>
 #include <arm/proc_reg.h>
@@ -129,77 +119,55 @@ fbt_invop(uintptr_t addr, uintptr_t * stack, uintptr_t rval)
                                CPU->cpu_dtrace_invop_underway = 1;     /* Race not possible on
                                                                        * this per-cpu state */
 
+                               /*
+                                * 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. */
                                if (fbt->fbtp_roffset == 0) {
-                                       /*
-                                        * Stack looks like this:
-                                        *
-                                        *      [Higher addresses]
-                                        *
-                                        *      Frame of caller
-                                        *      Extra args for callee
-                                        *      ------------------------
-                                        *      Frame from traced function: <previous sp (e.g. 0x1000), return address>
-                                        *      ------------------------
-                                        *      arm_context_t
-                                        *      ------------------------
-                                        *      Frame from trap handler:  <previous sp (e.g. 0x1000) , traced PC >
-                                        *                              The traced function never got to mov fp, sp,
-                                        *                              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]
-                                        */
-
-                                       arm_saved_state_t *regs = (arm_saved_state_t *)(&((arm_context_t *)stack)->ss);
-
-                                       /*
-                                        * cpu_dtrace_caller compensates for fact that the traced function never got to update its fp.
-                                        * 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.
-                                        */
-                                       CPU->cpu_dtrace_caller = get_saved_state_lr(regs);
                                        dtrace_probe(fbt->fbtp_id, get_saved_state_reg(regs, 0), get_saved_state_reg(regs, 1),
                                            get_saved_state_reg(regs, 2), get_saved_state_reg(regs, 3), get_saved_state_reg(regs, 4));
-                                       CPU->cpu_dtrace_caller = 0;
                                } else {
-                                       /*
-                                        * When fbtp_roffset is non-zero, we know we are handling a return probe point.
-                                        *
-                                        *
-                                        * Stack looks like this, as we've already popped the frame in the traced callee, and
-                                        * we trap with lr set to the return address in the caller.
-                                        *      [Higher addresses]
-                                        *
-                                        *      Frame of caller
-                                        *      Extra args for callee
-                                        *      ------------------------
-                                        *      arm_context_t
-                                        *      ------------------------
-                                        *      Frame from trap handler:  <sp at time of trap, traced PC >
-                                        *      ------------------------
-                                        *           |
-                                        *           |
-                                        *           |  stack grows this way
-                                        *           |
-                                        *           |
-                                        *           v
-                                        *      [Lower addresses]
-                                        */
-                                       arm_saved_state_t *regs = (arm_saved_state_t *)(&((arm_context_t *)stack)->ss);
-
-                                       CPU->cpu_dtrace_caller = get_saved_state_lr(regs);
                                        dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset, rval, 0, 0, 0);
-                                       CPU->cpu_dtrace_caller = 0;
                                }
+
+                               CPU->cpu_dtrace_caller = 0;
                                CPU->cpu_dtrace_invop_underway = 0;
                        }
 
@@ -231,7 +199,8 @@ fbt_perfCallback(
        if (FBT_EXCEPTION_CODE == trapno && !IS_USER_TRAP(regs)) {
                boolean_t oldlevel = 0;
                machine_inst_t emul = 0;
-               uint64_t sp, pc, lr, imm;
+               uint64_t sp, lr;
+               uint32_t imm;
 
                oldlevel = ml_set_interrupts_enabled(FALSE);
 
@@ -259,8 +228,7 @@ fbt_perfCallback(
                        /*
                         * Skip over the patched NOP planted by sdt
                         */
-                       pc = get_saved_state_pc(regs);
-                       set_saved_state_pc(regs, pc + DTRACE_INVOP_NOP_SKIP);
+                       add_saved_state_pc(regs, DTRACE_INVOP_NOP_SKIP);
                        retval = KERN_SUCCESS;
                } else if (FBT_IS_ARM64_ADD_FP_SP(emul)) {
                        /* retrieve the value to add */
@@ -278,8 +246,7 @@ fbt_perfCallback(
                        set_saved_state_fp(regs, sp + val);
 
                        /* skip over the bytes of the patched instruction */
-                       pc = get_saved_state_pc(regs);
-                       set_saved_state_pc(regs, pc + DTRACE_INVOP_ADD_FP_SP_SKIP);
+                       add_saved_state_pc(regs, DTRACE_INVOP_ADD_FP_SP_SKIP);
 
                        retval = KERN_SUCCESS;
                } else if (FBT_IS_ARM64_RET(emul)) {
@@ -290,9 +257,8 @@ fbt_perfCallback(
                        set_saved_state_pc(regs, lr);
                        retval = KERN_SUCCESS;
                } else if (FBT_IS_ARM64_B_INSTR(emul)) {
-                       pc = get_saved_state_pc(regs);
                        imm = FBT_GET_ARM64_B_IMM(emul);
-                       set_saved_state_pc(regs, pc + imm);
+                       add_saved_state_pc(regs, imm);
                        retval = KERN_SUCCESS;
                } else if (emul == FBT_PATCHVAL) {
                        /* Means we encountered an error but handled it, try same inst again */
@@ -527,7 +493,7 @@ again:
        newfbt->fbtp_ctl = ctl;
        newfbt->fbtp_loadcnt = ctl->mod_loadcnt;
 
-       ASSERT(FBT_IS_ARM64_RET(theInstr));
+       ASSERT(FBT_IS_ARM64_RET(theInstr) || FBT_IS_ARM64_B_INSTR(theInstr));
        newfbt->fbtp_rval = DTRACE_INVOP_RET;
        newfbt->fbtp_roffset = (uintptr_t) ((uint8_t*) instr - (uint8_t *)symbolStart);
        newfbt->fbtp_savedval = theInstr;