1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/sysmacros.h> 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate #include <strings.h> 33*0Sstevel@tonic-gate #include <alloca.h> 34*0Sstevel@tonic-gate #include <assert.h> 35*0Sstevel@tonic-gate #include <stdlib.h> 36*0Sstevel@tonic-gate #include <errno.h> 37*0Sstevel@tonic-gate #include <limits.h> 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #include <dt_impl.h> 40*0Sstevel@tonic-gate #include <dt_strtab.h> 41*0Sstevel@tonic-gate #include <dt_provider.h> 42*0Sstevel@tonic-gate #include <dt_dof.h> 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate void 45*0Sstevel@tonic-gate dt_dof_init(dtrace_hdl_t *dtp) 46*0Sstevel@tonic-gate { 47*0Sstevel@tonic-gate dt_dof_t *ddo = &dtp->dt_dof; 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate ddo->ddo_hdl = dtp; 50*0Sstevel@tonic-gate ddo->ddo_nsecs = 0; 51*0Sstevel@tonic-gate ddo->ddo_strsec = DOF_SECIDX_NONE; 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_secs, "section headers", 0); 54*0Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_strs, "string table", 0); 55*0Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_ldata, "loadable data", 0); 56*0Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_udata, "unloadable data", 0); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_probes, "probe data", 0); 59*0Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_args, "probe args", 0); 60*0Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_offs, "probe offs", 0); 61*0Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_rels, "probe rels", 0); 62*0Sstevel@tonic-gate } 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate void 65*0Sstevel@tonic-gate dt_dof_fini(dtrace_hdl_t *dtp) 66*0Sstevel@tonic-gate { 67*0Sstevel@tonic-gate dt_dof_t *ddo = &dtp->dt_dof; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_secs); 70*0Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_strs); 71*0Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_ldata); 72*0Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_udata); 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_probes); 75*0Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_args); 76*0Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_offs); 77*0Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_rels); 78*0Sstevel@tonic-gate } 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate void 81*0Sstevel@tonic-gate dt_dof_reset(dtrace_hdl_t *dtp) 82*0Sstevel@tonic-gate { 83*0Sstevel@tonic-gate dt_dof_t *ddo = &dtp->dt_dof; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate ddo->ddo_nsecs = 0; 86*0Sstevel@tonic-gate ddo->ddo_strsec = DOF_SECIDX_NONE; 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_secs); 89*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_strs); 90*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_ldata); 91*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_udata); 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_probes); 94*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_args); 95*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_offs); 96*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_rels); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* 100*0Sstevel@tonic-gate * Add a loadable DOF section to the file using the specified data buffer and 101*0Sstevel@tonic-gate * the specified DOF section attributes. DOF_SECF_LOAD must be set in flags. 102*0Sstevel@tonic-gate * If 'data' is NULL, the caller is responsible for manipulating the ldata buf. 103*0Sstevel@tonic-gate */ 104*0Sstevel@tonic-gate static dof_secidx_t 105*0Sstevel@tonic-gate dof_add_lsect(dt_dof_t *ddo, const void *data, uint32_t type, 106*0Sstevel@tonic-gate uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size) 107*0Sstevel@tonic-gate { 108*0Sstevel@tonic-gate dtrace_hdl_t *dtp = ddo->ddo_hdl; 109*0Sstevel@tonic-gate dof_sec_t s; 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate s.dofs_type = type; 112*0Sstevel@tonic-gate s.dofs_align = align; 113*0Sstevel@tonic-gate s.dofs_flags = flags | DOF_SECF_LOAD; 114*0Sstevel@tonic-gate s.dofs_entsize = entsize; 115*0Sstevel@tonic-gate s.dofs_offset = dt_buf_offset(&ddo->ddo_ldata, align); 116*0Sstevel@tonic-gate s.dofs_size = size; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t)); 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate if (data != NULL) 121*0Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_ldata, data, size, align); 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate return (ddo->ddo_nsecs++); 124*0Sstevel@tonic-gate } 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate /* 127*0Sstevel@tonic-gate * Add an unloadable DOF section to the file using the specified data buffer 128*0Sstevel@tonic-gate * and DOF section attributes. DOF_SECF_LOAD must *not* be set in flags. 129*0Sstevel@tonic-gate * If 'data' is NULL, the caller is responsible for manipulating the udata buf. 130*0Sstevel@tonic-gate */ 131*0Sstevel@tonic-gate static dof_secidx_t 132*0Sstevel@tonic-gate dof_add_usect(dt_dof_t *ddo, const void *data, uint32_t type, 133*0Sstevel@tonic-gate uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size) 134*0Sstevel@tonic-gate { 135*0Sstevel@tonic-gate dtrace_hdl_t *dtp = ddo->ddo_hdl; 136*0Sstevel@tonic-gate dof_sec_t s; 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate s.dofs_type = type; 139*0Sstevel@tonic-gate s.dofs_align = align; 140*0Sstevel@tonic-gate s.dofs_flags = flags & ~DOF_SECF_LOAD; 141*0Sstevel@tonic-gate s.dofs_entsize = entsize; 142*0Sstevel@tonic-gate s.dofs_offset = dt_buf_offset(&ddo->ddo_udata, align); 143*0Sstevel@tonic-gate s.dofs_size = size; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t)); 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate if (data != NULL) 148*0Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_udata, data, size, align); 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate return (ddo->ddo_nsecs++); 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate /* 154*0Sstevel@tonic-gate * Add a string to the global string table associated with the DOF. The offset 155*0Sstevel@tonic-gate * of the string is returned as an index into the string table. 156*0Sstevel@tonic-gate */ 157*0Sstevel@tonic-gate static dof_stridx_t 158*0Sstevel@tonic-gate dof_add_string(dt_dof_t *ddo, const char *s) 159*0Sstevel@tonic-gate { 160*0Sstevel@tonic-gate dt_buf_t *bp = &ddo->ddo_strs; 161*0Sstevel@tonic-gate dof_stridx_t i = dt_buf_len(bp); 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate if (i != 0 && (s == NULL || *s == '\0')) 164*0Sstevel@tonic-gate return (0); /* string table has \0 at offset 0 */ 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate dt_buf_write(ddo->ddo_hdl, bp, s, strlen(s) + 1, sizeof (char)); 167*0Sstevel@tonic-gate return (i); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate static dof_attr_t 171*0Sstevel@tonic-gate dof_attr(const dtrace_attribute_t *ap) 172*0Sstevel@tonic-gate { 173*0Sstevel@tonic-gate return (DOF_ATTR(ap->dtat_name, ap->dtat_data, ap->dtat_class)); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate static dof_secidx_t 177*0Sstevel@tonic-gate dof_add_difo(dt_dof_t *ddo, const dtrace_difo_t *dp) 178*0Sstevel@tonic-gate { 179*0Sstevel@tonic-gate dof_secidx_t dsecs[4]; /* enough for all possible DIFO sections */ 180*0Sstevel@tonic-gate uint_t nsecs = 0; 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate dof_difohdr_t *dofd; 183*0Sstevel@tonic-gate dof_relohdr_t dofr; 184*0Sstevel@tonic-gate dof_secidx_t relsec; 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate dof_secidx_t strsec = DOF_SECIDX_NONE; 187*0Sstevel@tonic-gate dof_secidx_t intsec = DOF_SECIDX_NONE; 188*0Sstevel@tonic-gate dof_secidx_t hdrsec = DOF_SECIDX_NONE; 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate if (dp->dtdo_buf != NULL) { 191*0Sstevel@tonic-gate dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_buf, 192*0Sstevel@tonic-gate DOF_SECT_DIF, sizeof (dif_instr_t), 0, 193*0Sstevel@tonic-gate sizeof (dif_instr_t), sizeof (dif_instr_t) * dp->dtdo_len); 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate if (dp->dtdo_inttab != NULL) { 197*0Sstevel@tonic-gate dsecs[nsecs++] = intsec = dof_add_lsect(ddo, dp->dtdo_inttab, 198*0Sstevel@tonic-gate DOF_SECT_INTTAB, sizeof (uint64_t), 0, 199*0Sstevel@tonic-gate sizeof (uint64_t), sizeof (uint64_t) * dp->dtdo_intlen); 200*0Sstevel@tonic-gate } 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate if (dp->dtdo_strtab != NULL) { 203*0Sstevel@tonic-gate dsecs[nsecs++] = strsec = dof_add_lsect(ddo, dp->dtdo_strtab, 204*0Sstevel@tonic-gate DOF_SECT_STRTAB, sizeof (char), 0, 0, dp->dtdo_strlen); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate if (dp->dtdo_vartab != NULL) { 208*0Sstevel@tonic-gate dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_vartab, 209*0Sstevel@tonic-gate DOF_SECT_VARTAB, sizeof (uint_t), 0, sizeof (dtrace_difv_t), 210*0Sstevel@tonic-gate sizeof (dtrace_difv_t) * dp->dtdo_varlen); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * Copy the return type and the array of section indices that form the 215*0Sstevel@tonic-gate * DIFO into a single dof_difohdr_t and then add DOF_SECT_DIFOHDR. 216*0Sstevel@tonic-gate */ 217*0Sstevel@tonic-gate assert(nsecs <= sizeof (dsecs) / sizeof (dsecs[0])); 218*0Sstevel@tonic-gate dofd = alloca(sizeof (dtrace_diftype_t) + sizeof (dsecs)); 219*0Sstevel@tonic-gate bcopy(&dp->dtdo_rtype, &dofd->dofd_rtype, sizeof (dtrace_diftype_t)); 220*0Sstevel@tonic-gate bcopy(dsecs, &dofd->dofd_links, sizeof (dof_secidx_t) * nsecs); 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate hdrsec = dof_add_lsect(ddo, dofd, DOF_SECT_DIFOHDR, 223*0Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, 224*0Sstevel@tonic-gate sizeof (dtrace_diftype_t) + sizeof (dof_secidx_t) * nsecs); 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate /* 227*0Sstevel@tonic-gate * Add any other sections related to dtrace_difo_t. These are not 228*0Sstevel@tonic-gate * referenced in dof_difohdr_t because they are not used by emulation. 229*0Sstevel@tonic-gate */ 230*0Sstevel@tonic-gate if (dp->dtdo_kreltab != NULL) { 231*0Sstevel@tonic-gate relsec = dof_add_lsect(ddo, dp->dtdo_kreltab, DOF_SECT_RELTAB, 232*0Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 233*0Sstevel@tonic-gate sizeof (dof_relodesc_t) * dp->dtdo_krelen); 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate /* 236*0Sstevel@tonic-gate * This code assumes the target of all relocations is the 237*0Sstevel@tonic-gate * integer table 'intsec' (DOF_SECT_INTTAB). If other sections 238*0Sstevel@tonic-gate * need relocation in the future this will need to change. 239*0Sstevel@tonic-gate */ 240*0Sstevel@tonic-gate dofr.dofr_strtab = strsec; 241*0Sstevel@tonic-gate dofr.dofr_relsec = relsec; 242*0Sstevel@tonic-gate dofr.dofr_tgtsec = intsec; 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate (void) dof_add_lsect(ddo, &dofr, DOF_SECT_KRELHDR, 245*0Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate if (dp->dtdo_ureltab != NULL) { 249*0Sstevel@tonic-gate relsec = dof_add_lsect(ddo, dp->dtdo_ureltab, DOF_SECT_RELTAB, 250*0Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 251*0Sstevel@tonic-gate sizeof (dof_relodesc_t) * dp->dtdo_urelen); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * This code assumes the target of all relocations is the 255*0Sstevel@tonic-gate * integer table 'intsec' (DOF_SECT_INTTAB). If other sections 256*0Sstevel@tonic-gate * need relocation in the future this will need to change. 257*0Sstevel@tonic-gate */ 258*0Sstevel@tonic-gate dofr.dofr_strtab = strsec; 259*0Sstevel@tonic-gate dofr.dofr_relsec = relsec; 260*0Sstevel@tonic-gate dofr.dofr_tgtsec = intsec; 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate (void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR, 263*0Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 264*0Sstevel@tonic-gate } 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate return (hdrsec); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate /*ARGSUSED*/ 270*0Sstevel@tonic-gate static int 271*0Sstevel@tonic-gate dof_add_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 272*0Sstevel@tonic-gate { 273*0Sstevel@tonic-gate dt_dof_t *ddo = data; 274*0Sstevel@tonic-gate dtrace_hdl_t *dtp = ddo->ddo_hdl; 275*0Sstevel@tonic-gate dt_probe_t *prp = idp->di_data; 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate dof_probe_t dofpr; 278*0Sstevel@tonic-gate dof_relodesc_t dofr; 279*0Sstevel@tonic-gate dt_probe_instance_t *pip; 280*0Sstevel@tonic-gate dt_node_t *dnp; 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate char buf[DT_TYPE_NAMELEN]; 283*0Sstevel@tonic-gate uint_t i; 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate dofpr.dofpr_addr = 0; 286*0Sstevel@tonic-gate dofpr.dofpr_name = dof_add_string(ddo, prp->pr_name); 287*0Sstevel@tonic-gate dofpr.dofpr_nargv = dt_buf_len(&ddo->ddo_strs); 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate for (dnp = prp->pr_nargs; dnp != NULL; dnp = dnp->dn_list) { 290*0Sstevel@tonic-gate (void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp, 291*0Sstevel@tonic-gate dnp->dn_type, buf, sizeof (buf))); 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate dofpr.dofpr_xargv = dt_buf_len(&ddo->ddo_strs); 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate for (dnp = prp->pr_xargs; dnp != NULL; dnp = dnp->dn_list) { 297*0Sstevel@tonic-gate (void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp, 298*0Sstevel@tonic-gate dnp->dn_type, buf, sizeof (buf))); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate dofpr.dofpr_argidx = dt_buf_len(&ddo->ddo_args) / sizeof (uint8_t); 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate for (i = 0; i < prp->pr_xargc; i++) { 304*0Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_args, &prp->pr_mapping[i], 305*0Sstevel@tonic-gate sizeof (uint8_t), sizeof (uint8_t)); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate dofpr.dofpr_nargc = prp->pr_nargc; 309*0Sstevel@tonic-gate dofpr.dofpr_xargc = prp->pr_xargc; 310*0Sstevel@tonic-gate dofpr.dofpr_pad = 0; 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) { 313*0Sstevel@tonic-gate dofpr.dofpr_func = dof_add_string(ddo, pip->pi_fname); 314*0Sstevel@tonic-gate dofpr.dofpr_offidx = 315*0Sstevel@tonic-gate dt_buf_len(&ddo->ddo_offs) / sizeof (uint32_t); 316*0Sstevel@tonic-gate dofpr.dofpr_noffs = pip->pi_noffs; 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_offs, pip->pi_offs, 319*0Sstevel@tonic-gate pip->pi_noffs * sizeof (uint32_t), sizeof (uint32_t)); 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate dofr.dofr_name = dofpr.dofpr_func; 322*0Sstevel@tonic-gate dofr.dofr_type = DOF_RELO_SETX; 323*0Sstevel@tonic-gate dofr.dofr_offset = dt_buf_len(&ddo->ddo_probes); 324*0Sstevel@tonic-gate dofr.dofr_data = 0; 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_rels, &dofr, 327*0Sstevel@tonic-gate sizeof (dofr), sizeof (uint64_t)); 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_probes, &dofpr, 330*0Sstevel@tonic-gate sizeof (dofpr), sizeof (uint64_t)); 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate return (0); 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate static void 337*0Sstevel@tonic-gate dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp) 338*0Sstevel@tonic-gate { 339*0Sstevel@tonic-gate dtrace_hdl_t *dtp = ddo->ddo_hdl; 340*0Sstevel@tonic-gate dof_provider_t dofpv; 341*0Sstevel@tonic-gate dof_relohdr_t dofr; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate if (pvp->pv_flags & DT_PROVIDER_IMPL) 344*0Sstevel@tonic-gate return; /* ignore providers that are exported by dtrace(7D) */ 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_probes); 347*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_args); 348*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_offs); 349*0Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_rels); 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate (void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo); 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate dofpv.dofpv_probes = dof_add_lsect(ddo, NULL, DOF_SECT_PROBES, 354*0Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_probe_t), 355*0Sstevel@tonic-gate dt_buf_len(&ddo->ddo_probes)); 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate dt_buf_concat(dtp, &ddo->ddo_ldata, 358*0Sstevel@tonic-gate &ddo->ddo_probes, sizeof (uint64_t)); 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate dofpv.dofpv_prargs = dof_add_lsect(ddo, NULL, DOF_SECT_PRARGS, 361*0Sstevel@tonic-gate sizeof (uint8_t), 0, sizeof (uint8_t), dt_buf_len(&ddo->ddo_args)); 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_args, sizeof (uint8_t)); 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate dofpv.dofpv_proffs = dof_add_lsect(ddo, NULL, DOF_SECT_PROFFS, 366*0Sstevel@tonic-gate sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_offs)); 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_offs, sizeof (uint_t)); 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate dofpv.dofpv_strtab = ddo->ddo_strsec; 371*0Sstevel@tonic-gate dofpv.dofpv_name = dof_add_string(ddo, pvp->pv_desc.dtvd_name); 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate dofpv.dofpv_provattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_provider); 374*0Sstevel@tonic-gate dofpv.dofpv_modattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_mod); 375*0Sstevel@tonic-gate dofpv.dofpv_funcattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_func); 376*0Sstevel@tonic-gate dofpv.dofpv_nameattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_name); 377*0Sstevel@tonic-gate dofpv.dofpv_argsattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_args); 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate (void) dof_add_lsect(ddo, &dofpv, DOF_SECT_PROVIDER, 380*0Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, sizeof (dof_provider_t)); 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate dofr.dofr_strtab = dofpv.dofpv_strtab; 383*0Sstevel@tonic-gate dofr.dofr_tgtsec = dofpv.dofpv_probes; 384*0Sstevel@tonic-gate dofr.dofr_relsec = dof_add_lsect(ddo, NULL, DOF_SECT_RELTAB, 385*0Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 386*0Sstevel@tonic-gate dt_buf_len(&ddo->ddo_rels)); 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_rels, sizeof (uint64_t)); 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate (void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR, 391*0Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate static int 395*0Sstevel@tonic-gate dof_hdr(dtrace_hdl_t *dtp, dof_hdr_t *hp) 396*0Sstevel@tonic-gate { 397*0Sstevel@tonic-gate /* 398*0Sstevel@tonic-gate * If our config values cannot fit in a uint8_t, we can't generate a 399*0Sstevel@tonic-gate * DOF header since the values won't fit. This can only happen if the 400*0Sstevel@tonic-gate * user forcibly compiles a program with an artificial configuration. 401*0Sstevel@tonic-gate */ 402*0Sstevel@tonic-gate if (dtp->dt_conf.dtc_difversion > UINT8_MAX || 403*0Sstevel@tonic-gate dtp->dt_conf.dtc_difintregs > UINT8_MAX || 404*0Sstevel@tonic-gate dtp->dt_conf.dtc_diftupregs > UINT8_MAX) 405*0Sstevel@tonic-gate return (dt_set_errno(dtp, EOVERFLOW)); 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate bzero(hp, sizeof (dof_hdr_t)); 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0; 410*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1; 411*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2; 412*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3; 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) 415*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_LP64; 416*0Sstevel@tonic-gate else 417*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_ILP32; 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE; 420*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_VERSION] = DOF_VERSION_1; 421*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_DIFVERS] = dtp->dt_conf.dtc_difversion; 422*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_DIFIREG] = dtp->dt_conf.dtc_difintregs; 423*0Sstevel@tonic-gate hp->dofh_ident[DOF_ID_DIFTREG] = dtp->dt_conf.dtc_diftupregs; 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate hp->dofh_hdrsize = sizeof (dof_hdr_t); 426*0Sstevel@tonic-gate hp->dofh_secsize = sizeof (dof_sec_t); 427*0Sstevel@tonic-gate hp->dofh_secoff = sizeof (dof_hdr_t); 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate return (0); 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate void * 433*0Sstevel@tonic-gate dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags) 434*0Sstevel@tonic-gate { 435*0Sstevel@tonic-gate dt_dof_t *ddo = &dtp->dt_dof; 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate const dtrace_ecbdesc_t *edp, *last; 438*0Sstevel@tonic-gate const dtrace_probedesc_t *pdp; 439*0Sstevel@tonic-gate const dtrace_actdesc_t *ap; 440*0Sstevel@tonic-gate const dt_stmt_t *stp; 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate uint_t maxacts = 0; 443*0Sstevel@tonic-gate uint_t maxfmt = 0; 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate dt_provider_t *pvp; 446*0Sstevel@tonic-gate dof_actdesc_t *dofa; 447*0Sstevel@tonic-gate dof_sec_t *sp; 448*0Sstevel@tonic-gate size_t ssize, lsize; 449*0Sstevel@tonic-gate dof_hdr_t h; 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate dt_buf_t dof; 452*0Sstevel@tonic-gate char *fmt; 453*0Sstevel@tonic-gate uint_t i; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate if (flags & ~DTRACE_D_MASK) { 456*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EINVAL); 457*0Sstevel@tonic-gate return (NULL); 458*0Sstevel@tonic-gate } 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate flags |= dtp->dt_dflags; 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate if (dof_hdr(dtp, &h) != 0) 463*0Sstevel@tonic-gate return (NULL); 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate assert(ddo->ddo_hdl == dtp); 466*0Sstevel@tonic-gate dt_dof_reset(dtp); 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate /* 469*0Sstevel@tonic-gate * Iterate through the statement list computing the maximum number of 470*0Sstevel@tonic-gate * actions and the maximum format string for allocating local buffers. 471*0Sstevel@tonic-gate */ 472*0Sstevel@tonic-gate for (last = NULL, stp = dt_list_next(&pgp->dp_stmts); 473*0Sstevel@tonic-gate stp != NULL; stp = dt_list_next(stp), last = edp) { 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate dtrace_stmtdesc_t *sdp = stp->ds_desc; 476*0Sstevel@tonic-gate dtrace_actdesc_t *ap = sdp->dtsd_action; 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate if (sdp->dtsd_fmtdata != NULL) { 479*0Sstevel@tonic-gate i = dtrace_printf_format(dtp, 480*0Sstevel@tonic-gate sdp->dtsd_fmtdata, NULL, 0); 481*0Sstevel@tonic-gate maxfmt = MAX(maxfmt, i); 482*0Sstevel@tonic-gate } 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate if ((edp = sdp->dtsd_ecbdesc) == last) 485*0Sstevel@tonic-gate continue; /* same ecb as previous statement */ 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate for (i = 0, ap = edp->dted_action; ap; ap = ap->dtad_next) 488*0Sstevel@tonic-gate i++; 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate maxacts = MAX(maxacts, i); 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate dofa = alloca(sizeof (dof_actdesc_t) * maxacts); 494*0Sstevel@tonic-gate fmt = alloca(maxfmt + 1); 495*0Sstevel@tonic-gate 496*0Sstevel@tonic-gate ddo->ddo_strsec = dof_add_lsect(ddo, NULL, DOF_SECT_STRTAB, 1, 0, 0, 0); 497*0Sstevel@tonic-gate (void) dof_add_string(ddo, ""); 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate /* 500*0Sstevel@tonic-gate * Now iterate through the statement list, creating the DOF section 501*0Sstevel@tonic-gate * headers and data for each one and adding them to our buffers. 502*0Sstevel@tonic-gate */ 503*0Sstevel@tonic-gate for (last = NULL, stp = dt_list_next(&pgp->dp_stmts); 504*0Sstevel@tonic-gate stp != NULL; stp = dt_list_next(stp), last = edp) { 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate dof_secidx_t probesec = DOF_SECIDX_NONE; 507*0Sstevel@tonic-gate dof_secidx_t prdsec = DOF_SECIDX_NONE; 508*0Sstevel@tonic-gate dof_secidx_t actsec = DOF_SECIDX_NONE; 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate const dt_stmt_t *next = stp; 511*0Sstevel@tonic-gate dtrace_stmtdesc_t *sdp = stp->ds_desc; 512*0Sstevel@tonic-gate dof_stridx_t strndx = 0; 513*0Sstevel@tonic-gate dof_probedesc_t dofp; 514*0Sstevel@tonic-gate dof_ecbdesc_t dofe; 515*0Sstevel@tonic-gate uint_t i; 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate if ((edp = stp->ds_desc->dtsd_ecbdesc) == last) 518*0Sstevel@tonic-gate continue; /* same ecb as previous statement */ 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate pdp = &edp->dted_probe; 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate /* 523*0Sstevel@tonic-gate * Add a DOF_SECT_PROBEDESC for the ECB's probe description, 524*0Sstevel@tonic-gate * and copy the probe description strings into the string table. 525*0Sstevel@tonic-gate */ 526*0Sstevel@tonic-gate dofp.dofp_strtab = ddo->ddo_strsec; 527*0Sstevel@tonic-gate dofp.dofp_provider = dof_add_string(ddo, pdp->dtpd_provider); 528*0Sstevel@tonic-gate dofp.dofp_mod = dof_add_string(ddo, pdp->dtpd_mod); 529*0Sstevel@tonic-gate dofp.dofp_func = dof_add_string(ddo, pdp->dtpd_func); 530*0Sstevel@tonic-gate dofp.dofp_name = dof_add_string(ddo, pdp->dtpd_name); 531*0Sstevel@tonic-gate dofp.dofp_id = pdp->dtpd_id; 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate probesec = dof_add_lsect(ddo, &dofp, DOF_SECT_PROBEDESC, 534*0Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 535*0Sstevel@tonic-gate sizeof (dof_probedesc_t), sizeof (dof_probedesc_t)); 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate /* 538*0Sstevel@tonic-gate * If there is a predicate DIFO associated with the ecbdesc, 539*0Sstevel@tonic-gate * write out the DIFO sections and save the DIFO section index. 540*0Sstevel@tonic-gate */ 541*0Sstevel@tonic-gate if (edp->dted_pred.dtpdd_difo != NULL) 542*0Sstevel@tonic-gate prdsec = dof_add_difo(ddo, edp->dted_pred.dtpdd_difo); 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate /* 545*0Sstevel@tonic-gate * Now iterate through the action list generating DIFOs as 546*0Sstevel@tonic-gate * referenced therein and adding action descriptions to 'dofa'. 547*0Sstevel@tonic-gate */ 548*0Sstevel@tonic-gate for (i = 0, ap = edp->dted_action; 549*0Sstevel@tonic-gate ap != NULL; ap = ap->dtad_next, i++) { 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate if (ap->dtad_difo != NULL) { 552*0Sstevel@tonic-gate dofa[i].dofa_difo = 553*0Sstevel@tonic-gate dof_add_difo(ddo, ap->dtad_difo); 554*0Sstevel@tonic-gate } else 555*0Sstevel@tonic-gate dofa[i].dofa_difo = DOF_SECIDX_NONE; 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate /* 558*0Sstevel@tonic-gate * If the first action in a statement has format data, 559*0Sstevel@tonic-gate * add the format string to the global string table. 560*0Sstevel@tonic-gate */ 561*0Sstevel@tonic-gate if (sdp != NULL && ap == sdp->dtsd_action) { 562*0Sstevel@tonic-gate if (sdp->dtsd_fmtdata != NULL) { 563*0Sstevel@tonic-gate (void) dtrace_printf_format(dtp, 564*0Sstevel@tonic-gate sdp->dtsd_fmtdata, fmt, maxfmt + 1); 565*0Sstevel@tonic-gate strndx = dof_add_string(ddo, fmt); 566*0Sstevel@tonic-gate } else 567*0Sstevel@tonic-gate strndx = 0; /* use dtad_arg instead */ 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate if ((next = dt_list_next(next)) != NULL) 570*0Sstevel@tonic-gate sdp = next->ds_desc; 571*0Sstevel@tonic-gate else 572*0Sstevel@tonic-gate sdp = NULL; 573*0Sstevel@tonic-gate } 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate if (strndx != 0) { 576*0Sstevel@tonic-gate dofa[i].dofa_arg = strndx; 577*0Sstevel@tonic-gate dofa[i].dofa_strtab = ddo->ddo_strsec; 578*0Sstevel@tonic-gate } else { 579*0Sstevel@tonic-gate dofa[i].dofa_arg = ap->dtad_arg; 580*0Sstevel@tonic-gate dofa[i].dofa_strtab = DOF_SECIDX_NONE; 581*0Sstevel@tonic-gate } 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate dofa[i].dofa_kind = ap->dtad_kind; 584*0Sstevel@tonic-gate dofa[i].dofa_ntuple = ap->dtad_ntuple; 585*0Sstevel@tonic-gate dofa[i].dofa_uarg = ap->dtad_uarg; 586*0Sstevel@tonic-gate } 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate if (i > 0) { 589*0Sstevel@tonic-gate actsec = dof_add_lsect(ddo, dofa, DOF_SECT_ACTDESC, 590*0Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_actdesc_t), 591*0Sstevel@tonic-gate sizeof (dof_actdesc_t) * i); 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate /* 595*0Sstevel@tonic-gate * Now finally, add the DOF_SECT_ECBDESC referencing all the 596*0Sstevel@tonic-gate * previously created sub-sections. 597*0Sstevel@tonic-gate */ 598*0Sstevel@tonic-gate dofe.dofe_probes = probesec; 599*0Sstevel@tonic-gate dofe.dofe_pred = prdsec; 600*0Sstevel@tonic-gate dofe.dofe_actions = actsec; 601*0Sstevel@tonic-gate dofe.dofe_pad = 0; 602*0Sstevel@tonic-gate dofe.dofe_uarg = edp->dted_uarg; 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate (void) dof_add_lsect(ddo, &dofe, DOF_SECT_ECBDESC, 605*0Sstevel@tonic-gate sizeof (uint64_t), 0, 0, sizeof (dof_ecbdesc_t)); 606*0Sstevel@tonic-gate } 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate /* 609*0Sstevel@tonic-gate * If any providers are user-defined, output DOF sections corresponding 610*0Sstevel@tonic-gate * to the providers and the probes and arguments that they define. 611*0Sstevel@tonic-gate */ 612*0Sstevel@tonic-gate if (flags & DTRACE_D_PROBES) { 613*0Sstevel@tonic-gate for (pvp = dt_list_next(&dtp->dt_provlist); 614*0Sstevel@tonic-gate pvp != NULL; pvp = dt_list_next(pvp)) 615*0Sstevel@tonic-gate dof_add_provider(ddo, pvp); 616*0Sstevel@tonic-gate } 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate /* 619*0Sstevel@tonic-gate * If we're not stripping unloadable sections, generate compiler 620*0Sstevel@tonic-gate * comments and any other unloadable miscellany. 621*0Sstevel@tonic-gate */ 622*0Sstevel@tonic-gate if (!(flags & DTRACE_D_STRIP)) { 623*0Sstevel@tonic-gate (void) dof_add_usect(ddo, _dtrace_version, DOF_SECT_COMMENTS, 624*0Sstevel@tonic-gate sizeof (char), 0, 0, strlen(_dtrace_version) + 1); 625*0Sstevel@tonic-gate (void) dof_add_usect(ddo, &dtp->dt_uts, DOF_SECT_UTSNAME, 626*0Sstevel@tonic-gate sizeof (char), 0, 0, sizeof (struct utsname)); 627*0Sstevel@tonic-gate } 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate /* 630*0Sstevel@tonic-gate * Compute and fill in the appropriate values for the dof_hdr_t's 631*0Sstevel@tonic-gate * dofh_secnum, dofh_loadsz, and dofh_filez values. 632*0Sstevel@tonic-gate */ 633*0Sstevel@tonic-gate h.dofh_secnum = ddo->ddo_nsecs; 634*0Sstevel@tonic-gate ssize = sizeof (h) + dt_buf_len(&ddo->ddo_secs); 635*0Sstevel@tonic-gate assert(ssize == sizeof (h) + sizeof (dof_sec_t) * ddo->ddo_nsecs); 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate h.dofh_loadsz = ssize + 638*0Sstevel@tonic-gate dt_buf_len(&ddo->ddo_ldata) + 639*0Sstevel@tonic-gate dt_buf_len(&ddo->ddo_strs); 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate if (dt_buf_len(&ddo->ddo_udata) != 0) { 642*0Sstevel@tonic-gate lsize = roundup(h.dofh_loadsz, sizeof (uint64_t)); 643*0Sstevel@tonic-gate h.dofh_filesz = lsize + dt_buf_len(&ddo->ddo_udata); 644*0Sstevel@tonic-gate } else { 645*0Sstevel@tonic-gate lsize = h.dofh_loadsz; 646*0Sstevel@tonic-gate h.dofh_filesz = lsize; 647*0Sstevel@tonic-gate } 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate /* 650*0Sstevel@tonic-gate * Set the global DOF_SECT_STRTAB's offset to be after the header, 651*0Sstevel@tonic-gate * section headers, and other loadable data. Since we're going to 652*0Sstevel@tonic-gate * iterate over the buffer data directly, we must check for errors. 653*0Sstevel@tonic-gate */ 654*0Sstevel@tonic-gate if ((i = dt_buf_error(&ddo->ddo_secs)) != 0) { 655*0Sstevel@tonic-gate (void) dt_set_errno(dtp, i); 656*0Sstevel@tonic-gate return (NULL); 657*0Sstevel@tonic-gate } 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate sp = dt_buf_ptr(&ddo->ddo_secs); 660*0Sstevel@tonic-gate assert(sp[ddo->ddo_strsec].dofs_type == DOF_SECT_STRTAB); 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate sp[ddo->ddo_strsec].dofs_offset = ssize + dt_buf_len(&ddo->ddo_ldata); 663*0Sstevel@tonic-gate sp[ddo->ddo_strsec].dofs_size = dt_buf_len(&ddo->ddo_strs); 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate /* 666*0Sstevel@tonic-gate * Now relocate all the other section headers by adding the appropriate 667*0Sstevel@tonic-gate * delta to their respective dofs_offset values. 668*0Sstevel@tonic-gate */ 669*0Sstevel@tonic-gate for (i = 0; i < ddo->ddo_nsecs; i++, sp++) { 670*0Sstevel@tonic-gate if (i == ddo->ddo_strsec) 671*0Sstevel@tonic-gate continue; /* already relocated above */ 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate if (sp->dofs_flags & DOF_SECF_LOAD) 674*0Sstevel@tonic-gate sp->dofs_offset += ssize; 675*0Sstevel@tonic-gate else 676*0Sstevel@tonic-gate sp->dofs_offset += lsize; 677*0Sstevel@tonic-gate } 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate /* 680*0Sstevel@tonic-gate * Finally, assemble the complete in-memory DOF buffer by writing the 681*0Sstevel@tonic-gate * header and then concatenating all our buffers. dt_buf_concat() will 682*0Sstevel@tonic-gate * propagate any errors and cause dt_buf_claim() to return NULL. 683*0Sstevel@tonic-gate */ 684*0Sstevel@tonic-gate dt_buf_create(dtp, &dof, "dof", h.dofh_filesz); 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate dt_buf_write(dtp, &dof, &h, sizeof (h), sizeof (uint64_t)); 687*0Sstevel@tonic-gate dt_buf_concat(dtp, &dof, &ddo->ddo_secs, sizeof (uint64_t)); 688*0Sstevel@tonic-gate dt_buf_concat(dtp, &dof, &ddo->ddo_ldata, sizeof (uint64_t)); 689*0Sstevel@tonic-gate dt_buf_concat(dtp, &dof, &ddo->ddo_strs, sizeof (char)); 690*0Sstevel@tonic-gate dt_buf_concat(dtp, &dof, &ddo->ddo_udata, sizeof (uint64_t)); 691*0Sstevel@tonic-gate 692*0Sstevel@tonic-gate return (dt_buf_claim(dtp, &dof)); 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate void 696*0Sstevel@tonic-gate dtrace_dof_destroy(dtrace_hdl_t *dtp, void *dof) 697*0Sstevel@tonic-gate { 698*0Sstevel@tonic-gate dt_free(dtp, dof); 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate void * 702*0Sstevel@tonic-gate dtrace_getopt_dof(dtrace_hdl_t *dtp) 703*0Sstevel@tonic-gate { 704*0Sstevel@tonic-gate dof_hdr_t *dof; 705*0Sstevel@tonic-gate dof_sec_t *sec; 706*0Sstevel@tonic-gate dof_optdesc_t *dofo; 707*0Sstevel@tonic-gate int i, nopts = 0, len = sizeof (dof_hdr_t) + 708*0Sstevel@tonic-gate roundup(sizeof (dof_sec_t), sizeof (uint64_t)); 709*0Sstevel@tonic-gate 710*0Sstevel@tonic-gate for (i = 0; i < DTRACEOPT_MAX; i++) { 711*0Sstevel@tonic-gate if (dtp->dt_options[i] != DTRACEOPT_UNSET) 712*0Sstevel@tonic-gate nopts++; 713*0Sstevel@tonic-gate } 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate len += sizeof (dof_optdesc_t) * nopts; 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate if ((dof = dt_zalloc(dtp, len)) == NULL || dof_hdr(dtp, dof) != 0) { 718*0Sstevel@tonic-gate dt_free(dtp, dof); 719*0Sstevel@tonic-gate return (NULL); 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate dof->dofh_secnum = 1; /* only DOF_SECT_OPTDESC */ 723*0Sstevel@tonic-gate dof->dofh_loadsz = len; 724*0Sstevel@tonic-gate dof->dofh_filesz = len; 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate /* 727*0Sstevel@tonic-gate * Fill in the option section header... 728*0Sstevel@tonic-gate */ 729*0Sstevel@tonic-gate sec = (dof_sec_t *)((uintptr_t)dof + sizeof (dof_hdr_t)); 730*0Sstevel@tonic-gate sec->dofs_type = DOF_SECT_OPTDESC; 731*0Sstevel@tonic-gate sec->dofs_align = sizeof (uint64_t); 732*0Sstevel@tonic-gate sec->dofs_flags = DOF_SECF_LOAD; 733*0Sstevel@tonic-gate sec->dofs_entsize = sizeof (dof_optdesc_t); 734*0Sstevel@tonic-gate 735*0Sstevel@tonic-gate dofo = (dof_optdesc_t *)((uintptr_t)sec + 736*0Sstevel@tonic-gate roundup(sizeof (dof_sec_t), sizeof (uint64_t))); 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate sec->dofs_offset = (uintptr_t)dofo - (uintptr_t)dof; 739*0Sstevel@tonic-gate sec->dofs_size = sizeof (dof_optdesc_t) * nopts; 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate for (i = 0; i < DTRACEOPT_MAX; i++) { 742*0Sstevel@tonic-gate if (dtp->dt_options[i] == DTRACEOPT_UNSET) 743*0Sstevel@tonic-gate continue; 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate dofo->dofo_option = i; 746*0Sstevel@tonic-gate dofo->dofo_strtab = DOF_SECIDX_NONE; 747*0Sstevel@tonic-gate dofo->dofo_value = dtp->dt_options[i]; 748*0Sstevel@tonic-gate dofo++; 749*0Sstevel@tonic-gate } 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate return (dof); 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate void * 755*0Sstevel@tonic-gate dtrace_geterr_dof(dtrace_hdl_t *dtp) 756*0Sstevel@tonic-gate { 757*0Sstevel@tonic-gate if (dtp->dt_errprog != NULL) 758*0Sstevel@tonic-gate return (dtrace_dof_create(dtp, dtp->dt_errprog, 0)); 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_BADERROR); 761*0Sstevel@tonic-gate return (NULL); 762*0Sstevel@tonic-gate } 763