1/* 2 * Copyright (c) 2006-2008 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#if defined(__APPLE__) 25 26// This must be done *after* any references to Foundation.h! 27#define uint_t __Solaris_uint_t 28 29#import <pthread.h> 30 31#import <sys/dtrace.h> 32#import <dtrace.h> 33 34#import <dt_proc.h> 35#import <dt_pid.h> 36 37/* 38 * FIX ME. This is a direct cut & paste from 39 * dt_pid.c. It is probably already out of sync. 40 */ 41typedef struct dt_pid_probe { 42 dtrace_hdl_t *dpp_dtp; 43 dt_pcb_t *dpp_pcb; 44 dt_proc_t *dpp_dpr; 45 struct ps_prochandle *dpp_pr; 46 fasttrap_provider_type_t dpp_provider_type; 47 const char *dpp_mod; 48 char *dpp_func; 49 const char *dpp_name; 50 const char *dpp_obj; 51 uintptr_t dpp_pc; 52 size_t dpp_size; 53 Lmid_t dpp_lmid; 54 uint_t dpp_nmatches; 55 uint64_t dpp_stret[4]; 56 GElf_Sym dpp_last; 57 uint_t dpp_last_taken; 58} dt_pid_probe_t; 59 60/* 61 * OBJC provider methods 62 */ 63 64static int dt_pid_objc_filt(void *arg, const GElf_Sym *sym, const char *class_name, const char *method_name) 65{ 66 dt_pid_probe_t *pp = arg; 67 68 // Handle the class name first. 69 if ((strisglob(pp->dpp_mod) && gmatch(class_name, pp->dpp_mod)) || (strcmp(class_name, pp->dpp_mod) == 0)) { 70 // Now check the method name. 71 if ((strisglob(pp->dpp_func) && gmatch(method_name, pp->dpp_func)) || (strcmp(method_name, pp->dpp_func) == 0)) { 72 pp->dpp_obj = class_name; 73 // At this point, we can cheat and use the normal pid probe code. 74 return dt_pid_per_sym(pp, sym, method_name); 75 } 76 } 77 78 return (0); 79} 80 81int dt_pid_create_objc_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb, dt_proc_t *dpr) 82{ 83 dt_pid_probe_t pp; 84 int ret = 0; 85 86 /* 87 * Disable breakpoints so they don't interfere with our disassembly. 88 */ 89 dt_proc_bpdisable(dpr); 90 91 pp.dpp_dtp = dtp; 92 pp.dpp_dpr = dpr; 93 pp.dpp_pr = dpr->dpr_proc; 94 pp.dpp_pcb = pcb; 95 96 /* 97 * We can only trace dynamically-linked executables (since we've 98 * hidden some magic in ld.so.1 as well as libc.so.1). 99 */ 100#if defined(__APPLE__) 101 prmap_t thread_local_map; 102 if (Pname_to_map(pp.dpp_pr, PR_OBJ_LDSO, &thread_local_map) == NULL) { 103 return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_DYN, 104 "process %s has no dyld, and cannot be instrumented", 105 &pdp->dtpd_provider[3])); 106 } 107#else 108 if (Pname_to_map(pp.dpp_pr, PR_OBJ_LDSO) == NULL) { 109 return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_DYN, 110 "process %s is not a dynamically-linked executable", 111 &pdp->dtpd_provider[3])); 112 } 113#endif 114 115 pp.dpp_provider_type = DTFTP_PROVIDER_OBJC; 116 pp.dpp_mod = pdp->dtpd_mod[0] != '\0' ? pdp->dtpd_mod : "*"; 117 pp.dpp_func = pdp->dtpd_func[0] != '\0' ? pdp->dtpd_func : "*"; 118 pp.dpp_name = pdp->dtpd_name[0] != '\0' ? pdp->dtpd_name : "*"; 119 pp.dpp_last_taken = 0; 120 121 // 122 // We set up some default values that normally change per module. 123 // 124 pp.dpp_lmid = LM_ID_BASE; 125 pp.dpp_stret[0] = 0; 126 pp.dpp_stret[1] = 0; 127 pp.dpp_stret[2] = 0; 128 pp.dpp_stret[3] = 0; 129 130 /* 131 * We're working in the objc namespace, symbols are in "library, function" style. 132 * We have to look at every symbol in every owner, even without globbing. 133 */ 134 135 ret = Pobjc_method_iter(pp.dpp_pr, (proc_objc_f*)dt_pid_objc_filt, &pp); 136 137 dt_proc_bpenable(dpr); 138 139 return (ret); 140} 141 142#endif /* __APPLE__ */