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. 
   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. 
  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] 
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved. 
  23  * Use is subject to license terms. 
  26 /* #pragma ident        "@(#)sdt.c      1.9     08/07/01 SMI" */ 
  30 #define _KERNEL /* Solaris vs. Darwin */ 
  34 #include <sys/param.h> 
  35 #include <sys/systm.h> 
  36 #include <sys/errno.h> 
  38 #include <sys/ioctl.h> 
  40 #include <sys/fcntl.h> 
  41 #include <miscfs/devfs/devfs.h> 
  43 #include <sys/dtrace.h> 
  44 #include <sys/dtrace_impl.h> 
  46 #include <sys/dtrace_glue.h> 
  48 #include <sys/sdt_impl.h> 
  49 extern int dtrace_kernel_symbol_mode
; 
  51 struct savearea_t
; /* Used anonymously */ 
  52 typedef kern_return_t (*perfCallback
)(int, struct savearea_t 
*, uintptr_t *, int); 
  54 #if defined(__i386__) || defined(__x86_64__) 
  55 extern perfCallback tempDTraceTrapHook
; 
  56 extern kern_return_t 
fbt_perfCallback(int, struct savearea_t 
*, int, int); 
  58 #define SDT_PATCHVAL    0xf0 
  61 #error Unknown architecture 
  64 #define SDT_PROBETAB_SIZE       0x1000          /* 4k entries -- 16K total */ 
  66 #if defined(__x86_64__) 
  67 #define DTRACE_PROBE_PREFIX "_dtrace_probeDOLLAR" 
  69 #define DTRACE_PROBE_PREFIX "_dtrace_probe$" 
  72 static dev_info_t               
*sdt_devi
; 
  73 static int                      sdt_verbose 
= 0; 
  74 sdt_probe_t             
**sdt_probetab
; 
  75 int                     sdt_probetab_size
; 
  76 int                     sdt_probetab_mask
; 
  80 __sdt_provide_module(void *arg
, struct modctl 
*ctl
) 
  83         struct module *mp 
= (struct module *)ctl
->mod_address
; 
  84         char *modname 
= ctl
->mod_modname
; 
  85         sdt_probedesc_t 
*sdpd
; 
  86         sdt_probe_t 
