The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/cddl/dev/fbt/fbt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: f11b91b4efa195873bb073685f46d7d8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.