Home | History | Annotate | Line # | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     24  * Copyright (c) 2011 by Delphix. All rights reserved.
     25  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
     26  */
     27 
     28 #include <sys/types.h>
     29 #ifdef illumos
     30 #include <sys/sysmacros.h>
     31 #endif
     32 
     33 #include <strings.h>
     34 #ifdef illumos
     35 #include <alloca.h>
     36 #endif
     37 #include <assert.h>
     38 #include <stdlib.h>
     39 #include <errno.h>
     40 #include <limits.h>
     41 
     42 #include <dt_impl.h>
     43 #include <dt_strtab.h>
     44 #include <dt_program.h>
     45 #include <dt_provider.h>
     46 #include <dt_xlator.h>
     47 #include <dt_dof.h>
     48 
     49 void
     50 dt_dof_init(dtrace_hdl_t *dtp)
     51 {
     52 	dt_dof_t *ddo = &dtp->dt_dof;
     53 
     54 	ddo->ddo_hdl = dtp;
     55 	ddo->ddo_nsecs = 0;
     56 	ddo->ddo_strsec = DOF_SECIDX_NONE;
     57 	ddo->ddo_xlimport = NULL;
     58 	ddo->ddo_xlexport = NULL;
     59 
     60 	dt_buf_create(dtp, &ddo->ddo_secs, "section headers", 0);
     61 	dt_buf_create(dtp, &ddo->ddo_strs, "string table", 0);
     62 	dt_buf_create(dtp, &ddo->ddo_ldata, "loadable data", 0);
     63 	dt_buf_create(dtp, &ddo->ddo_udata, "unloadable data", 0);
     64 
     65 	dt_buf_create(dtp, &ddo->ddo_probes, "probe data", 0);
     66 	dt_buf_create(dtp, &ddo->ddo_args, "probe args", 0);
     67 	dt_buf_create(dtp, &ddo->ddo_offs, "probe offs", 0);
     68 	dt_buf_create(dtp, &ddo->ddo_enoffs, "probe is-enabled offs", 0);
     69 	dt_buf_create(dtp, &ddo->ddo_rels, "probe rels", 0);
     70 
     71 	dt_buf_create(dtp, &ddo->ddo_xlms, "xlate members", 0);
     72 }
     73 
     74 void
     75 dt_dof_fini(dtrace_hdl_t *dtp)
     76 {
     77 	dt_dof_t *ddo = &dtp->dt_dof;
     78 
     79 	dt_free(dtp, ddo->ddo_xlimport);
     80 	dt_free(dtp, ddo->ddo_xlexport);
     81 
     82 	dt_buf_destroy(dtp, &ddo->ddo_secs);
     83 	dt_buf_destroy(dtp, &ddo->ddo_strs);
     84 	dt_buf_destroy(dtp, &ddo->ddo_ldata);
     85 	dt_buf_destroy(dtp, &ddo->ddo_udata);
     86 
     87 	dt_buf_destroy(dtp, &ddo->ddo_probes);
     88 	dt_buf_destroy(dtp, &ddo->ddo_args);
     89 	dt_buf_destroy(dtp, &ddo->ddo_offs);
     90 	dt_buf_destroy(dtp, &ddo->ddo_enoffs);
     91 	dt_buf_destroy(dtp, &ddo->ddo_rels);
     92 
     93 	dt_buf_destroy(dtp, &ddo->ddo_xlms);
     94 }
     95 
     96 static int
     97 dt_dof_reset(dtrace_hdl_t *dtp, dtrace_prog_t *pgp)
     98 {
     99 	dt_dof_t *ddo = &dtp->dt_dof;
    100 	uint_t i, nx = dtp->dt_xlatorid;
    101 
    102 	assert(ddo->ddo_hdl == dtp);
    103 	ddo->ddo_pgp = pgp;
    104 
    105 	ddo->ddo_nsecs = 0;
    106 	ddo->ddo_strsec = DOF_SECIDX_NONE;
    107 
    108 	dt_free(dtp, ddo->ddo_xlimport);
    109 	dt_free(dtp, ddo->ddo_xlexport);
    110 
    111 	ddo->ddo_xlimport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx);
    112 	ddo->ddo_xlexport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx);
    113 
    114 	if (nx != 0 && (ddo->ddo_xlimport == NULL || ddo->ddo_xlexport == NULL))
    115 		return (-1); /* errno is set for us */
    116 
    117 	for (i = 0; i < nx; i++) {
    118 		ddo->ddo_xlimport[i] = DOF_SECIDX_NONE;
    119 		ddo->ddo_xlexport[i] = DOF_SECIDX_NONE;
    120 	}
    121 
    122 	dt_buf_reset(dtp, &ddo->ddo_secs);
    123 	dt_buf_reset(dtp, &ddo->ddo_strs);
    124 	dt_buf_reset(dtp, &ddo->ddo_ldata);
    125 	dt_buf_reset(dtp, &ddo->ddo_udata);
    126 
    127 	dt_buf_reset(dtp, &ddo->ddo_probes);
    128 	dt_buf_reset(dtp, &ddo->ddo_args);
    129 	dt_buf_reset(dtp, &ddo->ddo_offs);
    130 	dt_buf_reset(dtp, &ddo->ddo_enoffs);
    131 	dt_buf_reset(dtp, &ddo->ddo_rels);
    132 
    133 	dt_buf_reset(dtp, &ddo->ddo_xlms);
    134 	return (0);
    135 }
    136 
    137 /*
    138  * Add a loadable DOF section to the file using the specified data buffer and
    139  * the specified DOF section attributes.  DOF_SECF_LOAD must be set in flags.
    140  * If 'data' is NULL, the caller is responsible for manipulating the ldata buf.
    141  */
    142 static dof_secidx_t
    143 dof_add_lsect(dt_dof_t *ddo, const void *data, uint32_t type,
    144     uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size)
    145 {
    146 	dtrace_hdl_t *dtp = ddo->ddo_hdl;
    147 	dof_sec_t s;
    148 
    149 	s.dofs_type = type;
    150 	s.dofs_align = align;
    151 	s.dofs_flags = flags | DOF_SECF_LOAD;
    152 	s.dofs_entsize = entsize;
    153 	s.dofs_offset = dt_buf_offset(&ddo->ddo_ldata, align);
    154 	s.dofs_size = size;
    155 
    156 	dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t));
    157 
    158 	if (data != NULL)
    159 		dt_buf_write(dtp, &ddo->ddo_ldata, data, size, align);
    160 
    161 	return (ddo->ddo_nsecs++);
    162 }
    163 
    164 /*
    165  * Add an unloadable DOF section to the file using the specified data buffer
    166  * and DOF section attributes.  DOF_SECF_LOAD must *not* be set in flags.
    167  * If 'data' is NULL, the caller is responsible for manipulating the udata buf.
    168  */
    169 static dof_secidx_t
    170 dof_add_usect(dt_dof_t *ddo, const void *data, uint32_t type,
    171     uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size)
    172 {
    173 	dtrace_hdl_t *dtp = ddo->ddo_hdl;
    174 	dof_sec_t s;
    175 
    176 	s.dofs_type = type;
    177 	s.dofs_align = align;
    178 	s.dofs_flags = flags & ~DOF_SECF_LOAD;
    179 	s.dofs_entsize = entsize;
    180 	s.dofs_offset = dt_buf_offset(&ddo->ddo_udata, align);
    181 	s.dofs_size = size;
    182 
    183 	dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t));
    184 
    185 	if (data != NULL)
    186 		dt_buf_write(dtp, &ddo->ddo_udata, data, size, align);
    187 
    188 	return (ddo->ddo_nsecs++);
    189 }
    190 
    191 /*
    192  * Add a string to the global string table associated with the DOF.  The offset
    193  * of the string is returned as an index into the string table.
    194  */
    195 static dof_stridx_t
    196 dof_add_string(dt_dof_t *ddo, const char *s)
    197 {
    198 	dt_buf_t *bp = &ddo->ddo_strs;
    199 	dof_stridx_t i = dt_buf_len(bp);
    200 
    201 	if (i != 0 && (s == NULL || *s == '\0'))
    202 		return (0); /* string table has \0 at offset 0 */
    203 
    204 	dt_buf_write(ddo->ddo_hdl, bp, s, strlen(s) + 1, sizeof (char));
    205 	return (i);
    206 }
    207 
    208 static dof_attr_t
    209 dof_attr(const dtrace_attribute_t *ap)
    210 {
    211 	return (DOF_ATTR(ap->dtat_name, ap->dtat_data, ap->dtat_class));
    212 }
    213 
    214 static dof_secidx_t
    215 dof_add_difo(dt_dof_t *ddo, const dtrace_difo_t *dp)
    216 {
    217 	dof_secidx_t dsecs[5]; /* enough for all possible DIFO sections */
    218 	uint_t nsecs = 0;
    219 
    220 	dof_difohdr_t *dofd;
    221 	dof_relohdr_t dofr;
    222 	dof_secidx_t relsec;
    223 
    224 	dof_secidx_t strsec = DOF_SECIDX_NONE;
    225 	dof_secidx_t intsec = DOF_SECIDX_NONE;
    226 	dof_secidx_t hdrsec = DOF_SECIDX_NONE;
    227 
    228 	if (dp->dtdo_buf != NULL) {
    229 		dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_buf,
    230 		    DOF_SECT_DIF, sizeof (dif_instr_t), 0,
    231 		    sizeof (dif_instr_t), sizeof (dif_instr_t) * dp->dtdo_len);
    232 	}
    233 
    234 	if (dp->dtdo_inttab != NULL) {
    235 		dsecs[nsecs++] = intsec = dof_add_lsect(ddo, dp->dtdo_inttab,
    236 		    DOF_SECT_INTTAB, sizeof (uint64_t), 0,
    237 		    sizeof (uint64_t), sizeof (uint64_t) * dp->dtdo_intlen);
    238 	}
    239 
    240 	if (dp->dtdo_strtab != NULL) {
    241 		dsecs[nsecs++] = strsec = dof_add_lsect(ddo, dp->dtdo_strtab,
    242 		    DOF_SECT_STRTAB, sizeof (char), 0, 0, dp->dtdo_strlen);
    243 	}
    244 
    245 	if (dp->dtdo_vartab != NULL) {
    246 		dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_vartab,
    247 		    DOF_SECT_VARTAB, sizeof (uint_t), 0, sizeof (dtrace_difv_t),
    248 		    sizeof (dtrace_difv_t) * dp->dtdo_varlen);
    249 	}
    250 
    251 	if (dp->dtdo_xlmtab != NULL) {
    252 		dof_xlref_t *xlt, *xlp;
    253 		dt_node_t **pnp;
    254 
    255 		xlt = alloca(sizeof (dof_xlref_t) * dp->dtdo_xlmlen);
    256 		pnp = dp->dtdo_xlmtab;
    257 
    258 		/*
    259 		 * dtdo_xlmtab contains pointers to the translator members.
    260 		 * The translator itself is in sect ddo_xlimport[dxp->dx_id].
    261 		 * The XLMEMBERS entries are in order by their dn_membid, so
    262 		 * the member section offset is the population count of bits
    263 		 * in ddo_pgp->dp_xlrefs[] up to and not including dn_membid.
    264 		 */
    265 		for (xlp = xlt; xlp < xlt + dp->dtdo_xlmlen; xlp++) {
    266 			dt_node_t *dnp = *pnp++;
    267 			dt_xlator_t *dxp = dnp->dn_membexpr->dn_xlator;
    268 
    269 			xlp->dofxr_xlator = ddo->ddo_xlimport[dxp->dx_id];
    270 			xlp->dofxr_member = dt_popcb(
    271 			    ddo->ddo_pgp->dp_xrefs[dxp->dx_id], dnp->dn_membid);
    272 			xlp->dofxr_argn = (uint32_t)dxp->dx_arg;
    273 		}
    274 
    275 		dsecs[nsecs++] = dof_add_lsect(ddo, xlt, DOF_SECT_XLTAB,
    276 		    sizeof (dof_secidx_t), 0, sizeof (dof_xlref_t),
    277 		    sizeof (dof_xlref_t) * dp->dtdo_xlmlen);
    278 	}
    279 
    280 	/*
    281 	 * Copy the return type and the array of section indices that form the
    282 	 * DIFO into a single dof_difohdr_t and then add DOF_SECT_DIFOHDR.
    283 	 */
    284 	assert(nsecs <= sizeof (dsecs) / sizeof (dsecs[0]));
    285 	dofd = alloca(sizeof (dtrace_diftype_t) + sizeof (dsecs));
    286 	bcopy(&dp->dtdo_rtype, &dofd->dofd_rtype, sizeof (dtrace_diftype_t));
    287 	bcopy(dsecs, &dofd->dofd_links, sizeof (dof_secidx_t) * nsecs);
    288 
    289 	hdrsec = dof_add_lsect(ddo, dofd, DOF_SECT_DIFOHDR,
    290 	    sizeof (dof_secidx_t), 0, 0,
    291 	    sizeof (dtrace_diftype_t) + sizeof (dof_secidx_t) * nsecs);
    292 
    293 	/*
    294 	 * Add any other sections related to dtrace_difo_t.  These are not
    295 	 * referenced in dof_difohdr_t because they are not used by emulation.
    296 	 */
    297 	if (dp->dtdo_kreltab != NULL) {
    298 		relsec = dof_add_lsect(ddo, dp->dtdo_kreltab, DOF_SECT_RELTAB,
    299 		    sizeof (uint64_t), 0, sizeof (dof_relodesc_t),
    300 		    sizeof (dof_relodesc_t) * dp->dtdo_krelen);
    301 
    302 		/*
    303 		 * This code assumes the target of all relocations is the
    304 		 * integer table 'intsec' (DOF_SECT_INTTAB).  If other sections
    305 		 * need relocation in the future this will need to change.
    306 		 */
    307 		dofr.dofr_strtab = strsec;
    308 		dofr.dofr_relsec = relsec;
    309 		dofr.dofr_tgtsec = intsec;
    310 
    311 		(void) dof_add_lsect(ddo, &dofr, DOF_SECT_KRELHDR,
    312 		    sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t));
    313 	}
    314 
    315 	if (dp->dtdo_ureltab != NULL) {
    316 		relsec = dof_add_lsect(ddo, dp->dtdo_ureltab, DOF_SECT_RELTAB,
    317 		    sizeof (uint64_t), 0, sizeof (dof_relodesc_t),
    318 		    sizeof (dof_relodesc_t) * dp->dtdo_urelen);
    319 
    320 		/*
    321 		 * This code assumes the target of all relocations is the
    322 		 * integer table 'intsec' (DOF_SECT_INTTAB).  If other sections
    323 		 * need relocation in the future this will need to change.
    324 		 */
    325 		dofr.dofr_strtab = strsec;
    326 		dofr.dofr_relsec = relsec;
    327 		dofr.dofr_tgtsec = intsec;
    328 
    329 		(void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR,
    330 		    sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t));
    331 	}
    332 
    333 	return (hdrsec);
    334 }
    335 
    336 static void
    337 dof_add_translator(dt_dof_t *ddo, const dt_xlator_t *dxp, uint_t type)
    338 {
    339 	dtrace_hdl_t *dtp = ddo->ddo_hdl;
    340 	dof_xlmember_t dofxm;
    341 	dof_xlator_t dofxl;
    342 	dof_secidx_t *xst;
    343 
    344 	char buf[DT_TYPE_NAMELEN];
    345 	dt_node_t *dnp;
    346 	uint_t i = 0;
    347 
    348 	assert(type == DOF_SECT_XLIMPORT || type == DOF_SECT_XLEXPORT);
    349 	xst = type == DOF_SECT_XLIMPORT ? ddo->ddo_xlimport : ddo->ddo_xlexport;
    350 
    351 	if (xst[dxp->dx_id] != DOF_SECIDX_NONE)
    352 		return; /* translator has already been emitted */
    353 
    354 	dt_buf_reset(dtp, &ddo->ddo_xlms);
    355 
    356 	/*
    357 	 * Generate an array of dof_xlmember_t's into ddo_xlms.  If we are
    358 	 * importing the translator, add only those members referenced by the
    359 	 * program and set the dofxm_difo reference of each member to NONE.  If
    360 	 * we're exporting the translator, add all members and a DIFO for each.
    361 	 */
    362 	for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list, i++) {
    363 		if (type == DOF_SECT_XLIMPORT) {
    364 			if (!BT_TEST(ddo->ddo_pgp->dp_xrefs[dxp->dx_id], i))
    365 				continue; /* member is not referenced */
    366 			dofxm.dofxm_difo = DOF_SECIDX_NONE;
    367 		} else {
    368 			dofxm.dofxm_difo = dof_add_difo(ddo,
    369 			    dxp->dx_membdif[dnp->dn_membid]);
    370 		}
    371 
    372 		dofxm.dofxm_name = dof_add_string(ddo, dnp->dn_membname);
    373 		dt_node_diftype(dtp, dnp, &dofxm.dofxm_type);
    374 
    375 		dt_buf_write(dtp, &ddo->ddo_xlms,
    376 		    &dofxm, sizeof (dofxm), sizeof (uint32_t));
    377 	}
    378 
    379 	dofxl.dofxl_members = dof_add_lsect(ddo, NULL, DOF_SECT_XLMEMBERS,
    380 	    sizeof (uint32_t), 0, sizeof (dofxm), dt_buf_len(&ddo->ddo_xlms));
    381 
    382 	dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_xlms, sizeof (uint32_t));
    383 
    384 	dofxl.dofxl_strtab = ddo->ddo_strsec;
    385 	dofxl.dofxl_argv = dof_add_string(ddo, ctf_type_name(
    386 	    dxp->dx_src_ctfp, dxp->dx_src_type, buf, sizeof (buf)));
    387 	dofxl.dofxl_argc = 1;
    388 	dofxl.dofxl_type = dof_add_string(ddo, ctf_type_name(
    389 	    dxp->dx_dst_ctfp, dxp->dx_dst_type, buf, sizeof (buf)));
    390 	dofxl.dofxl_attr = dof_attr(&dxp->dx_souid.di_attr);
    391 
    392 	xst[dxp->dx_id] = dof_add_lsect(ddo, &dofxl, type,
    393 	    sizeof (uint32_t), 0, 0, sizeof (dofxl));
    394 }
    395 
    396 /*ARGSUSED*/
    397 static int
    398 dof_add_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
    399 {
    400 	dt_dof_t *ddo = data;
    401 	dtrace_hdl_t *dtp = ddo->ddo_hdl;
    402 	dt_probe_t *prp = idp->di_data;
    403 
    404 	dof_probe_t dofpr;
    405 	dof_relodesc_t dofr;
    406 	dt_probe_instance_t *pip;
    407 	dt_node_t *dnp;
    408 
    409 	char buf[DT_TYPE_NAMELEN];
    410 	uint_t i;
    411 
    412 	dofpr.dofpr_addr = 0;
    413 	dofpr.dofpr_name = dof_add_string(ddo, prp->pr_name);
    414 	dofpr.dofpr_nargv = dt_buf_len(&ddo->ddo_strs);
    415 
    416 	for (dnp = prp->pr_nargs; dnp != NULL; dnp = dnp->dn_list) {
    417 		(void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp,
    418 		    dnp->dn_type, buf, sizeof (buf)));
    419 	}
    420 
    421 	dofpr.dofpr_xargv = dt_buf_len(&ddo->ddo_strs);
    422 
    423 	for (dnp = prp->pr_xargs; dnp != NULL; dnp = dnp->dn_list) {
    424 		(void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp,
    425 		    dnp->dn_type, buf, sizeof (buf)));
    426 	}
    427 
    428 	dofpr.dofpr_argidx = dt_buf_len(&ddo->ddo_args) / sizeof (uint8_t);
    429 
    430 	for (i = 0; i < prp->pr_xargc; i++) {
    431 		dt_buf_write(dtp, &ddo->ddo_args, &prp->pr_mapping[i],
    432 		    sizeof (uint8_t), sizeof (uint8_t));
    433 	}
    434 
    435 	dofpr.dofpr_nargc = prp->pr_nargc;
    436 	dofpr.dofpr_xargc = prp->pr_xargc;
    437 	dofpr.dofpr_pad1 = 0;
    438 	dofpr.dofpr_pad2 = 0;
    439 
    440 	for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) {
    441 		dt_dprintf("adding probe for %s:%s\n", pip->pi_fname,
    442 		    prp->pr_name);
    443 
    444 		dofpr.dofpr_func = dof_add_string(ddo, pip->pi_fname);
    445 
    446 		/*
    447 		 * There should be one probe offset or is-enabled probe offset
    448 		 * or else this probe instance won't have been created. The
    449 		 * kernel will reject DOF which has a probe with no offsets.
    450 		 */
    451 		assert(pip->pi_noffs + pip->pi_nenoffs > 0);
    452 
    453 		dofpr.dofpr_offidx =
    454 		    dt_buf_len(&ddo->ddo_offs) / sizeof (uint32_t);
    455 		dofpr.dofpr_noffs = pip->pi_noffs;
    456 		dt_buf_write(dtp, &ddo->ddo_offs, pip->pi_offs,
    457 		    pip->pi_noffs * sizeof (uint32_t), sizeof (uint32_t));
    458 
    459 		dofpr.dofpr_enoffidx =
    460 		    dt_buf_len(&ddo->ddo_enoffs) / sizeof (uint32_t);
    461 		dofpr.dofpr_nenoffs = pip->pi_nenoffs;
    462 		dt_buf_write(dtp, &ddo->ddo_enoffs, pip->pi_enoffs,
    463 		    pip->pi_nenoffs * sizeof (uint32_t), sizeof (uint32_t));
    464 
    465 		dofr.dofr_name = dof_add_string(ddo, pip->pi_rname);
    466 		dofr.dofr_type = DOF_RELO_DOFREL;
    467 		dofr.dofr_offset = dt_buf_len(&ddo->ddo_probes);
    468 		dofr.dofr_data = 0;
    469 
    470 		dt_buf_write(dtp, &ddo->ddo_rels, &dofr,
    471 		    sizeof (dofr), sizeof (uint64_t));
    472 
    473 		dt_buf_write(dtp, &ddo->ddo_probes, &dofpr,
    474 		    sizeof (dofpr), sizeof (uint64_t));
    475 	}
    476 
    477 	return (0);
    478 }
    479 
    480 static int
    481 dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp)
    482 {
    483 	dtrace_hdl_t *dtp = ddo->ddo_hdl;
    484 	dof_provider_t dofpv;
    485 	dof_relohdr_t dofr;
    486 	dof_secidx_t *dofs;
    487 	ulong_t xr, nxr;
    488 	size_t sz;
    489 	id_t i;
    490 
    491 	if (pvp->pv_flags & DT_PROVIDER_IMPL) {
    492 		/*
    493 		 * ignore providers that are exported by dtrace(7D)
    494 		 */
    495 		return (0);
    496 	}
    497 
    498 	nxr = dt_popcb(pvp->pv_xrefs, pvp->pv_xrmax);
    499 	dofs = alloca(sizeof (dof_secidx_t) * (nxr + 1));
    500 	xr = 1; /* reserve dofs[0] for the provider itself */
    501 
    502 	/*
    503 	 * For each translator referenced by the provider (pv_xrefs), emit an
    504 	 * exported translator section for it if one hasn't been created yet.
    505 	 */
    506 	for (i = 0; i < pvp->pv_xrmax; i++) {
    507 		if (BT_TEST(pvp->pv_xrefs, i) &&
    508 		    dtp->dt_xlatemode == DT_XL_DYNAMIC) {
    509 			dof_add_translator(ddo,
    510 			    dt_xlator_lookup_id(dtp, i), DOF_SECT_XLEXPORT);
    511 			dofs[xr++] = ddo->ddo_xlexport[i];
    512 		}
    513 	}
    514 
    515 	dt_buf_reset(dtp, &ddo->ddo_probes);
    516 	dt_buf_reset(dtp, &ddo->ddo_args);
    517 	dt_buf_reset(dtp, &ddo->ddo_offs);
    518 	dt_buf_reset(dtp, &ddo->ddo_enoffs);
    519 	dt_buf_reset(dtp, &ddo->ddo_rels);
    520 
    521 	(void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo);
    522 
    523 	if (dt_buf_len(&ddo->ddo_probes) == 0)
    524 		return (dt_set_errno(dtp, EDT_NOPROBES));
    525 
    526 	dofpv.dofpv_probes = dof_add_lsect(ddo, NULL, DOF_SECT_PROBES,
    527 	    sizeof (uint64_t), 0, sizeof (dof_probe_t),
    528 	    dt_buf_len(&ddo->ddo_probes));
    529 
    530 	dt_buf_concat(dtp, &ddo->ddo_ldata,
    531 	    &ddo->ddo_probes, sizeof (uint64_t));
    532 
    533 	dofpv.dofpv_prargs = dof_add_lsect(ddo, NULL, DOF_SECT_PRARGS,
    534 	    sizeof (uint8_t), 0, sizeof (uint8_t), dt_buf_len(&ddo->ddo_args));
    535 
    536 	dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_args, sizeof (uint8_t));
    537 
    538 	dofpv.dofpv_proffs = dof_add_lsect(ddo, NULL, DOF_SECT_PROFFS,
    539 	    sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_offs));
    540 
    541 	dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_offs, sizeof (uint_t));
    542 
    543 	if ((sz = dt_buf_len(&ddo->ddo_enoffs)) != 0) {
    544 		dofpv.dofpv_prenoffs = dof_add_lsect(ddo, NULL,
    545 		    DOF_SECT_PRENOFFS, sizeof (uint_t), 0, sizeof (uint_t), sz);
    546 	} else {
    547 		dofpv.dofpv_prenoffs = DOF_SECT_NONE;
    548 	}
    549 
    550 	dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_enoffs, sizeof (uint_t));
    551 
    552 	dofpv.dofpv_strtab = ddo->ddo_strsec;
    553 	dofpv.dofpv_name = dof_add_string(ddo, pvp->pv_desc.dtvd_name);
    554 
    555 	dofpv.dofpv_provattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_provider);
    556 	dofpv.dofpv_modattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_mod);
    557 	dofpv.dofpv_funcattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_func);
    558 	dofpv.dofpv_nameattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_name);
    559 	dofpv.dofpv_argsattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_args);
    560 
    561 	dofs[0] = dof_add_lsect(ddo, &dofpv, DOF_SECT_PROVIDER,
    562 	    sizeof (dof_secidx_t), 0, 0, sizeof (dof_provider_t));
    563 
    564 	dofr.dofr_strtab = dofpv.dofpv_strtab;
    565 	dofr.dofr_tgtsec = dofpv.dofpv_probes;
    566 	dofr.dofr_relsec = dof_add_lsect(ddo, NULL, DOF_SECT_RELTAB,
    567 	    sizeof (uint64_t), 0, sizeof (dof_relodesc_t),
    568 	    dt_buf_len(&ddo->ddo_rels));
    569 
    570 	dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_rels, sizeof (uint64_t));
    571 
    572 	(void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR,
    573 	    sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t));
    574 
    575 	if (nxr != 0 && dtp->dt_xlatemode == DT_XL_DYNAMIC) {
    576 		(void) dof_add_lsect(ddo, dofs, DOF_SECT_PREXPORT,
    577 		    sizeof (dof_secidx_t), 0, sizeof (dof_secidx_t),
    578 		    sizeof (dof_secidx_t) * (nxr + 1));
    579 	}
    580 
    581 	return (0);
    582 }
    583 
    584 static int
    585 dof_hdr(dtrace_hdl_t *dtp, uint8_t dofversion, dof_hdr_t *hp)
    586 {
    587 	/*
    588 	 * If our config values cannot fit in a uint8_t, we can't generate a
    589 	 * DOF header since the values won't fit.  This can only happen if the
    590 	 * user forcibly compiles a program with an artificial configuration.
    591 	 */
    592 	if (dtp->dt_conf.dtc_difversion > UINT8_MAX ||
    593 	    dtp->dt_conf.dtc_difintregs > UINT8_MAX ||
    594 	    dtp->dt_conf.dtc_diftupregs > UINT8_MAX)
    595 		return (dt_set_errno(dtp, EOVERFLOW));
    596 
    597 	bzero(hp, sizeof (dof_hdr_t));
    598 
    599 	hp->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0;
    600 	hp->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1;
    601 	hp->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2;
    602 	hp->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3;
    603 
    604 	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
    605 		hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_LP64;
    606 	else
    607 		hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_ILP32;
    608 
    609 	hp->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE;
    610 	hp->dofh_ident[DOF_ID_VERSION] = dofversion;
    611 	hp->dofh_ident[DOF_ID_DIFVERS] = dtp->dt_conf.dtc_difversion;
    612 	hp->dofh_ident[DOF_ID_DIFIREG] = dtp->dt_conf.dtc_difintregs;
    613 	hp->dofh_ident[DOF_ID_DIFTREG] = dtp->dt_conf.dtc_diftupregs;
    614 
    615 	hp->dofh_hdrsize = sizeof (dof_hdr_t);
    616 	hp->dofh_secsize = sizeof (dof_sec_t);
    617 	hp->dofh_secoff = sizeof (dof_hdr_t);
    618 
    619 	return (0);
    620 }
    621 
    622 void *
    623 dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags)
    624 {
    625 	dt_dof_t *ddo = &dtp->dt_dof;
    626 
    627 	const dtrace_ecbdesc_t *edp, *last;
    628 	const dtrace_probedesc_t *pdp;
    629 	const dtrace_actdesc_t *ap;
    630 	const dt_stmt_t *stp;
    631 
    632 	uint_t maxacts = 0;
    633 	uint_t maxfmt = 0;
    634 
    635 	dt_provider_t *pvp;
    636 	dt_xlator_t *dxp;
    637 	dof_actdesc_t *dofa;
    638 	dof_sec_t *sp;
    639 	size_t ssize, lsize;
    640 	dof_hdr_t h;
    641 
    642 	dt_buf_t dof;
    643 	char *fmt;
    644 	uint_t i;
    645 
    646 	if (flags & ~DTRACE_D_MASK) {
    647 		(void) dt_set_errno(dtp, EINVAL);
    648 		return (NULL);
    649 	}
    650 
    651 	flags |= dtp->dt_dflags;
    652 
    653 	if (dof_hdr(dtp, pgp->dp_dofversion, &h) != 0)
    654 		return (NULL);
    655 
    656 	if (dt_dof_reset(dtp, pgp) != 0)
    657 		return (NULL);
    658 
    659 	/*
    660 	 * Iterate through the statement list computing the maximum number of
    661 	 * actions and the maximum format string for allocating local buffers.
    662 	 */
    663 	for (last = NULL, stp = dt_list_next(&pgp->dp_stmts);
    664 	    stp != NULL; stp = dt_list_next(stp), last = edp) {
    665 
    666 		dtrace_stmtdesc_t *sdp = stp->ds_desc;
    667 		dtrace_actdesc_t *ap = sdp->dtsd_action;
    668 
    669 		if (sdp->dtsd_fmtdata != NULL) {
    670 			i = dtrace_printf_format(dtp,
    671 			    sdp->dtsd_fmtdata, NULL, 0);
    672 			maxfmt = MAX(maxfmt, i);
    673 		}
    674 
    675 		if ((edp = sdp->dtsd_ecbdesc) == last)
    676 			continue; /* same ecb as previous statement */
    677 
    678 		for (i = 0, ap = edp->dted_action; ap; ap = ap->dtad_next)
    679 			i++;
    680 
    681 		maxacts = MAX(maxacts, i);
    682 	}
    683 
    684 	dofa = alloca(sizeof (dof_actdesc_t) * maxacts);
    685 	fmt = alloca(maxfmt + 1);
    686 
    687 	ddo->ddo_strsec = dof_add_lsect(ddo, NULL, DOF_SECT_STRTAB, 1, 0, 0, 0);
    688 	(void) dof_add_string(ddo, "");
    689 
    690 	/*
    691 	 * If there are references to dynamic translators in the program, add
    692 	 * an imported translator table entry for each referenced translator.
    693 	 */
    694 	if (pgp->dp_xrefslen != 0) {
    695 		for (dxp = dt_list_next(&dtp->dt_xlators);
    696 		    dxp != NULL; dxp = dt_list_next(dxp)) {
    697 			if (dxp->dx_id < pgp->dp_xrefslen &&
    698 			    pgp->dp_xrefs[dxp->dx_id] != NULL)
    699 				dof_add_translator(ddo, dxp, DOF_SECT_XLIMPORT);
    700 		}
    701 	}
    702 
    703 	/*
    704 	 * Now iterate through the statement list, creating the DOF section
    705 	 * headers and data for each one and adding them to our buffers.
    706 	 */
    707 	for (last = NULL, stp = dt_list_next(&pgp->dp_stmts);
    708 	    stp != NULL; stp = dt_list_next(stp), last = edp) {
    709 
    710 		dof_secidx_t probesec = DOF_SECIDX_NONE;
    711 		dof_secidx_t prdsec = DOF_SECIDX_NONE;
    712 		dof_secidx_t actsec = DOF_SECIDX_NONE;
    713 
    714 		const dt_stmt_t *next = stp;
    715 		dtrace_stmtdesc_t *sdp = stp->ds_desc;
    716 		dof_stridx_t strndx = 0;
    717 		dof_probedesc_t dofp;
    718 		dof_ecbdesc_t dofe;
    719 		uint_t i;
    720 
    721 		if ((edp = stp->ds_desc->dtsd_ecbdesc) == last)
    722 			continue; /* same ecb as previous statement */
    723 
    724 		pdp = &edp->dted_probe;
    725 
    726 		/*
    727 		 * Add a DOF_SECT_PROBEDESC for the ECB's probe description,
    728 		 * and copy the probe description strings into the string table.
    729 		 */
    730 		dofp.dofp_strtab = ddo->ddo_strsec;
    731 		dofp.dofp_provider = dof_add_string(ddo, pdp->dtpd_provider);
    732 		dofp.dofp_mod = dof_add_string(ddo, pdp->dtpd_mod);
    733 		dofp.dofp_func = dof_add_string(ddo, pdp->dtpd_func);
    734 		dofp.dofp_name = dof_add_string(ddo, pdp->dtpd_name);
    735 		dofp.dofp_id = pdp->dtpd_id;
    736 
    737 		probesec = dof_add_lsect(ddo, &dofp, DOF_SECT_PROBEDESC,
    738 		    sizeof (dof_secidx_t), 0,
    739 		    sizeof (dof_probedesc_t), sizeof (dof_probedesc_t));
    740 
    741 		/*
    742 		 * If there is a predicate DIFO associated with the ecbdesc,
    743 		 * write out the DIFO sections and save the DIFO section index.
    744 		 */
    745 		if (edp->dted_pred.dtpdd_difo != NULL)
    746 			prdsec = dof_add_difo(ddo, edp->dted_pred.dtpdd_difo);
    747 
    748 		/*
    749 		 * Now iterate through the action list generating DIFOs as
    750 		 * referenced therein and adding action descriptions to 'dofa'.
    751 		 */
    752 		for (i = 0, ap = edp->dted_action;
    753 		    ap != NULL; ap = ap->dtad_next, i++) {
    754 
    755 			if (ap->dtad_difo != NULL) {
    756 				dofa[i].dofa_difo =
    757 				    dof_add_difo(ddo, ap->dtad_difo);
    758 			} else
    759 				dofa[i].dofa_difo = DOF_SECIDX_NONE;
    760 
    761 			/*
    762 			 * If the first action in a statement has string data,
    763 			 * add the string to the global string table.  This can
    764 			 * be due either to a printf() format string
    765 			 * (dtsd_fmtdata) or a print() type string
    766 			 * (dtsd_strdata).
    767 			 */
    768 			if (sdp != NULL && ap == sdp->dtsd_action) {
    769 				if (sdp->dtsd_fmtdata != NULL) {
    770 					(void) dtrace_printf_format(dtp,
    771 					    sdp->dtsd_fmtdata, fmt, maxfmt + 1);
    772 					strndx = dof_add_string(ddo, fmt);
    773 				} else if (sdp->dtsd_strdata != NULL) {
    774 					strndx = dof_add_string(ddo,
    775 					    sdp->dtsd_strdata);
    776 				} else {
    777 					strndx = 0; /* use dtad_arg instead */
    778 				}
    779 
    780 				if ((next = dt_list_next(next)) != NULL)
    781 					sdp = next->ds_desc;
    782 				else
    783 					sdp = NULL;
    784 			}
    785 
    786 			if (strndx != 0) {
    787 				dofa[i].dofa_arg = strndx;
    788 				dofa[i].dofa_strtab = ddo->ddo_strsec;
    789 			} else {
    790 				dofa[i].dofa_arg = ap->dtad_arg;
    791 				dofa[i].dofa_strtab = DOF_SECIDX_NONE;
    792 			}
    793 
    794 			dofa[i].dofa_kind = ap->dtad_kind;
    795 			dofa[i].dofa_ntuple = ap->dtad_ntuple;
    796 			dofa[i].dofa_uarg = ap->dtad_uarg;
    797 		}
    798 
    799 		if (i > 0) {
    800 			actsec = dof_add_lsect(ddo, dofa, DOF_SECT_ACTDESC,
    801 			    sizeof (uint64_t), 0, sizeof (dof_actdesc_t),
    802 			    sizeof (dof_actdesc_t) * i);
    803 		}
    804 
    805 		/*
    806 		 * Now finally, add the DOF_SECT_ECBDESC referencing all the
    807 		 * previously created sub-sections.
    808 		 */
    809 		dofe.dofe_probes = probesec;
    810 		dofe.dofe_pred = prdsec;
    811 		dofe.dofe_actions = actsec;
    812 		dofe.dofe_pad = 0;
    813 		dofe.dofe_uarg = edp->dted_uarg;
    814 
    815 		(void) dof_add_lsect(ddo, &dofe, DOF_SECT_ECBDESC,
    816 		    sizeof (uint64_t), 0, 0, sizeof (dof_ecbdesc_t));
    817 	}
    818 
    819 	/*
    820 	 * If any providers are user-defined, output DOF sections corresponding
    821 	 * to the providers and the probes and arguments that they define.
    822 	 */
    823 	if (flags & DTRACE_D_PROBES) {
    824 		for (pvp = dt_list_next(&dtp->dt_provlist);
    825 		    pvp != NULL; pvp = dt_list_next(pvp)) {
    826 			if (dof_add_provider(ddo, pvp) != 0)
    827 				return (NULL);
    828 		}
    829 	}
    830 
    831 	/*
    832 	 * If we're not stripping unloadable sections, generate compiler
    833 	 * comments and any other unloadable miscellany.
    834 	 */
    835 	if (!(flags & DTRACE_D_STRIP)) {
    836 		(void) dof_add_usect(ddo, _dtrace_version, DOF_SECT_COMMENTS,
    837 		    sizeof (char), 0, 0, strlen(_dtrace_version) + 1);
    838 		(void) dof_add_usect(ddo, &dtp->dt_uts, DOF_SECT_UTSNAME,
    839 		    sizeof (char), 0, 0, sizeof (struct utsname));
    840 	}
    841 
    842 	/*
    843 	 * Compute and fill in the appropriate values for the dof_hdr_t's
    844 	 * dofh_secnum, dofh_loadsz, and dofh_filez values.
    845 	 */
    846 	h.dofh_secnum = ddo->ddo_nsecs;
    847 	ssize = sizeof (h) + dt_buf_len(&ddo->ddo_secs);
    848 
    849 	h.dofh_loadsz = ssize +
    850 	    dt_buf_len(&ddo->ddo_ldata) +
    851 	    dt_buf_len(&ddo->ddo_strs);
    852 
    853 	if (dt_buf_len(&ddo->ddo_udata) != 0) {
    854 		lsize = roundup(h.dofh_loadsz, sizeof (uint64_t));
    855 		h.dofh_filesz = lsize + dt_buf_len(&ddo->ddo_udata);
    856 	} else {
    857 		lsize = h.dofh_loadsz;
    858 		h.dofh_filesz = lsize;
    859 	}
    860 
    861 	/*
    862 	 * Set the global DOF_SECT_STRTAB's offset to be after the header,
    863 	 * section headers, and other loadable data.  Since we're going to
    864 	 * iterate over the buffer data directly, we must check for errors.
    865 	 */
    866 	if ((i = dt_buf_error(&ddo->ddo_secs)) != 0) {
    867 		(void) dt_set_errno(dtp, i);
    868 		return (NULL);
    869 	}
    870 
    871 	sp = dt_buf_ptr(&ddo->ddo_secs);
    872 	assert(sp[ddo->ddo_strsec].dofs_type == DOF_SECT_STRTAB);
    873 	assert(ssize == sizeof (h) + sizeof (dof_sec_t) * ddo->ddo_nsecs);
    874 
    875 	sp[ddo->ddo_strsec].dofs_offset = ssize + dt_buf_len(&ddo->ddo_ldata);
    876 	sp[ddo->ddo_strsec].dofs_size = dt_buf_len(&ddo->ddo_strs);
    877 
    878 	/*
    879 	 * Now relocate all the other section headers by adding the appropriate
    880 	 * delta to their respective dofs_offset values.
    881 	 */
    882 	for (i = 0; i < ddo->ddo_nsecs; i++, sp++) {
    883 		if (i == ddo->ddo_strsec)
    884 			continue; /* already relocated above */
    885 
    886 		if (sp->dofs_flags & DOF_SECF_LOAD)
    887 			sp->dofs_offset += ssize;
    888 		else
    889 			sp->dofs_offset += lsize;
    890 	}
    891 
    892 	/*
    893 	 * Finally, assemble the complete in-memory DOF buffer by writing the
    894 	 * header and then concatenating all our buffers.  dt_buf_concat() will
    895 	 * propagate any errors and cause dt_buf_claim() to return NULL.
    896 	 */
    897 	dt_buf_create(dtp, &dof, "dof", h.dofh_filesz);
    898 
    899 	dt_buf_write(dtp, &dof, &h, sizeof (h), sizeof (uint64_t));
    900 	dt_buf_concat(dtp, &dof, &ddo->ddo_secs, sizeof (uint64_t));
    901 	dt_buf_concat(dtp, &dof, &ddo->ddo_ldata, sizeof (uint64_t));
    902 	dt_buf_concat(dtp, &dof, &ddo->ddo_strs, sizeof (char));
    903 	dt_buf_concat(dtp, &dof, &ddo->ddo_udata, sizeof (uint64_t));
    904 
    905 	return (dt_buf_claim(dtp, &dof));
    906 }
    907 
    908 void
    909 dtrace_dof_destroy(dtrace_hdl_t *dtp, void *dof)
    910 {
    911 	dt_free(dtp, dof);
    912 }
    913 
    914 void *
    915 dtrace_getopt_dof(dtrace_hdl_t *dtp)
    916 {
    917 	dof_hdr_t *dof;
    918 	dof_sec_t *sec;
    919 	dof_optdesc_t *dofo;
    920 	int i, nopts = 0, len = sizeof (dof_hdr_t) +
    921 	    roundup(sizeof (dof_sec_t), sizeof (uint64_t));
    922 
    923 	for (i = 0; i < DTRACEOPT_MAX; i++) {
    924 		if (dtp->dt_options[i] != DTRACEOPT_UNSET)
    925 			nopts++;
    926 	}
    927 
    928 	len += sizeof (dof_optdesc_t) * nopts;
    929 
    930 	if ((dof = dt_zalloc(dtp, len)) == NULL ||
    931 	    dof_hdr(dtp, DOF_VERSION, dof) != 0) {
    932 		dt_free(dtp, dof);
    933 		return (NULL);
    934 	}
    935 
    936 	dof->dofh_secnum = 1;	/* only DOF_SECT_OPTDESC */
    937 	dof->dofh_loadsz = len;
    938 	dof->dofh_filesz = len;
    939 
    940 	/*
    941 	 * Fill in the option section header...
    942 	 */
    943 	sec = (dof_sec_t *)((uintptr_t)dof + sizeof (dof_hdr_t));
    944 	sec->dofs_type = DOF_SECT_OPTDESC;
    945 	sec->dofs_align = sizeof (uint64_t);
    946 	sec->dofs_flags = DOF_SECF_LOAD;
    947 	sec->dofs_entsize = sizeof (dof_optdesc_t);
    948 
    949 	dofo = (dof_optdesc_t *)((uintptr_t)sec +
    950 	    roundup(sizeof (dof_sec_t), sizeof (uint64_t)));
    951 
    952 	sec->dofs_offset = (uintptr_t)dofo - (uintptr_t)dof;
    953 	sec->dofs_size = sizeof (dof_optdesc_t) * nopts;
    954 
    955 	for (i = 0; i < DTRACEOPT_MAX; i++) {
    956 		if (dtp->dt_options[i] == DTRACEOPT_UNSET)
    957 			continue;
    958 
    959 		dofo->dofo_option = i;
    960 		dofo->dofo_strtab = DOF_SECIDX_NONE;
    961 		dofo->dofo_value = dtp->dt_options[i];
    962 		dofo++;
    963 	}
    964 
    965 	return (dof);
    966 }
    967 
    968 void *
    969 dtrace_geterr_dof(dtrace_hdl_t *dtp)
    970 {
    971 	if (dtp->dt_errprog != NULL)
    972 		return (dtrace_dof_create(dtp, dtp->dt_errprog, 0));
    973 
    974 	(void) dt_set_errno(dtp, EDT_BADERROR);
    975 	return (NULL);
    976 }
    977