X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/0a7de7458d150b5d4dffc935ba399be265ef0a1a..c3c9b80d004dbbfdf763edeb97968c6997e3b45b:/bsd/dev/arm64/fbt_arm.c diff --git a/bsd/dev/arm64/fbt_arm.c b/bsd/dev/arm64/fbt_arm.c index 083f98665..15b2a33cf 100644 --- a/bsd/dev/arm64/fbt_arm.c +++ b/bsd/dev/arm64/fbt_arm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Apple Inc. All rights reserved. + * Copyright (c) 2007-2018 Apple Inc. All rights reserved. */ /* * CDDL HEADER START @@ -27,16 +27,6 @@ * 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 #include #include @@ -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: + * 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: + * 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: - * ------------------------ - * arm_context_t - * ------------------------ - * Frame from trap handler: - * 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: - * ------------------------ - * | - * | - * | 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;