1 /*        $NetBSD: fbt.c,v 1.29 2022/09/02 11:03:50 riastradh Exp $   */
2 
3 /*
4  * CDDL HEADER START
5  *
6  * The contents of this file are subject to the terms of the
7  * Common Development and Distribution License (the "License").
8  * You may not use this file except in compliance with the License.
9  *
10  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11  * or http://www.opensolaris.org/os/licensing.
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  *
23  * Portions Copyright 2006-2008 John Birrell jb@freebsd.org
24  * Portions Copyright 2010 Darran Hunt darran@NetBSD.org
25  *
26  * $FreeBSD: head/sys/cddl/dev/fbt/fbt.c 309786 2016-12-10 03:13:11Z markj $
27  *
28  */
29 
30 /*
31  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
32  * Use is subject to license terms.
33  */
34 
35 #include <sys/cdefs.h>
36 #include <sys/proc.h>
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/conf.h>
40 #include <sys/cpuvar.h>
41 #include <sys/fcntl.h>
42 #include <sys/filio.h>
43 #include <sys/kernel.h>
44 #include <sys/kmem.h>
45 #include <sys/ksyms.h>
46 #include <sys/cpu.h>
47 #include <sys/kthread.h>
48 #include <sys/syslimits.h>
49 #include <sys/linker.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/module.h>
53 #include <sys/mutex.h>
54 #include <sys/poll.h>
55 #include <sys/proc.h>
56 #include <sys/selinfo.h>
57 #include <sys/syscall.h>
58 #include <sys/uio.h>
59 #include <sys/unistd.h>
60 #include <sys/exec_elf.h>
61 
62 #include <sys/dtrace.h>
63 #include <sys/dtrace_bsd.h>
64 #include <sys/kern_ctf.h>
65 #include <sys/dtrace_impl.h>
66 
67 #include "fbt.h"
68 
69 mod_ctf_t *modptr;
70 
71 dtrace_provider_id_t          fbt_id;
72 fbt_probe_t                   **fbt_probetab;
73 int                           fbt_probetab_mask;
74 static int                              fbt_probetab_size;
75 
76 static dev_type_open(fbt_open);
77 static int          fbt_unload(void);
78 static void         fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
79 static void         fbt_provide_module(void *, modctl_t *);
80 static void         fbt_destroy(void *, dtrace_id_t, void *);
81 static int          fbt_enable(void *, dtrace_id_t, void *);
82 static void         fbt_disable(void *, dtrace_id_t, void *);
83 static void         fbt_load(void);
84 static void         fbt_suspend(void *, dtrace_id_t, void *);
85 static void         fbt_resume(void *, dtrace_id_t, void *);
86 
87 static const struct cdevsw fbt_cdevsw = {
88           .d_open             = fbt_open,
89           .d_close  = noclose,
90           .d_read             = noread,
91           .d_write  = nowrite,
92           .d_ioctl  = noioctl,
93           .d_stop             = nostop,
94           .d_tty              = notty,
95           .d_poll             = nopoll,
96           .d_mmap             = nommap,
97           .d_kqfilter         = nokqfilter,
98           .d_discard          = nodiscard,
99           .d_flag             = D_OTHER
100 };
101 
102 static dtrace_pattr_t fbt_attr = {
103 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
104 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
105 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
106 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
107 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
108 };
109 
110 static dtrace_pops_t fbt_pops = {
111           NULL,
112           fbt_provide_module,
113           fbt_enable,
114           fbt_disable,
115           fbt_suspend,
116           fbt_resume,
117           fbt_getargdesc,
118           NULL,
119           NULL,
120           fbt_destroy
121 };
122 
123 #ifdef __FreeBSD__
124 static int                              fbt_verbose = 0;
125 
126 static struct cdev            *fbt_cdev;
127 #endif /* __FreeBSD__ */
128 
129 #ifdef __NetBSD__
130 specificdata_key_t fbt_module_key;
131 
132 #define version xversion
133 #endif /* __NetBSD__ */
134 
135 int
fbt_excluded(const char * name)136 fbt_excluded(const char *name)
137 {
138 
139           if (strncmp(name, "dtrace_", 7) == 0 &&
140               strncmp(name, "dtrace_safe_", 12) != 0) {
141                     /*
142                      * Anything beginning with "dtrace_" may be called
143                      * from probe context unless it explicitly indicates
144                      * that it won't be called from probe context by
145                      * using the prefix "dtrace_safe_".
146                      */
147                     return (1);
148           }
149 
150 #ifdef __FreeBSD__
151           /*
152            * Lock owner methods may be called from probe context.
153            */
154           if (strcmp(name, "owner_mtx") == 0 ||
155               strcmp(name, "owner_rm") == 0 ||
156               strcmp(name, "owner_rw") == 0 ||
157               strcmp(name, "owner_sx") == 0)
158                     return (1);
159 
160           /*
161            * When DTrace is built into the kernel we need to exclude
162            * the FBT functions from instrumentation.
163            */
164 #ifndef _KLD_MODULE
165           if (strncmp(name, "fbt_", 4) == 0)
166                     return (1);
167 #endif
168 #endif
169 
170 #ifdef __NetBSD__
171           if (strcmp(name, "cpu_index") == 0 ||
172               strncmp(name, "db_", 3) == 0 ||
173               strncmp(name, "ddb_", 4) == 0 ||
174               strncmp(name, "kdb_", 4) == 0 ||
175               strncmp(name, "lockdebug_", 10) == 0 ||
176               strncmp(name, "kauth_", 5) == 0 ||
177               strncmp(name, "ktext_write", 11) == 0 ||
178               strncmp(name, "fbt_", 4) == 0) {
179                     return (1);
180           }
181 #endif
182 
183           return (0);
184 }
185 
186 static void
fbt_doubletrap(void)187 fbt_doubletrap(void)
188 {
189           fbt_probe_t *fbt;
190           int i;
191 
192           for (i = 0; i < fbt_probetab_size; i++) {
193                     fbt = fbt_probetab[i];
194 
195                     for (; fbt != NULL; fbt = fbt->fbtp_next)
196                               fbt_patch_tracepoint(fbt, fbt->fbtp_savedval);
197           }
198 }
199 
200 #ifdef __FreeBSD__
201 static void
fbt_provide_module(void * arg,modctl_t * lf)202 fbt_provide_module(void *arg, modctl_t *lf)
203 {
204           char modname[MAXPATHLEN];
205           int i;
206           size_t len;
207 
208           strlcpy(modname, lf->filename, sizeof(modname));
209           len = strlen(modname);
210           if (len > 3 && strcmp(modname + len - 3, ".ko") == 0)
211                     modname[len - 3] = '\0';
212 
213           /*
214            * Employees of dtrace and their families are ineligible.  Void
215            * where prohibited.
216            */
217           if (strcmp(modname, "dtrace") == 0)
218                     return;
219 
220           /*
221            * To register with DTrace, a module must list 'dtrace' as a
222            * dependency in order for the kernel linker to resolve
223            * symbols like dtrace_register(). All modules with such a
224            * dependency are ineligible for FBT tracing.
225            */
226           for (i = 0; i < lf->ndeps; i++)
227                     if (strncmp(lf->deps[i]->filename, "dtrace", 6) == 0)
228                               return;
229 
230           if (lf->fbt_nentries) {
231                     /*
232                      * This module has some FBT entries allocated; we're afraid
233                      * to screw with it.
234                      */
235                     return;
236           }
237 
238           /*
239            * List the functions in the module and the symbol values.
240            */
241           (void) linker_file_function_listall(lf, fbt_provide_module_function, modname);
242 }
243 #endif
244 #ifdef __NetBSD__
245 static void
fbt_provide_module(void * arg,modctl_t * mod)246 fbt_provide_module(void *arg, modctl_t *mod)
247 {
248           struct fbt_ksyms_arg fka;
249           struct mod_ctf *mc;
250           char modname[MAXPATHLEN];
251           int i;
252           size_t len;
253 
254           if (mod_ctf_get(mod, &mc)) {
255                     printf("fbt: no CTF data for module %s\n", module_name(mod));
256                     return;
257           }
258 
259           strlcpy(modname, module_name(mod), sizeof(modname));
260           len = strlen(modname);
261           if (len > 5 && strcmp(modname + len - 3, ".kmod") == 0)
262                     modname[len - 4] = '\0';
263 
264           /*
265            * Employees of dtrace and their families are ineligible.  Void
266            * where prohibited.
267            */
268           if (strcmp(modname, "dtrace") == 0)
269                     return;
270 
271           /*
272            * The cyclic timer subsystem can be built as a module and DTrace
273            * depends on that, so it is ineligible too.
274            */
275           if (strcmp(modname, "cyclic") == 0)
276                     return;
277 
278           /*
279            * To register with DTrace, a module must list 'dtrace' as a
280            * dependency in order for the kernel linker to resolve
281            * symbols like dtrace_register(). All modules with such a
282            * dependency are ineligible for FBT tracing.
283            */
284           for (i = 0; i < mod->mod_nrequired; i++) {
285                     if (strncmp(module_name((*mod->mod_required)[i]),
286                                   "dtrace", 6) == 0)
287                               return;
288           }
289           if (mc->fbt_provided) {
290                     return;
291           }
292 
293           /*
294            * List the functions in the module and the symbol values.
295            */
296           memset(&fka, 0, sizeof(fka));
297           fka.fka_mod = mod;
298           fka.fka_mc = mc;
299           ksyms_mod_foreach(modname, fbt_provide_module_cb, &fka);
300           mc->fbt_provided = true;
301 }
302 
303 static void
fbt_module_dtor(void * arg)304 fbt_module_dtor(void *arg)
305 {
306           mod_ctf_t *mc = arg;
307 
308           if (mc->ctfalloc)
309                     free(mc->ctftab, M_TEMP);
310           kmem_free(mc, sizeof(*mc));
311 }
312 #endif
313 
314 static void
fbt_destroy(void * arg,dtrace_id_t id,void * parg)315 fbt_destroy(void *arg, dtrace_id_t id, void *parg)
316 {
317           fbt_probe_t *fbt = parg, *next, *hash, *last;
318           modctl_t *ctl;
319           int ndx;
320 
321           do {
322                     ctl = fbt->fbtp_ctl;
323 
324 #ifdef __FreeBSD__
325                     ctl->mod_fbtentries--;
326 #endif
327 #ifdef __NetBSD__
328                     mod_ctf_t *mc = module_getspecific(ctl, fbt_module_key);
329                     mc->fbt_provided = false;
330 #endif
331 
332                     /*
333                      * Now we need to remove this probe from the fbt_probetab.
334                      */
335                     ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint);
336                     last = NULL;
337                     hash = fbt_probetab[ndx];
338 
339                     while (hash != fbt) {
340                               ASSERT(hash != NULL);
341                               last = hash;
342                               hash = hash->fbtp_hashnext;
343                     }
344 
345                     if (last != NULL) {
346                               last->fbtp_hashnext = fbt->fbtp_hashnext;
347                     } else {
348                               fbt_probetab[ndx] = fbt->fbtp_hashnext;
349                     }
350 
351                     next = fbt->fbtp_next;
352                     kmem_free(fbt, sizeof(*fbt));
353 
354                     fbt = next;
355           } while (fbt != NULL);
356 }
357 
358 static int
fbt_enable(void * arg,dtrace_id_t id,void * parg)359 fbt_enable(void *arg, dtrace_id_t id, void *parg)
360 {
361           fbt_probe_t *fbt = parg;
362           modctl_t *ctl = fbt->fbtp_ctl;
363 
364 #ifdef __NetBSD__
365           module_hold(ctl);
366 #else
367           ctl->nenabled++;
368 
369           /*
370            * Now check that our modctl has the expected load count.  If it
371            * doesn't, this module must have been unloaded and reloaded -- and
372            * we're not going to touch it.
373            */
374           if (ctl->loadcnt != fbt->fbtp_loadcnt) {
375                     if (fbt_verbose) {
376                               printf("fbt is failing for probe %s "
377                                   "(module %s reloaded)",
378                                   fbt->fbtp_name, module_name(ctl));
379                     }
380 
381                     return 0;
382           }
383 #endif
384 
385           for (; fbt != NULL; fbt = fbt->fbtp_next)
386                     fbt_patch_tracepoint(fbt, fbt->fbtp_patchval);
387           return 0;
388 }
389 
390 static void
fbt_disable(void * arg,dtrace_id_t id,void * parg)391 fbt_disable(void *arg, dtrace_id_t id, void *parg)
392 {
393           fbt_probe_t *fbt = parg;
394           modctl_t *ctl = fbt->fbtp_ctl;
395 
396 #ifndef __NetBSD__
397           ASSERT(ctl->nenabled > 0);
398           ctl->nenabled--;
399 
400           if ((ctl->loadcnt != fbt->fbtp_loadcnt))
401                     return;
402 #endif
403 
404           for (; fbt != NULL; fbt = fbt->fbtp_next)
405                     fbt_patch_tracepoint(fbt, fbt->fbtp_savedval);
406 
407 #ifdef __NetBSD__
408           module_rele(ctl);
409 #endif
410 }
411 
412 static void
fbt_suspend(void * arg,dtrace_id_t id,void * parg)413 fbt_suspend(void *arg, dtrace_id_t id, void *parg)
414 {
415           fbt_probe_t *fbt = parg;
416 #ifndef __NetBSD__
417           modctl_t *ctl = fbt->fbtp_ctl;
418 
419           ASSERT(ctl->nenabled > 0);
420 
421           if ((ctl->loadcnt != fbt->fbtp_loadcnt))
422                     return;
423 #endif
424 
425           for (; fbt != NULL; fbt = fbt->fbtp_next)
426                     fbt_patch_tracepoint(fbt, fbt->fbtp_savedval);
427 }
428 
429 static void
fbt_resume(void * arg,dtrace_id_t id,void * parg)430 fbt_resume(void *arg, dtrace_id_t id, void *parg)
431 {
432           fbt_probe_t *fbt = parg;
433 #ifndef __NetBSD__
434           modctl_t *ctl = fbt->fbtp_ctl;
435 
436           ASSERT(ctl->nenabled > 0);
437 
438           if ((ctl->loadcnt != fbt->fbtp_loadcnt))
439                     return;
440 #endif
441 
442           for (; fbt != NULL; fbt = fbt->fbtp_next)
443                     fbt_patch_tracepoint(fbt, fbt->fbtp_patchval);
444 }
445 
446 static int
fbt_ctfoff_init(modctl_t * mod,mod_ctf_t * mc)447 fbt_ctfoff_init(modctl_t *mod, mod_ctf_t *mc)
448 {
449           const Elf_Sym *symp = mc->symtab;
450           const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
451           const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t);
452           int i;
453           uint32_t *ctfoff;
454           uint32_t objtoff = hp->cth_objtoff;
455           uint32_t funcoff = hp->cth_funcoff;
456           ushort_t info;
457           ushort_t vlen;
458           int nsyms = (mc->nmap != NULL) ? mc->nmapsize : mc->nsym;
459 
460           /* Sanity check. */
461           if (hp->cth_magic != CTF_MAGIC) {
462                     printf("Bad magic value in CTF data of '%s'\n",
463                         module_name(mod));
464                     return (EINVAL);
465           }
466 
467           if (mc->symtab == NULL) {
468                     printf("No symbol table in '%s'\n", module_name(mod));
469                     return (EINVAL);
470           }
471 
472           ctfoff = malloc(sizeof(uint32_t) * nsyms, M_FBT, M_WAITOK);
473           mc->ctfoffp = ctfoff;
474 
475           for (i = 0; i < nsyms; i++, ctfoff++, symp++) {
476                     if (mc->nmap != NULL) {
477                               if (mc->nmap[i] == 0) {
478                                         printf("%s.%d: Error! Got zero nmap!\n",
479                                                   __func__, __LINE__);
480                                         continue;
481                               }
482 
483                               /*
484                                * CTF expects the unsorted symbol ordering,
485                                * so map it from that to the current sorted
486                                * symbol table.
487                                * ctfoff[new-ind] = oldind symbol info.
488                                */
489 
490                               /* map old index to new symbol table */
491                               symp = &mc->symtab[mc->nmap[i] - 1];
492 
493                               /* map old index to new ctfoff index */
494                               ctfoff = &mc->ctfoffp[mc->nmap[i]-1];
495                     }
496 
497                     /*
498                      * Note that due to how kern_ksyms.c adjusts st_name
499                      * to be the offset into a virtual combined strtab,
500                      * st_name will never be 0 for loaded modules.
501                      */
502 
503                     if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
504                               *ctfoff = 0xffffffff;
505                               continue;
506                     }
507 
508                     switch (ELF_ST_TYPE(symp->st_info)) {
509                     case STT_OBJECT:
510                               if (objtoff >= hp->cth_funcoff ||
511                             (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
512                                         *ctfoff = 0xffffffff;
513                                 break;
514                         }
515 
516                         *ctfoff = objtoff;
517                         objtoff += sizeof (ushort_t);
518                               break;
519 
520                     case STT_FUNC:
521                               if (funcoff >= hp->cth_typeoff) {
522                                         *ctfoff = 0xffffffff;
523                                         break;
524                               }
525 
526                               *ctfoff = funcoff;
527 
528                               info = *((const ushort_t *)(ctfdata + funcoff));
529                               vlen = CTF_INFO_VLEN(info);
530 
531                               /*
532                                * If we encounter a zero pad at the end, just skip it.
533                                * Otherwise skip over the function and its return type
534                                * (+2) and the argument list (vlen).
535                                */
536                               if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
537                                         funcoff += sizeof (ushort_t); /* skip pad */
538                               else
539                                         funcoff += sizeof (ushort_t) * (vlen + 2);
540                               break;
541 
542                     default:
543                               *ctfoff = 0xffffffff;
544                               break;
545                     }
546           }
547 
548           return (0);
549 }
550 
551 static ssize_t
fbt_get_ctt_size(uint8_t version,const ctf_type_t * tp,ssize_t * sizep,ssize_t * incrementp)552 fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep,
553     ssize_t *incrementp)
554 {
555           ssize_t size, increment;
556 
557           if (version > CTF_VERSION_1 &&
558               tp->ctt_size == CTF_LSIZE_SENT) {
559                     size = CTF_TYPE_LSIZE(tp);
560                     increment = sizeof (ctf_type_t);
561           } else {
562                     size = tp->ctt_size;
563                     increment = sizeof (ctf_stype_t);
564           }
565 
566           if (sizep)
567                     *sizep = size;
568           if (incrementp)
569                     *incrementp = increment;
570 
571           return (size);
572 }
573 
574 static int
fbt_typoff_init(mod_ctf_t * mc)575 fbt_typoff_init(mod_ctf_t *mc)
576 {
577           const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
578           const ctf_type_t *tbuf;
579           const ctf_type_t *tend;
580           const ctf_type_t *tp;
581           const uint8_t *ctfdata = mc->ctftab + sizeof(ctf_header_t);
582           int ctf_typemax = 0;
583           uint32_t *xp;
584           ulong_t pop[CTF_K_MAX + 1] = { 0 };
585 
586 
587           /* Sanity check. */
588           if (hp->cth_magic != CTF_MAGIC)
589                     return (EINVAL);
590 
591           tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
592           tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
593 
594           int child = hp->cth_parname != 0;
595 
596           /*
597            * We make two passes through the entire type section.  In this first
598            * pass, we count the number of each type and the total number of types.
599            */
600           for (tp = tbuf; tp < tend; ctf_typemax++) {
601                     ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
602                     ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
603                     ssize_t size, increment;
604 
605                     size_t vbytes;
606                     uint_t n;
607 
608                     (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
609 
610                     switch (kind) {
611                     case CTF_K_INTEGER:
612                     case CTF_K_FLOAT:
613                               vbytes = sizeof (uint_t);
614                               break;
615                     case CTF_K_ARRAY:
616                               vbytes = sizeof (ctf_array_t);
617                               break;
618                     case CTF_K_FUNCTION:
619                               vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
620                               break;
621                     case CTF_K_STRUCT:
622                     case CTF_K_UNION:
623                               if (size < CTF_LSTRUCT_THRESH) {
624                                         ctf_member_t *mp = (ctf_member_t *)
625                                             ((uintptr_t)tp + increment);
626 
627                                         vbytes = sizeof (ctf_member_t) * vlen;
628                                         for (n = vlen; n != 0; n--, mp++)
629                                                   child |= CTF_TYPE_ISCHILD(mp->ctm_type);
630                               } else {
631                                         ctf_lmember_t *lmp = (ctf_lmember_t *)
632                                             ((uintptr_t)tp + increment);
633 
634                                         vbytes = sizeof (ctf_lmember_t) * vlen;
635                                         for (n = vlen; n != 0; n--, lmp++)
636                                                   child |=
637                                                       CTF_TYPE_ISCHILD(lmp->ctlm_type);
638                               }
639                               break;
640                     case CTF_K_ENUM:
641                               vbytes = sizeof (ctf_enum_t) * vlen;
642                               break;
643                     case CTF_K_FORWARD:
644                               /*
645                                * For forward declarations, ctt_type is the CTF_K_*
646                                * kind for the tag, so bump that population count too.
647                                * If ctt_type is unknown, treat the tag as a struct.
648                                */
649                               if (tp->ctt_type == CTF_K_UNKNOWN ||
650                                   tp->ctt_type >= CTF_K_MAX)
651                                         pop[CTF_K_STRUCT]++;
652                               else
653                                         pop[tp->ctt_type]++;
654                               /*FALLTHRU*/
655                     case CTF_K_UNKNOWN:
656                               vbytes = 0;
657                               break;
658                     case CTF_K_POINTER:
659                     case CTF_K_TYPEDEF:
660                     case CTF_K_VOLATILE:
661                     case CTF_K_CONST:
662                     case CTF_K_RESTRICT:
663                               child |= CTF_TYPE_ISCHILD(tp->ctt_type);
664                               vbytes = 0;
665                               break;
666                     default:
667                               printf("%s(%d): detected invalid CTF kind -- %u\n",
668                                      __func__, __LINE__, kind);
669                               return (EIO);
670                     }
671                     tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
672                     pop[kind]++;
673           }
674 
675           /* account for a sentinel value below */
676           ctf_typemax++;
677           mc->typlen = ctf_typemax;
678 
679           xp = malloc(sizeof(uint32_t) * ctf_typemax, M_FBT, M_ZERO | M_WAITOK);
680 
681           mc->typoffp = xp;
682 
683           /* type id 0 is used as a sentinel value */
684           *xp++ = 0;
685 
686           /*
687            * In the second pass, fill in the type offset.
688            */
689           for (tp = tbuf; tp < tend; xp++) {
690                     ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
691                     ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
692                     ssize_t size, increment;
693 
694                     size_t vbytes;
695                     uint_t n;
696 
697                     (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment);
698 
699                     switch (kind) {
700                     case CTF_K_INTEGER:
701                     case CTF_K_FLOAT:
702                               vbytes = sizeof (uint_t);
703                               break;
704                     case CTF_K_ARRAY:
705                               vbytes = sizeof (ctf_array_t);
706                               break;
707                     case CTF_K_FUNCTION:
708                               vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
709                               break;
710                     case CTF_K_STRUCT:
711                     case CTF_K_UNION:
712                               if (size < CTF_LSTRUCT_THRESH) {
713                                         ctf_member_t *mp = (ctf_member_t *)
714                                             ((uintptr_t)tp + increment);
715 
716                                         vbytes = sizeof (ctf_member_t) * vlen;
717                                         for (n = vlen; n != 0; n--, mp++)
718                                                   child |= CTF_TYPE_ISCHILD(mp->ctm_type);
719                               } else {
720                                         ctf_lmember_t *lmp = (ctf_lmember_t *)
721                                             ((uintptr_t)tp + increment);
722 
723                                         vbytes = sizeof (ctf_lmember_t) * vlen;
724                                         for (n = vlen; n != 0; n--, lmp++)
725                                                   child |=
726                                                       CTF_TYPE_ISCHILD(lmp->ctlm_type);
727                               }
728                               break;
729                     case CTF_K_ENUM:
730                               vbytes = sizeof (ctf_enum_t) * vlen;
731                               break;
732                     case CTF_K_FORWARD:
733                     case CTF_K_UNKNOWN:
734                               vbytes = 0;
735                               break;
736                     case CTF_K_POINTER:
737                     case CTF_K_TYPEDEF:
738                     case CTF_K_VOLATILE:
739                     case CTF_K_CONST:
740                     case CTF_K_RESTRICT:
741                               vbytes = 0;
742                               break;
743                     default:
744                               printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
745                               return (EIO);
746                     }
747                     *xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata);
748                     tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
749           }
750 
751           return (0);
752 }
753 
754 /*
755  * CTF Declaration Stack
756  *
757  * In order to implement ctf_type_name(), we must convert a type graph back
758  * into a C type declaration.  Unfortunately, a type graph represents a storage
759  * class ordering of the type whereas a type declaration must obey the C rules
760  * for operator precedence, and the two orderings are frequently in conflict.
761  * For example, consider these CTF type graphs and their C declarations:
762  *
763  * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
764  * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
765  *
766  * In each case, parentheses are used to raise operator * to higher lexical
767  * precedence, so the string form of the C declaration cannot be constructed by
768  * walking the type graph links and forming the string from left to right.
769  *
770  * The functions in this file build a set of stacks from the type graph nodes
771  * corresponding to the C operator precedence levels in the appropriate order.
772  * The code in ctf_type_name() can then iterate over the levels and nodes in
773  * lexical precedence order and construct the final C declaration string.
774  */
775 typedef struct ctf_list {
776           struct ctf_list *l_prev; /* previous pointer or tail pointer */
777           struct ctf_list *l_next; /* next pointer or head pointer */
778 } ctf_list_t;
779 
780 #define   ctf_list_prev(elem) ((void *)(((ctf_list_t *)(elem))->l_prev))
781 #define   ctf_list_next(elem) ((void *)(((ctf_list_t *)(elem))->l_next))
782 
783 typedef enum {
784           CTF_PREC_BASE,
785           CTF_PREC_POINTER,
786           CTF_PREC_ARRAY,
787           CTF_PREC_FUNCTION,
788           CTF_PREC_MAX
789 } ctf_decl_prec_t;
790 
791 typedef struct ctf_decl_node {
792           ctf_list_t cd_list;                     /* linked list pointers */
793           ctf_id_t cd_type;                       /* type identifier */
794           uint_t cd_kind;                                   /* type kind */
795           uint_t cd_n;                                      /* type dimension if array */
796 } ctf_decl_node_t;
797 
798 typedef struct ctf_decl {
799           ctf_list_t cd_nodes[CTF_PREC_MAX];      /* declaration node stacks */
800           int cd_order[CTF_PREC_MAX];             /* storage order of decls */
801           ctf_decl_prec_t cd_qualp;               /* qualifier precision */
802           ctf_decl_prec_t cd_ordp;                /* ordered precision */
803           char *cd_buf;                                     /* buffer for output */
804           char *cd_ptr;                                     /* buffer location */
805           char *cd_end;                                     /* buffer limit */
806           size_t cd_len;                                    /* buffer space required */
807           int cd_err;                                       /* saved error value */
808 } ctf_decl_t;
809 
810 /*
811  * Simple doubly-linked list append routine.  This implementation assumes that
812  * each list element contains an embedded ctf_list_t as the first member.
813  * An additional ctf_list_t is used to store the head (l_next) and tail
814  * (l_prev) pointers.  The current head and tail list elements have their
815  * previous and next pointers set to NULL, respectively.
816  */
817 static void
ctf_list_append(ctf_list_t * lp,void * new)818 ctf_list_append(ctf_list_t *lp, void *new)
819 {
820           ctf_list_t *p = lp->l_prev;   /* p = tail list element */
821           ctf_list_t *q = new;                    /* q = new list element */
822 
823           lp->l_prev = q;
824           q->l_prev = p;
825           q->l_next = NULL;
826 
827           if (p != NULL)
828                     p->l_next = q;
829           else
830                     lp->l_next = q;
831 }
832 
833 /*
834  * Prepend the specified existing element to the given ctf_list_t.  The
835  * existing pointer should be pointing at a struct with embedded ctf_list_t.
836  */
837 static void
ctf_list_prepend(ctf_list_t * lp,void * new)838 ctf_list_prepend(ctf_list_t *lp, void *new)
839 {
840           ctf_list_t *p = new;                    /* p = new list element */
841           ctf_list_t *q = lp->l_next;   /* q = head list element */
842 
843           lp->l_next = p;
844           p->l_prev = NULL;
845           p->l_next = q;
846 
847           if (q != NULL)
848                     q->l_prev = p;
849           else
850                     lp->l_prev = p;
851 }
852 
853 static void
ctf_decl_init(ctf_decl_t * cd,char * buf,size_t len)854 ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len)
855 {
856           int i;
857 
858           bzero(cd, sizeof (ctf_decl_t));
859 
860           for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
861                     cd->cd_order[i] = CTF_PREC_BASE - 1;
862 
863           cd->cd_qualp = CTF_PREC_BASE;
864           cd->cd_ordp = CTF_PREC_BASE;
865 
866           cd->cd_buf = buf;
867           cd->cd_ptr = buf;
868           cd->cd_end = buf + len;
869 }
870 
871 static void
ctf_decl_fini(ctf_decl_t * cd)872 ctf_decl_fini(ctf_decl_t *cd)
873 {
874           ctf_decl_node_t *cdp, *ndp;
875           int i;
876 
877           for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) {
878                     for (cdp = ctf_list_next(&cd->cd_nodes[i]);
879                         cdp != NULL; cdp = ndp) {
880                               ndp = ctf_list_next(cdp);
881                               free(cdp, M_FBT);
882                     }
883           }
884 }
885 
886 static const ctf_type_t *
ctf_lookup_by_id(mod_ctf_t * mc,ctf_id_t type)887 ctf_lookup_by_id(mod_ctf_t *mc, ctf_id_t type)
888 {
889           const ctf_type_t *tp;
890           uint32_t offset;
891           uint32_t *typoff = mc->typoffp;
892 
893           if (type >= mc->typlen) {
894                     printf("%s(%d): type %d exceeds max %ld\n",__func__,__LINE__,(int) type,mc->typlen);
895                     return(NULL);
896           }
897 
898           /* Check if the type isn't cross-referenced. */
899           if ((offset = typoff[type]) == 0) {
900                     printf("%s(%d): type %d isn't cross referenced\n",__func__,__LINE__, (int) type);
901                     return(NULL);
902           }
903 
904           tp = (const ctf_type_t *)(mc->ctftab + offset + sizeof(ctf_header_t));
905 
906           return (tp);
907 }
908 
909 static void
fbt_array_info(mod_ctf_t * mc,ctf_id_t type,ctf_arinfo_t * arp)910 fbt_array_info(mod_ctf_t *mc, ctf_id_t type, ctf_arinfo_t *arp)
911 {
912           const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;
913           const ctf_type_t *tp;
914           const ctf_array_t *ap;
915           ssize_t increment;
916 
917           bzero(arp, sizeof(*arp));
918 
919           if ((tp = ctf_lookup_by_id(mc, type)) == NULL)
920                     return;
921 
922           if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY)
923                     return;
924 
925           (void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment);
926 
927           ap = (const ctf_array_t *)((uintptr_t)tp + increment);
928           arp->ctr_contents = ap->cta_contents;
929           arp->ctr_index = ap->cta_index;
930           arp->ctr_nelems = ap->cta_nelems;
931 }
932 
933 static const char *
ctf_strptr(mod_ctf_t * mc,int name)934 ctf_strptr(mod_ctf_t *mc, int name)
935 {
936           const ctf_header_t *hp = (const ctf_header_t *) mc->ctftab;;
937           const char *strp = "";
938 
939           if (name < 0 || name >= hp->cth_strlen)
940                     return(strp);
941 
942           strp = (const char *)(mc->ctftab + hp->cth_stroff + name + sizeof(ctf_header_t));
943 
944           return (strp);
945 }
946 
947 static void
ctf_decl_push(ctf_decl_t * cd,mod_ctf_t * mc,ctf_id_t type)948 ctf_decl_push(ctf_decl_t *cd, mod_ctf_t *mc, ctf_id_t type)
949 {
950           ctf_decl_node_t *cdp;
951           ctf_decl_prec_t prec;
952           uint_t kind, n = 1;
953           int is_qual = 0;
954 
955           const ctf_type_t *tp;
956           ctf_arinfo_t ar;
957 
958           if ((tp = ctf_lookup_by_id(mc, type)) == NULL) {
959                     cd->cd_err = ENOENT;
960                     return;
961           }
962 
963           switch (kind = CTF_INFO_KIND(tp->ctt_info)) {
964           case CTF_K_ARRAY:
965                     fbt_array_info(mc, type, &ar);
966                     ctf_decl_push(cd, mc, ar.ctr_contents);
967                     n = ar.ctr_nelems;
968                     prec = CTF_PREC_ARRAY;
969                     break;
970 
971           case CTF_K_TYPEDEF:
972                     if (ctf_strptr(mc, tp->ctt_name)[0] == '\0') {
973                               ctf_decl_push(cd, mc, tp->ctt_type);
974                               return;
975                     }
976                     prec = CTF_PREC_BASE;
977                     break;
978 
979           case CTF_K_FUNCTION:
980                     ctf_decl_push(cd, mc, tp->ctt_type);
981                     prec = CTF_PREC_FUNCTION;
982                     break;
983 
984           case CTF_K_POINTER:
985                     ctf_decl_push(cd, mc, tp->ctt_type);
986                     prec = CTF_PREC_POINTER;
987                     break;
988 
989           case CTF_K_VOLATILE:
990           case CTF_K_CONST:
991           case CTF_K_RESTRICT:
992                     ctf_decl_push(cd, mc, tp->ctt_type);
993                     prec = cd->cd_qualp;
994                     is_qual++;
995                     break;
996 
997           default:
998                     prec = CTF_PREC_BASE;
999           }
1000 
1001           cdp = malloc(sizeof(*cdp), M_FBT, M_WAITOK);
1002           cdp->cd_type = type;
1003           cdp->cd_kind = kind;
1004           cdp->cd_n = n;
1005 
1006           if (ctf_list_next(&cd->cd_nodes[prec]) == NULL)
1007                     cd->cd_order[prec] = cd->cd_ordp++;
1008 
1009           /*
1010            * Reset cd_qualp to the highest precedence level that we've seen so
1011            * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).
1012            */
1013           if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
1014                     cd->cd_qualp = prec;
1015 
1016           /*
1017            * C array declarators are ordered inside out so prepend them.  Also by
1018            * convention qualifiers of base types precede the type specifier (e.g.
1019            * const int vs. int const) even though the two forms are equivalent.
1020            */
1021           if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
1022                     ctf_list_prepend(&cd->cd_nodes[prec], cdp);
1023           else
1024                     ctf_list_append(&cd->cd_nodes[prec], cdp);
1025 }
1026 
1027 static void
ctf_decl_sprintf(ctf_decl_t * cd,const char * format,...)1028 ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...)
1029 {
1030           size_t len = (size_t)(cd->cd_end - cd->cd_ptr);
1031           va_list ap;
1032           size_t n;
1033 
1034           va_start(ap, format);
1035           n = vsnprintf(cd->cd_ptr, len, format, ap);
1036           va_end(ap);
1037 
1038           cd->cd_ptr += MIN(n, len);
1039           cd->cd_len += n;
1040 }
1041 
1042 static ssize_t
fbt_type_name(mod_ctf_t * mc,ctf_id_t type,char * buf,size_t len)1043 fbt_type_name(mod_ctf_t *mc, ctf_id_t type, char *buf, size_t len)
1044 {
1045           ctf_decl_t cd;
1046           ctf_decl_node_t *cdp;
1047           ctf_decl_prec_t prec, lp, rp;
1048           int ptr, arr;
1049           uint_t k;
1050 
1051           if (mc == NULL && type == CTF_ERR)
1052                     return (-1); /* simplify caller code by permitting CTF_ERR */
1053 
1054           ctf_decl_init(&cd, buf, len);
1055           ctf_decl_push(&cd, mc, type);
1056 
1057           if (cd.cd_err != 0) {
1058                     ctf_decl_fini(&cd);
1059                     return (-1);
1060           }
1061 
1062           /*
1063            * If the type graph's order conflicts with lexical precedence order
1064            * for pointers or arrays, then we need to surround the declarations at
1065            * the corresponding lexical precedence with parentheses.  This can
1066            * result in either a parenthesized pointer (*) as in int (*)() or
1067            * int (*)[], or in a parenthesized pointer and array as in int (*[])().
1068            */
1069           ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
1070           arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
1071 
1072           rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
1073           lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
1074 
1075           k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
1076 
1077           for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
1078                     for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
1079                         cdp != NULL; cdp = ctf_list_next(cdp)) {
1080 
1081                               const ctf_type_t *tp =
1082                                   ctf_lookup_by_id(mc, cdp->cd_type);
1083                               const char *name = ctf_strptr(mc, tp->ctt_name);
1084 
1085                               if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
1086                                         ctf_decl_sprintf(&cd, " ");
1087 
1088                               if (lp == prec) {
1089                                         ctf_decl_sprintf(&cd, "(");
1090                                         lp = -1;
1091                               }
1092 
1093                               switch (cdp->cd_kind) {
1094                               case CTF_K_INTEGER:
1095                               case CTF_K_FLOAT:
1096                               case CTF_K_TYPEDEF:
1097                                         ctf_decl_sprintf(&cd, "%s", name);
1098                                         break;
1099                               case CTF_K_POINTER:
1100                                         ctf_decl_sprintf(&cd, "*");
1101                                         break;
1102                               case CTF_K_ARRAY:
1103                                         ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
1104                                         break;
1105                               case CTF_K_FUNCTION:
1106                                         ctf_decl_sprintf(&cd, "()");
1107                                         break;
1108                               case CTF_K_STRUCT:
1109                               case CTF_K_FORWARD:
1110                                         ctf_decl_sprintf(&cd, "struct %s", name);
1111                                         break;
1112                               case CTF_K_UNION:
1113                                         ctf_decl_sprintf(&cd, "union %s", name);
1114                                         break;
1115                               case CTF_K_ENUM:
1116                                         ctf_decl_sprintf(&cd, "enum %s", name);
1117                                         break;
1118                               case CTF_K_VOLATILE:
1119                                         ctf_decl_sprintf(&cd, "volatile");
1120                                         break;
1121                               case CTF_K_CONST:
1122                                         ctf_decl_sprintf(&cd, "const");
1123                                         break;
1124                               case CTF_K_RESTRICT:
1125                                         ctf_decl_sprintf(&cd, "restrict");
1126                                         break;
1127                               }
1128 
1129                               k = cdp->cd_kind;
1130                     }
1131 
1132                     if (rp == prec)
1133                               ctf_decl_sprintf(&cd, ")");
1134           }
1135 
1136           ctf_decl_fini(&cd);
1137           return (cd.cd_len);
1138 }
1139 
1140 static void
fbt_getargdesc(void * arg __unused,dtrace_id_t id __unused,void * parg,dtrace_argdesc_t * desc)1141 fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc)
1142 {
1143           const ushort_t *dp;
1144           fbt_probe_t *fbt = parg;
1145           mod_ctf_t *mc;
1146           modctl_t *ctl = fbt->fbtp_ctl;
1147           int ndx = desc->dtargd_ndx;
1148           int symindx = fbt->fbtp_symindx;
1149           uint32_t *ctfoff;
1150           uint32_t offset;
1151           ushort_t info, kind, n;
1152           int nsyms;
1153 
1154           if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) {
1155                     (void) strcpy(desc->dtargd_native, "int");
1156                     return;
1157           }
1158 
1159           desc->dtargd_ndx = DTRACE_ARGNONE;
1160 
1161           /* Get a pointer to the CTF data and its length. */
1162           if (mod_ctf_get(ctl, &mc) != 0) {
1163                     static int report = 0;
1164                     if (report < 1) {
1165                               report++;
1166                               printf("FBT: Error no CTF section found in module \"%s\"\n",
1167                                   module_name(ctl));
1168                     }
1169                     /* No CTF data? Something wrong? *shrug* */
1170                     return;
1171           }
1172 
1173           nsyms = (mc->nmap != NULL) ? mc->nmapsize : mc->nsym;
1174 
1175           /* Check if this module hasn't been initialised yet. */
1176           if (mc->ctfoffp == NULL) {
1177                     /*
1178                      * Initialise the CTF object and function symindx to
1179                      * byte offset array.
1180                      */
1181                     if (fbt_ctfoff_init(ctl, mc) != 0)
1182                               return;
1183 
1184                     /* Initialise the CTF type to byte offset array. */
1185                     if (fbt_typoff_init(mc) != 0)
1186                               return;
1187           }
1188 
1189           ctfoff = mc->ctfoffp;
1190 
1191           if (ctfoff == NULL || mc->typoffp == NULL) {
1192                     return;
1193           }
1194 
1195           /* Check if the symbol index is out of range. */
1196           if (symindx >= nsyms)
1197                     return;
1198 
1199           /* Check if the symbol isn't cross-referenced. */
1200           if ((offset = ctfoff[symindx]) == 0xffffffff)
1201                     return;
1202 
1203           dp = (const ushort_t *)(mc->ctftab + offset + sizeof(ctf_header_t));
1204 
1205           info = *dp++;
1206           kind = CTF_INFO_KIND(info);
1207           n = CTF_INFO_VLEN(info);
1208 
1209           if (kind == CTF_K_UNKNOWN && n == 0) {
1210                     printf("%s(%d): Unknown function %s!\n",__func__,__LINE__,
1211                         fbt->fbtp_name);
1212                     return;
1213           }
1214 
1215           if (kind != CTF_K_FUNCTION) {
1216                     printf("%s(%d): Expected a function %s!\n",__func__,__LINE__,
1217                         fbt->fbtp_name);
1218                     return;
1219           }
1220 
1221           if (fbt->fbtp_roffset != 0) {
1222                     /* Only return type is available for args[1] in return probe. */
1223                     if (ndx > 1)
1224                               return;
1225                     ASSERT(ndx == 1);
1226           } else {
1227                     /* Check if the requested argument doesn't exist. */
1228                     if (ndx >= n)
1229                               return;
1230 
1231                     /* Skip the return type and arguments up to the one requested. */
1232                     dp += ndx + 1;
1233           }
1234 
1235           if (fbt_type_name(mc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0)
1236                     desc->dtargd_ndx = ndx;
1237 
1238           return;
1239 }
1240 
1241 #ifdef __FreeBSD__
1242 static int
fbt_linker_file_cb(linker_file_t lf,void * arg)1243 fbt_linker_file_cb(linker_file_t lf, void *arg)
1244 {
1245 
1246           fbt_provide_module(arg, lf);
1247 
1248           return (0);
1249 }
1250 #endif
1251 
1252 static void
fbt_load(void)1253 fbt_load(void)
1254 {
1255 
1256 #ifdef __FreeBSD__
1257           /* Create the /dev/dtrace/fbt entry. */
1258           fbt_cdev = make_dev(&fbt_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
1259               "dtrace/fbt");
1260 #endif
1261 #ifdef __NetBSD__
1262           (void) module_specific_key_create(&fbt_module_key, fbt_module_dtor);
1263 #endif
1264 
1265           /* Default the probe table size if not specified. */
1266           if (fbt_probetab_size == 0)
1267                     fbt_probetab_size = FBT_PROBETAB_SIZE;
1268 
1269           /* Choose the hash mask for the probe table. */
1270           fbt_probetab_mask = fbt_probetab_size - 1;
1271 
1272           /* Allocate memory for the probe table. */
1273           fbt_probetab =
1274               malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO);
1275 
1276           dtrace_doubletrap_func = fbt_doubletrap;
1277           dtrace_invop_add(fbt_invop);
1278 
1279           if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER,
1280               NULL, &fbt_pops, NULL, &fbt_id) != 0)
1281                     return;
1282 }
1283 
1284 
1285 static int
fbt_unload(void)1286 fbt_unload(void)
1287 {
1288           int error = 0;
1289 
1290           /* De-register the invalid opcode handler. */
1291           dtrace_invop_remove(fbt_invop);
1292 
1293           dtrace_doubletrap_func = NULL;
1294 
1295           /* De-register this DTrace provider. */
1296           if ((error = dtrace_unregister(fbt_id)) != 0)
1297                     return (error);
1298 
1299           /* Free the probe table. */
1300           free(fbt_probetab, M_FBT);
1301           fbt_probetab = NULL;
1302           fbt_probetab_mask = 0;
1303 
1304 #ifdef __FreeBSD__
1305           destroy_dev(fbt_cdev);
1306 #endif
1307 #ifdef __NetBSD__
1308           (void) module_specific_key_delete(fbt_module_key);
1309 #endif
1310           return (error);
1311 }
1312 
1313 
1314 static int
dtrace_fbt_modcmd(modcmd_t cmd,void * data)1315 dtrace_fbt_modcmd(modcmd_t cmd, void *data)
1316 {
1317           int bmajor = -1, cmajor = 352;
1318           int error;
1319 
1320           switch (cmd) {
1321           case MODULE_CMD_INIT:
1322                     fbt_load();
1323                     return devsw_attach("fbt", NULL, &bmajor,
1324                         &fbt_cdevsw, &cmajor);
1325           case MODULE_CMD_FINI:
1326                     error = fbt_unload();
1327                     if (error != 0)
1328                               return error;
1329                     devsw_detach(NULL, &fbt_cdevsw);
1330                     return 0;
1331           case MODULE_CMD_AUTOUNLOAD:
1332                     return EBUSY;
1333           default:
1334                     return ENOTTY;
1335           }
1336 }
1337 
1338 static int
fbt_open(dev_t dev,int flags,int mode,struct lwp * l)1339 fbt_open(dev_t dev, int flags, int mode, struct lwp *l)
1340 {
1341           return (0);
1342 }
1343 
1344 #ifdef __FreeBSD__
1345 SYSINIT(fbt_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_load, NULL);
1346 SYSUNINIT(fbt_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_unload, NULL);
1347 
1348 DEV_MODULE(fbt, fbt_modevent, NULL);
1349 MODULE_VERSION(fbt, 1);
1350 MODULE_DEPEND(fbt, dtrace, 1, 1, 1);
1351 MODULE_DEPEND(fbt, opensolaris, 1, 1, 1);
1352 #endif
1353 #ifdef __NetBSD__
1354 MODULE(MODULE_CLASS_MISC, dtrace_fbt, "dtrace,zlib");
1355 #endif
1356