]>
git.saurik.com Git - apple/xnu.git/blob - bsd/dev/arm/dtrace_subr_arm.c
   2  *  Copyright (c) 2007 Apple Inc. All rights reserved. 
   7  * The contents of this file are subject to the terms of the 
   8  * Common Development and Distribution License, Version 1.0 only 
   9  * (the "License").  You may not use this file except in compliance 
  12  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 
  13  * or http://www.opensolaris.org/os/licensing. 
  14  * See the License for the specific language governing permissions 
  15  * and limitations under the License. 
  17  * When distributing Covered Code, include this CDDL HEADER in each 
  18  * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 
  19  * If applicable, add the following below this CDDL HEADER, with the 
  20  * fields enclosed by brackets "[]" replaced with your own identifying 
  21  * information: Portions Copyright [yyyy] [name of copyright owner] 
  26  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved. 
  27  * Use is subject to license terms. 
  30 #include <sys/dtrace.h> 
  31 #include <sys/dtrace_glue.h> 
  32 #include <sys/dtrace_impl.h> 
  33 #include <sys/fasttrap.h> 
  36 #include <sys/kauth.h> 
  37 #include <kern/debug.h> 
  38 #include <arm/proc_reg.h> 
  40 int             (*dtrace_pid_probe_ptr
)(arm_saved_state_t 
*); 
  41 int             (*dtrace_return_probe_ptr
) (arm_saved_state_t 
*); 
  44 dtrace_user_probe(arm_saved_state_t 
*, unsigned int); 
  47 dtrace_user_probe(arm_saved_state_t 
*regs
, unsigned int instr
) 
  52          * The only call path into this method is always a user trap. 
  53          * We don't need to test for user trap, but should assert it. 
  57         struct proc 
*p 
= current_proc(); 
  59         uthread_t uthread 
= (uthread_t
)get_bsdthread_info(current_thread()); 
  61         kauth_cred_uthread_update(uthread
, p
); 
  63         if (((regs
->cpsr 
& PSR_TF
) && ((uint16_t) instr
) == FASTTRAP_THUMB_RET_INSTR
) || 
  64             ((uint32_t) instr 
== FASTTRAP_ARM_RET_INSTR
)) { 
  65                 uint8_t step 
= uthread
->t_dtrace_step
; 
  66                 uint8_t ret 
= uthread
->t_dtrace_ret
; 
  67                 user_addr_t npc 
= uthread
->t_dtrace_npc
; 
  69                 if (uthread
->t_dtrace_ast
) { 
  70                         printf("dtrace_user_probe() should be calling aston()\n"); 
  72                         // uthread->t_sig_check = 1; 
  76                  * Clear all user tracing flags. 
  78                 uthread
->t_dtrace_ft 
= 0; 
  81                  * If we weren't expecting to take a return probe trap, kill 
  82                  * the process as though it had just executed an unassigned 
  87                          * APPLE NOTE: We're returning KERN_FAILURE, which causes 
  88                          * the generic signal handling code to take over, which will effectively 
  89                          * deliver a EXC_BAD_INSTRUCTION to the user process. 
  95                  * If we hit this trap unrelated to a return probe, we're 
  96                  * just here to reset the AST flag since we deferred a signal 
  97                  * until after we logically single-stepped the instruction we 
 106                  * We need to wait until after we've called the 
 107                  * dtrace_return_probe_ptr function pointer to step the pc. 
 109                 rwp 
= &CPU
->cpu_ft_lock
; 
 110                 lck_rw_lock_shared(rwp
); 
 112                 if (dtrace_return_probe_ptr 
!= NULL
) { 
 113                         (void) (*dtrace_return_probe_ptr
)(regs
); 
 115                 lck_rw_unlock_shared(rwp
); 
 121                 rwp 
= &CPU
->cpu_ft_lock
; 
 124                  * The DTrace fasttrap provider uses a trap, 
 125                  * FASTTRAP_{ARM,THUMB}_INSTR. We let 
 126                  * DTrace take the first crack at handling 
 127                  * this trap; if it's not a probe that DTrace knows about, 
 128                  * we call into the trap() routine to handle it like a 
 129                  * breakpoint placed by a conventional debugger. 
 133                  * APPLE NOTE: I believe the purpose of the reader/writers lock 
 134                  * is thus: There are times which dtrace needs to prevent calling 
 135                  * dtrace_pid_probe_ptr(). Sun's original impl grabbed a plain 
 136                  * mutex here. However, that serialized all probe calls, and 
 137                  * destroyed MP behavior. So now they use a RW lock, with probes 
 138                  * as readers, and the top level synchronization as a writer. 
 140                 lck_rw_lock_shared(rwp
); 
 141                 if (dtrace_pid_probe_ptr 
!= NULL 
&& 
 142                     (*dtrace_pid_probe_ptr
)(regs
) == 0) { 
 143                         lck_rw_unlock_shared(rwp
); 
 146                 lck_rw_unlock_shared(rwp
); 
 149                  * If the instruction that caused the breakpoint trap doesn't 
 150                  * look like our trap anymore, it may be that this tracepoint 
 151                  * was removed just after the user thread executed it. In 
 152                  * that case, return to user land to retry the instuction. 
 154                  * Note that the PC points to the instruction that caused the fault. 
 156                 if (regs
->cpsr 
& PSR_TF
) { 
 157                         uint16_t instr_check
; 
 158                         if (fuword16(regs
->pc
, &instr_check
) == 0 && instr_check 
!= FASTTRAP_THUMB_INSTR
) { 
 162                         uint32_t instr_check
; 
 163                         if (fuword32(regs
->pc
, &instr_check
) == 0 && instr_check 
!= FASTTRAP_ARM_INSTR
) {