X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4d15aeb193b2c68f1d38666c317f8d3734f5f083..5ba3f43ea354af8ad55bea84372a2bc834d8757c:/bsd/dev/arm/dtrace_subr_arm.c diff --git a/bsd/dev/arm/dtrace_subr_arm.c b/bsd/dev/arm/dtrace_subr_arm.c new file mode 100644 index 000000000..ab0bc4820 --- /dev/null +++ b/bsd/dev/arm/dtrace_subr_arm.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2007 Apple Inc. All rights reserved. + */ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * #pragma ident "@(#)dtrace_subr.c 1.12 05/06/08 SMI" + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int (*dtrace_pid_probe_ptr) (arm_saved_state_t *); +int (*dtrace_return_probe_ptr) (arm_saved_state_t *); + +kern_return_t +dtrace_user_probe(arm_saved_state_t *, unsigned int); + +kern_return_t +dtrace_user_probe(arm_saved_state_t *regs, unsigned int instr) +{ + /* + * FIXME + * + * The only call path into this method is always a user trap. + * We don't need to test for user trap, but should assert it. + */ + + lck_rw_t *rwp; + struct proc *p = current_proc(); + + uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread()); + + kauth_cred_uthread_update(uthread, p); + + if (((regs->cpsr & PSR_TF) && ((uint16_t) instr) == FASTTRAP_THUMB_RET_INSTR) || + ((uint32_t) instr == FASTTRAP_ARM_RET_INSTR)) { + uint8_t step = uthread->t_dtrace_step; + uint8_t ret = uthread->t_dtrace_ret; + user_addr_t npc = uthread->t_dtrace_npc; + + if (uthread->t_dtrace_ast) { + printf("dtrace_user_probe() should be calling aston()\n"); + // aston(thread); + // uthread->t_sig_check = 1; + } + + /* + * Clear all user tracing flags. + */ + uthread->t_dtrace_ft = 0; + + /* + * If we weren't expecting to take a return probe trap, kill + * the process as though it had just executed an unassigned + * trap instruction. + */ + if (step == 0) { + /* + * APPLE NOTE: We're returning KERN_FAILURE, which causes + * the generic signal handling code to take over, which will effectively + * deliver a EXC_BAD_INSTRUCTION to the user process. + */ + return KERN_FAILURE; + } + + /* + * If we hit this trap unrelated to a return probe, we're + * just here to reset the AST flag since we deferred a signal + * until after we logically single-stepped the instruction we + * copied out. + */ + if (ret == 0) { + regs->pc = npc; + return KERN_SUCCESS; + } + + /* + * We need to wait until after we've called the + * dtrace_return_probe_ptr function pointer to step the pc. + */ + rwp = &CPU->cpu_ft_lock; + lck_rw_lock_shared(rwp); + + if (dtrace_return_probe_ptr != NULL) + (void) (*dtrace_return_probe_ptr)(regs); + lck_rw_unlock_shared(rwp); + + regs->pc = npc; + + return KERN_SUCCESS; + } else { + rwp = &CPU->cpu_ft_lock; + + /* + * The DTrace fasttrap provider uses a trap, + * FASTTRAP_{ARM,THUMB}_INSTR. We let + * DTrace take the first crack at handling + * this trap; if it's not a probe that DTrace knows about, + * we call into the trap() routine to handle it like a + * breakpoint placed by a conventional debugger. + */ + + /* + * APPLE NOTE: I believe the purpose of the reader/writers lock + * is thus: There are times which dtrace needs to prevent calling + * dtrace_pid_probe_ptr(). Sun's original impl grabbed a plain + * mutex here. However, that serialized all probe calls, and + * destroyed MP behavior. So now they use a RW lock, with probes + * as readers, and the top level synchronization as a writer. + */ + lck_rw_lock_shared(rwp); + if (dtrace_pid_probe_ptr != NULL && + (*dtrace_pid_probe_ptr)(regs) == 0) { + lck_rw_unlock_shared(rwp); + return KERN_SUCCESS; + } + lck_rw_unlock_shared(rwp); + + /* + * If the instruction that caused the breakpoint trap doesn't + * look like our trap anymore, it may be that this tracepoint + * was removed just after the user thread executed it. In + * that case, return to user land to retry the instuction. + * + * Note that the PC points to the instruction that caused the fault. + */ + if (regs->cpsr & PSR_TF) { + uint16_t instr_check; + if (fuword16(regs->pc, &instr_check) == 0 && instr_check != FASTTRAP_THUMB_INSTR) { + return KERN_SUCCESS; + } + } else { + uint32_t instr_check; + if (fuword32(regs->pc, &instr_check) == 0 && instr_check != FASTTRAP_ARM_INSTR) { + return KERN_SUCCESS; + } + } + } + + return KERN_FAILURE; +} + +void +dtrace_safe_synchronous_signal(void) +{ + /* Not implemented */ +} + +int +dtrace_safe_defer_signal(void) +{ + /* Not implemented */ + return 0; +}