*sdp
, *old
; 
  91          * One for all, and all for one:  if we haven't yet registered all of 
  92          * our providers, we'll refuse to provide anything. 
  94         for (prov 
= sdt_providers
; prov
->sdtp_name 
!= NULL
; prov
++) { 
  95                 if (prov
->sdtp_id 
== DTRACE_PROVNONE
) 
  99         if (!mp 
|| mp
->sdt_nprobes 
!= 0 || (sdpd 
= mp
->sdt_probes
) == NULL
) 
 102         for (sdpd 
= mp
->sdt_probes
; sdpd 
!= NULL
; sdpd 
= sdpd
->sdpd_next
) { 
 103             const char *name 
= sdpd
->sdpd_name
, *func
; 
 108                 for (prov 
= sdt_providers
; prov
->sdtp_prefix 
!= NULL
; prov
++) { 
 109                         const char *prefpart
, *prefix 
= prov
->sdtp_prefix
; 
 111                         if ((prefpart 
= strstr(name
, prefix
))) { 
 112                                 name 
= prefpart 
+ strlen(prefix
); 
 117                 nname 
= kmem_alloc(len 
= strlen(name
) + 1, KM_SLEEP
); 
 119                 for (i 
= 0, j 
= 0; name
[j
] != '\0'; i
++) { 
 120                         if (name
[j
] == '_' && name
[j 
+ 1] == '_') { 
 124                                 nname
[i
] = name
[j
++]; 
 130                 sdp 
= kmem_zalloc(sizeof (sdt_probe_t
), KM_SLEEP
); 
 131                 sdp
->sdp_loadcnt 
= ctl
->mod_loadcnt
; 
 133                 sdp
->sdp_name 
= nname
; 
 134                 sdp
->sdp_namelen 
= len
; 
 135                 sdp
->sdp_provider 
= prov
; 
 137                 func 
= sdpd
->sdpd_func
; 
 143                  * We have our provider.  Now create the probe. 
 145                 if ((id 
= dtrace_probe_lookup(prov
->sdtp_id
, modname
, 
 146                     func
, nname
)) != DTRACE_IDNONE
) { 
 147                         old 
= dtrace_probe_arg(prov
->sdtp_id
, id
); 
 150                         sdp
->sdp_next 
= old
->sdp_next
; 
 154                         sdp
->sdp_id 
= dtrace_probe_create(prov
->sdtp_id
, 
 155                             modname
, func
, nname
, SDT_AFRAMES
, sdp
); 
 161                     sdt_probetab
[SDT_ADDR2NDX(sdpd
->sdpd_offset
)]; 
 162                 sdt_probetab
[SDT_ADDR2NDX(sdpd
->sdpd_offset
)] = sdp
; 
 164                 sdp
->sdp_patchval 
= SDT_PATCHVAL
; 
 165                 sdp
->sdp_patchpoint 
= (sdt_instr_t 
*)sdpd
->sdpd_offset
; 
 166                 sdp
->sdp_savedval 
= *sdp
->sdp_patchpoint
; 
 172 sdt_destroy(void *arg
, dtrace_id_t id
, void *parg
) 
 174 #pragma unused(arg,id) 
 175         sdt_probe_t 
*sdp 
= parg
, *old
, *last
, *hash
; 
 177 #if !defined(__APPLE__) 
 178         struct modctl 
*ctl 
= sdp
->sdp_ctl
; 
 180         if (ctl 
!= NULL 
&& ctl
->mod_loadcnt 
== sdp
->sdp_loadcnt
) { 
 181                 if ((ctl
->mod_loadcnt 
== sdp
->sdp_loadcnt 
&& 
 183                         ((struct module *)(ctl
->mod_mp
))->sdt_nprobes
--; 
 186 #endif /* __APPLE__ */ 
 188         while (sdp 
!= NULL
) { 
 192                  * Now we need to remove this probe from the sdt_probetab. 
 194                 ndx 
= SDT_ADDR2NDX(sdp
->sdp_patchpoint
); 
 196                 hash 
= sdt_probetab
[ndx
]; 
 198                 while (hash 
!= sdp
) { 
 199                         ASSERT(hash 
!= NULL
); 
 201                         hash 
= hash
->sdp_hashnext
; 
 205                         last
->sdp_hashnext 
= sdp
->sdp_hashnext
; 
 207                         sdt_probetab
[ndx
] = sdp
->sdp_hashnext
; 
 210                 kmem_free(sdp
->sdp_name
, sdp
->sdp_namelen
); 
 212                 kmem_free(old
, sizeof (sdt_probe_t
)); 
 218 sdt_enable(void *arg
, dtrace_id_t id
, void *parg
) 
 220 #pragma unused(arg,id) 
 221         sdt_probe_t 
*sdp 
= parg
; 
 222         struct modctl 
*ctl 
= sdp
->sdp_ctl
; 
 227          * If this module has disappeared since we discovered its probes, 
 228          * refuse to enable it. 
 230         if (!ctl
->mod_loaded
) { 
 232                         cmn_err(CE_NOTE
, "sdt is failing for probe %s " 
 233                             "(module %s unloaded)", 
 234                             sdp
->sdp_name
, ctl
->mod_modname
); 
 240          * Now check that our modctl has the expected load count.  If it 
 241          * doesn't, this module must have been unloaded and reloaded -- and 
 242          * we're not going to touch it. 
 244         if (ctl
->mod_loadcnt 
!= sdp
->sdp_loadcnt
) { 
 246                         cmn_err(CE_NOTE
, "sdt is failing for probe %s " 
 247                             "(module %s reloaded)", 
 248                             sdp
->sdp_name
, ctl
->mod_modname
); 
 253         dtrace_casptr(&tempDTraceTrapHook
, NULL
, fbt_perfCallback
); 
 254         if (tempDTraceTrapHook 
!= (perfCallback
)fbt_perfCallback
) { 
 256                         cmn_err(CE_NOTE
, "sdt_enable is failing for probe %s " 
 257                             "in module %s: tempDTraceTrapHook already occupied.", 
 258                             sdp
->sdp_name
, ctl
->mod_modname
); 
 263         while (sdp 
!= NULL
) { 
 264                 (void)ml_nofault_copy( (vm_offset_t
)&sdp
->sdp_patchval
, (vm_offset_t
)sdp
->sdp_patchpoint
,  
 265                                        (vm_size_t
)sizeof(sdp
->sdp_patchval
)); 
 275 sdt_disable(void *arg
, dtrace_id_t id
, void *parg
) 
 277 #pragma unused(arg,id) 
 278         sdt_probe_t 
*sdp 
= parg
; 
 279         struct modctl 
*ctl 
= sdp
->sdp_ctl
; 
 283         if (!ctl
->mod_loaded 
|| ctl
->mod_loadcnt 
!= sdp
->sdp_loadcnt
) 
 286         while (sdp 
!= NULL
) { 
 287                 (void)ml_nofault_copy( (vm_offset_t
)&sdp
->sdp_savedval
, (vm_offset_t
)sdp
->sdp_patchpoint
,  
 288                                        (vm_size_t
)sizeof(sdp
->sdp_savedval
)); 
 296 static dtrace_pops_t sdt_pops 
= { 
 311 sdt_attach(dev_info_t 
*devi
, ddi_attach_cmd_t cmd
) 
 314         sdt_provider_t 
*prov
; 
 316         if (ddi_create_minor_node(devi
, "sdt", S_IFCHR
, 
 317             0, DDI_PSEUDO
, 0) == DDI_FAILURE
) { 
 318                 cmn_err(CE_NOTE
, "/dev/sdt couldn't create minor node"); 
 319                 ddi_remove_minor_node(devi
, NULL
); 
 320                 return (DDI_FAILURE
); 
 323         ddi_report_dev(devi
); 
 326         if (sdt_probetab_size 
== 0) 
 327                 sdt_probetab_size 
= SDT_PROBETAB_SIZE
; 
 329         sdt_probetab_mask 
= sdt_probetab_size 
- 1; 
 331             kmem_zalloc(sdt_probetab_size 
* sizeof (sdt_probe_t 
*), KM_SLEEP
); 
 332         dtrace_invop_add(sdt_invop
); 
 334         for (prov 
= sdt_providers
; prov
->sdtp_name 
!= NULL
; prov
++) { 
 335                 if (dtrace_register(prov
->sdtp_name
, prov
->sdtp_attr
, 
 336                     DTRACE_PRIV_KERNEL
, NULL
, 
 337                     &sdt_pops
, prov
, &prov
->sdtp_id
) != 0) { 
 338                         cmn_err(CE_WARN
, "failed to register sdt provider %s", 
 343         return (DDI_SUCCESS
); 
 346 #if !defined(__APPLE__) 
 349 sdt_detach(dev_info_t 
*dip
, ddi_detach_cmd_t cmd
) 
 351         sdt_provider_t 
*prov
; 
 358                 return (DDI_SUCCESS
); 
 361                 return (DDI_FAILURE
); 
 364         for (prov 
= sdt_providers
; prov
->sdtp_name 
!= NULL
; prov
++) { 
 365                 if (prov
->sdtp_id 
!= DTRACE_PROVNONE
) { 
 366                         if (dtrace_unregister(prov
->sdtp_id
) != 0) 
 367                                 return (DDI_FAILURE
); 
 369                         prov
->sdtp_id 
= DTRACE_PROVNONE
; 
 373         dtrace_invop_remove(sdt_invop
); 
 374         kmem_free(sdt_probetab
, sdt_probetab_size 
* sizeof (sdt_probe_t 
*)); 
 376         return (DDI_SUCCESS
); 
 381 sdt_info(dev_info_t 
*dip
, ddi_info_cmd_t infocmd
, void *arg
, void **result
) 
 386         case DDI_INFO_DEVT2DEVINFO
: 
 387                 *result 
= (void *)sdt_devi
; 
 390         case DDI_INFO_DEVT2INSTANCE
: 
 402 sdt_open(dev_t 
*devp
, int flag
, int otyp
, cred_t 
*cred_p
) 
 407 static struct cb_ops sdt_cb_ops 
= { 
 410         nulldev
,                /* strategy */ 
 420         ddi_prop_op
,            /* cb_prop_op */ 
 422         D_NEW 
| D_MP            
/* Driver compatibility flag */ 
 425 static struct dev_ops sdt_ops 
= { 
 426         DEVO_REV
,               /* devo_rev, */ 
 428         sdt_info
,               /* get_dev_info */ 
 429         nulldev
,                /* identify */ 
 431         sdt_attach
,             /* attach */ 
 432         sdt_detach
,             /* detach */ 
 434         &sdt_cb_ops
,            /* driver operations */ 
 435         NULL
,                   /* bus operations */ 
 436         nodev                   
/* dev power */ 
 440  * Module linkage information for the kernel. 
 442 static struct modldrv modldrv 
= { 
 443         &mod_driverops
,         /* module type (this is a pseudo driver) */ 
 444         "Statically Defined Tracing",   /* name of module */ 
 445         &sdt_ops
,               /* driver ops */ 
 448 static struct modlinkage modlinkage 
= { 
 457         return (mod_install(&modlinkage
)); 
 461 _info(struct modinfo 
*modinfop
) 
 463         return (mod_info(&modlinkage
, modinfop
)); 
 469         return (mod_remove(&modlinkage
)); 
 474 int _sdt_open(dev_t dev
, int flags
, int devtype
, struct proc 
*p
) 
 476 #pragma unused(dev,flags,devtype,p) 
 480 #define SDT_MAJOR  -24 /* let the kernel pick the device number */ 
 483  * A struct describing which functions will get invoked for certain 
 486 static struct cdevsw sdt_cdevsw 
= 
 488         _sdt_open
,              /* open */ 
 489         eno_opcl
,                       /* close */ 
 490         eno_rdwrt
,                      /* read */ 
 491         eno_rdwrt
,                      /* write */ 
 492         eno_ioctl
,                      /* ioctl */ 
 493         (stop_fcn_t 
*)nulldev
, /* stop */ 
 494         (reset_fcn_t 
*)nulldev
, /* reset */ 
 496         eno_select
,                     /* select */ 
 498         eno_strat
,                      /* strategy */ 
 504 static int gSDTInited 
= 0; 
 505 static struct modctl g_sdt_kernctl
; 
 506 static struct module g_sdt_mach_module
; 
 508 #include <mach-o/nlist.h> 
 509 #include <libkern/kernel_mach_header.h> 
 511 #if defined(__LP64__) 
 512 #define KERNEL_MAGIC MH_MAGIC_64 
 513 typedef struct nlist_64 kernel_nlist_t
; 
 515 #define KERNEL_MAGIC MH_MAGIC 
 516 typedef struct nlist kernel_nlist_t
; 
 519 void sdt_init( void ) 
 523                 int majdevno 
= cdevsw_add(SDT_MAJOR
, &sdt_cdevsw
); 
 526                         printf("sdt_init: failed to allocate a major number!\n"); 
 531                 if (KERNEL_MAGIC 
!= _mh_execute_header
.magic
) { 
 532                         g_sdt_kernctl
.mod_address 
= (vm_address_t
)NULL
; 
 533                         g_sdt_kernctl
.mod_size 
= 0; 
 535                         kernel_mach_header_t        
*mh
; 
 536                         struct load_command         
*cmd
; 
 537                         kernel_segment_command_t    
*orig_ts 
= NULL
, *orig_le 
= NULL
; 
 538                         struct symtab_command       
*orig_st 
= NULL
; 
 539                         kernel_nlist_t              
*sym 
= NULL
; 
 543                         g_sdt_mach_module
.sdt_nprobes 
= 0; 
 544                         g_sdt_mach_module
.sdt_probes 
= NULL
; 
 546                         g_sdt_kernctl
.mod_address 
= (vm_address_t
)&g_sdt_mach_module
; 
 547                         g_sdt_kernctl
.mod_size 
= 0; 
 548                         strncpy((char *)&(g_sdt_kernctl
.mod_modname
), "mach_kernel", KMOD_MAX_NAME
); 
 550                         g_sdt_kernctl
.mod_next 
= NULL
; 
 551                         g_sdt_kernctl
.mod_stale 
= NULL
; 
 552                         g_sdt_kernctl
.mod_id 
= 0; 
 553                         g_sdt_kernctl
.mod_loadcnt 
= 1; 
 554                         g_sdt_kernctl
.mod_loaded 
= 1; 
 555                         g_sdt_kernctl
.mod_flags 
= 0; 
 556                         g_sdt_kernctl
.mod_nenabled 
= 0; 
 558                         mh 
= &_mh_execute_header
; 
 559                         cmd 
= (struct load_command
*) &mh
[1]; 
 560                         for (i 
= 0; i 
< mh
->ncmds
; i
++) { 
 561                                 if (cmd
->cmd 
== LC_SEGMENT_KERNEL
) { 
 562                                         kernel_segment_command_t 
*orig_sg 
= (kernel_segment_command_t 
*) cmd
; 
 564                                         if (LIT_STRNEQL(orig_sg
->segname
, SEG_TEXT
)) 
 566                                         else if (LIT_STRNEQL(orig_sg
->segname
, SEG_LINKEDIT
)) 
 568                                         else if (LIT_STRNEQL(orig_sg
->segname
, "")) 
 569                                                 orig_ts 
= orig_sg
; /* kexts have a single unnamed segment */ 
 571                                 else if (cmd
->cmd 
== LC_SYMTAB
) 
 572                                         orig_st 
= (struct symtab_command 
*) cmd
; 
 574                                 cmd 
= (struct load_command 
*) ((uintptr_t) cmd 
+ cmd
->cmdsize
); 
 577                         if ((orig_ts 
== NULL
) || (orig_st 
== NULL
) || (orig_le 
== NULL
)) 
 580                         sym 
= (kernel_nlist_t 
*)(orig_le
->vmaddr 
+ orig_st
->symoff 
- orig_le
->fileoff
); 
 581                         strings 
= (char *)(orig_le
->vmaddr 
+ orig_st
->stroff 
- orig_le
->fileoff
); 
 583                         for (i 
= 0; i 
< orig_st
->nsyms
; i
++) { 
 584                                 uint8_t n_type 
= sym
[i
].n_type 
& (N_TYPE 
| N_EXT
); 
 585                                 char *name 
= strings 
+ sym
[i
].n_un
.n_strx
; 
 586                                 const char *prev_name
; 
 590                                 /* Check that the symbol is a global and that it has a name. */ 
 591                                 if (((N_SECT 
| N_EXT
) != n_type 
&& (N_ABS 
| N_EXT
) != n_type
)) 
 594                                 if (0 == sym
[i
].n_un
.n_strx
) /* iff a null, "", name. */ 
 597                                 /* Lop off omnipresent leading underscore. */ 
 601                                 if (strncmp(name
, DTRACE_PROBE_PREFIX
, sizeof(DTRACE_PROBE_PREFIX
) - 1) == 0) { 
 602                                         sdt_probedesc_t 
*sdpd 
= kmem_alloc(sizeof(sdt_probedesc_t
), KM_SLEEP
); 
 603                                         int len 
= strlen(name
) + 1; 
 605                                         sdpd
->sdpd_name 
= kmem_alloc(len
, KM_SLEEP
); 
 606                                         strncpy(sdpd
->sdpd_name
, name
, len
); /* NUL termination is ensured. */ 
 608                                         prev_name 
= "<unknown>"; 
 612                                          * Find the symbol immediately preceding the sdt probe site just discovered, 
 613                                          * that symbol names the function containing the sdt probe. 
 615                                         for (j 
= 0; j 
< orig_st
->nsyms
; j
++) { 
 616                                                 uint8_t jn_type 
= sym
[j
].n_type 
& (N_TYPE 
| N_EXT
); 
 617                                                 char *jname 
= strings 
+ sym
[j
].n_un
.n_strx
; 
 619                                                 if (((N_SECT 
| N_EXT
) != jn_type 
&& (N_ABS 
| N_EXT
) != jn_type
)) 
 622                                                 if (0 == sym
[j
].n_un
.n_strx
) /* iff a null, "", name. */ 
 628                                                 if (*(unsigned long *)sym
[i
].n_value 
<= (unsigned long)sym
[j
].n_value
) 
 631                                                 if ((unsigned long)sym
[j
].n_value 
> best
) { 
 632                                                         best 
= (unsigned long)sym
[j
].n_value
; 
 637                                         sdpd
->sdpd_func 
= kmem_alloc((len 
= strlen(prev_name
) + 1), KM_SLEEP
); 
 638                                         strncpy(sdpd
->sdpd_func
, prev_name
, len
); /* NUL termination is ensured. */ 
 640                                         sdpd
->sdpd_offset 
= *(unsigned long *)sym
[i
].n_value
; 
 642                                         sdpd
->sdpd_next 
= g_sdt_mach_module
.sdt_probes
; 
 643                                         g_sdt_mach_module
.sdt_probes 
= sdpd
; 
 650                 sdt_attach( (dev_info_t 
*)(uintptr_t)majdevno
, DDI_ATTACH 
); 
 654                 panic("sdt_init: called twice!\n"); 
 661 sdt_provide_module(void *arg
, struct modctl 
*ctl
) 
 665         ASSERT(dtrace_kernel_symbol_mode 
!= DTRACE_KERNEL_SYMBOLS_NEVER
); 
 666         lck_mtx_assert(&mod_lock
, LCK_MTX_ASSERT_OWNED
); 
 668         if (MOD_SDT_DONE(ctl
)) 
 671         if (MOD_IS_MACH_KERNEL(ctl
)) { 
 672                 __sdt_provide_module(arg
, &g_sdt_kernctl
); 
 674                 sdt_probedesc_t 
*sdpd 
= g_sdt_mach_module
.sdt_probes
; 
 676                         sdt_probedesc_t 
*this_sdpd 
= sdpd
; 
 677                         kmem_free((void *)sdpd
->sdpd_name
, strlen(sdpd
->sdpd_name
) + 1); 
 678                         kmem_free((void *)sdpd
->sdpd_func
, strlen(sdpd
->sdpd_func
) + 1); 
 679                         sdpd 
= sdpd
->sdpd_next
; 
 680                         kmem_free((void *)this_sdpd
, sizeof(sdt_probedesc_t
)); 
 682                 g_sdt_mach_module
.sdt_probes 
= NULL
; 
 684                 /* FIXME -- sdt in kext not yet supported */ 
 687         /* Need to mark this module as completed */ 
 688         ctl
->mod_flags 
|= MODCTL_SDT_PROBES_PROVIDED
; 
 691 #endif /* __APPLE__ */