1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27/* 28 * #pragma ident "@(#)dtrace_subr.c 1.8 07/06/05 SMI" 29 */ 30 31#include <stdarg.h> 32#include <string.h> 33#include <sys/malloc.h> 34#include <sys/time.h> 35#include <sys/dtrace.h> 36#include <sys/dtrace_impl.h> 37#include <kern/debug.h> 38 39#if defined(__APPLE__) 40/* Solaris proc_t is the struct. Darwin's proc_t is a pointer to it. */ 41#define proc_t struct proc /* Steer clear of the Darwin typedef for proc_t */ 42#endif 43 44/* Copied from an arch specific dtrace_subr.c. */ 45int (*dtrace_fasttrap_probe_ptr)(struct regs *); 46 47/* 48 * Following DTrace hooks are taken from Solaris' dtrace_subr.c 49 * They're assigned in dtrace.c but Darwin never calls them. 50 */ 51void (*dtrace_cpu_init)(processorid_t); 52#if !defined(__APPLE__) 53void (*dtrace_modload)(struct modctl *); 54void (*dtrace_modunload)(struct modctl *); 55#else 56int (*dtrace_modload)(struct kmod_info *, uint32_t); 57int (*dtrace_modunload)(struct kmod_info *); 58void (*dtrace_helpers_cleanup)(proc_t *); 59#endif /*__APPLE__*/ 60void (*dtrace_helpers_fork)(proc_t *, proc_t *); 61void (*dtrace_cpustart_init)(void); 62void (*dtrace_cpustart_fini)(void); 63 64void (*dtrace_debugger_init)(void); 65void (*dtrace_debugger_fini)(void); 66 67dtrace_vtime_state_t dtrace_vtime_active = 0; 68dtrace_cacheid_t dtrace_predcache_id = DTRACE_CACHEIDNONE + 1; 69 70void (*dtrace_fasttrap_fork_ptr)(proc_t *, proc_t *); 71void (*dtrace_fasttrap_exec_ptr)(proc_t *); 72void (*dtrace_fasttrap_exit_ptr)(proc_t *); 73 74/* 75 * This function is called by cfork() in the event that it appears that 76 * there may be dtrace tracepoints active in the parent process's address 77 * space. This first confirms the existence of dtrace tracepoints in the 78 * parent process and calls into the fasttrap module to remove the 79 * corresponding tracepoints from the child. By knowing that there are 80 * existing tracepoints, and ensuring they can't be removed, we can rely 81 * on the fasttrap module remaining loaded. 82 */ 83void 84dtrace_fasttrap_fork(proc_t *p, proc_t *cp) 85{ 86#if !defined(__APPLE__) 87 ASSERT(p->p_proc_flag & P_PR_LOCK); 88 ASSERT(p->p_dtrace_count > 0); 89#endif /* __APPLE__ */ 90 91 if (dtrace_fasttrap_fork_ptr) { 92 (*dtrace_fasttrap_fork_ptr)(p, cp); 93 } 94} 95 96typedef struct dtrace_invop_hdlr { 97 int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t); 98 struct dtrace_invop_hdlr *dtih_next; 99} dtrace_invop_hdlr_t; 100 101dtrace_invop_hdlr_t *dtrace_invop_hdlr; 102 103int 104dtrace_invop(uintptr_t, uintptr_t *, uintptr_t); 105 106int 107dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax) 108{ 109 dtrace_invop_hdlr_t *hdlr; 110 int rval; 111 112 for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next) { 113 if ((rval = hdlr->dtih_func(addr, stack, eax)) != 0) 114 return (rval); 115 } 116 117 return (0); 118} 119 120void 121dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t)) 122{ 123 dtrace_invop_hdlr_t *hdlr; 124 125 hdlr = kmem_alloc(sizeof (dtrace_invop_hdlr_t), KM_SLEEP); 126 hdlr->dtih_func = func; 127 hdlr->dtih_next = dtrace_invop_hdlr; 128 dtrace_invop_hdlr = hdlr; 129} 130 131void 132dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t)) 133{ 134 dtrace_invop_hdlr_t *hdlr = dtrace_invop_hdlr, *prev = NULL; 135 136 for (;;) { 137 if (hdlr == NULL) 138 panic("attempt to remove non-existent invop handler"); 139 140 if (hdlr->dtih_func == func) 141 break; 142 143 prev = hdlr; 144 hdlr = hdlr->dtih_next; 145 } 146 147 if (prev == NULL) { 148 ASSERT(dtrace_invop_hdlr == hdlr); 149 dtrace_invop_hdlr = hdlr->dtih_next; 150 } else { 151 ASSERT(dtrace_invop_hdlr != hdlr); 152 prev->dtih_next = hdlr->dtih_next; 153 } 154 155 kmem_free(hdlr, sizeof (dtrace_invop_hdlr_t)); 156} 157 158