1178479Sjb/* 2178479Sjb * CDDL HEADER START 3178479Sjb * 4178479Sjb * The contents of this file are subject to the terms of the 5178479Sjb * Common Development and Distribution License (the "License"). 6178479Sjb * You may not use this file except in compliance with the License. 7178479Sjb * 8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9178479Sjb * or http://www.opensolaris.org/os/licensing. 10178479Sjb * See the License for the specific language governing permissions 11178479Sjb * and limitations under the License. 12178479Sjb * 13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each 14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15178479Sjb * If applicable, add the following below this CDDL HEADER, with the 16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18178479Sjb * 19178479Sjb * CDDL HEADER END 20178479Sjb */ 21178479Sjb 22178479Sjb/* 23210767Srpaulo * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24248708Spfg * Copyright (c) 2011 by Delphix. All rights reserved. 25265234Spfg * Copyright (c) 2013, Joyent, Inc. All rights reserved. 26178479Sjb */ 27178479Sjb 28178479Sjb#include <sys/types.h> 29178574Sjb#if defined(sun) 30178479Sjb#include <sys/sysmacros.h> 31178574Sjb#endif 32178479Sjb 33178479Sjb#include <strings.h> 34178574Sjb#if defined(sun) 35178479Sjb#include <alloca.h> 36178574Sjb#endif 37178479Sjb#include <assert.h> 38178479Sjb#include <stdlib.h> 39178479Sjb#include <errno.h> 40178479Sjb#include <limits.h> 41178479Sjb 42178479Sjb#include <dt_impl.h> 43178479Sjb#include <dt_strtab.h> 44178479Sjb#include <dt_program.h> 45178479Sjb#include <dt_provider.h> 46178479Sjb#include <dt_xlator.h> 47178479Sjb#include <dt_dof.h> 48178479Sjb 49178479Sjbvoid 50178479Sjbdt_dof_init(dtrace_hdl_t *dtp) 51178479Sjb{ 52178479Sjb dt_dof_t *ddo = &dtp->dt_dof; 53178479Sjb 54178479Sjb ddo->ddo_hdl = dtp; 55178479Sjb ddo->ddo_nsecs = 0; 56178479Sjb ddo->ddo_strsec = DOF_SECIDX_NONE; 57178479Sjb ddo->ddo_xlimport = NULL; 58178479Sjb ddo->ddo_xlexport = NULL; 59178479Sjb 60178479Sjb dt_buf_create(dtp, &ddo->ddo_secs, "section headers", 0); 61178479Sjb dt_buf_create(dtp, &ddo->ddo_strs, "string table", 0); 62178479Sjb dt_buf_create(dtp, &ddo->ddo_ldata, "loadable data", 0); 63178479Sjb dt_buf_create(dtp, &ddo->ddo_udata, "unloadable data", 0); 64178479Sjb 65178479Sjb dt_buf_create(dtp, &ddo->ddo_probes, "probe data", 0); 66178479Sjb dt_buf_create(dtp, &ddo->ddo_args, "probe args", 0); 67178479Sjb dt_buf_create(dtp, &ddo->ddo_offs, "probe offs", 0); 68178479Sjb dt_buf_create(dtp, &ddo->ddo_enoffs, "probe is-enabled offs", 0); 69178479Sjb dt_buf_create(dtp, &ddo->ddo_rels, "probe rels", 0); 70178479Sjb 71178479Sjb dt_buf_create(dtp, &ddo->ddo_xlms, "xlate members", 0); 72178479Sjb} 73178479Sjb 74178479Sjbvoid 75178479Sjbdt_dof_fini(dtrace_hdl_t *dtp) 76178479Sjb{ 77178479Sjb dt_dof_t *ddo = &dtp->dt_dof; 78178479Sjb 79178479Sjb dt_free(dtp, ddo->ddo_xlimport); 80178479Sjb dt_free(dtp, ddo->ddo_xlexport); 81178479Sjb 82178479Sjb dt_buf_destroy(dtp, &ddo->ddo_secs); 83178479Sjb dt_buf_destroy(dtp, &ddo->ddo_strs); 84178479Sjb dt_buf_destroy(dtp, &ddo->ddo_ldata); 85178479Sjb dt_buf_destroy(dtp, &ddo->ddo_udata); 86178479Sjb 87178479Sjb dt_buf_destroy(dtp, &ddo->ddo_probes); 88178479Sjb dt_buf_destroy(dtp, &ddo->ddo_args); 89178479Sjb dt_buf_destroy(dtp, &ddo->ddo_offs); 90178479Sjb dt_buf_destroy(dtp, &ddo->ddo_enoffs); 91178479Sjb dt_buf_destroy(dtp, &ddo->ddo_rels); 92178479Sjb 93178479Sjb dt_buf_destroy(dtp, &ddo->ddo_xlms); 94178479Sjb} 95178479Sjb 96178479Sjbstatic int 97178479Sjbdt_dof_reset(dtrace_hdl_t *dtp, dtrace_prog_t *pgp) 98178479Sjb{ 99178479Sjb dt_dof_t *ddo = &dtp->dt_dof; 100178479Sjb uint_t i, nx = dtp->dt_xlatorid; 101178479Sjb 102178479Sjb assert(ddo->ddo_hdl == dtp); 103178479Sjb ddo->ddo_pgp = pgp; 104178479Sjb 105178479Sjb ddo->ddo_nsecs = 0; 106178479Sjb ddo->ddo_strsec = DOF_SECIDX_NONE; 107178479Sjb 108178479Sjb dt_free(dtp, ddo->ddo_xlimport); 109178479Sjb dt_free(dtp, ddo->ddo_xlexport); 110178479Sjb 111178479Sjb ddo->ddo_xlimport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx); 112178479Sjb ddo->ddo_xlexport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx); 113178479Sjb 114178479Sjb if (nx != 0 && (ddo->ddo_xlimport == NULL || ddo->ddo_xlexport == NULL)) 115178479Sjb return (-1); /* errno is set for us */ 116178479Sjb 117178479Sjb for (i = 0; i < nx; i++) { 118178479Sjb ddo->ddo_xlimport[i] = DOF_SECIDX_NONE; 119178479Sjb ddo->ddo_xlexport[i] = DOF_SECIDX_NONE; 120178479Sjb } 121178479Sjb 122178479Sjb dt_buf_reset(dtp, &ddo->ddo_secs); 123178479Sjb dt_buf_reset(dtp, &ddo->ddo_strs); 124178479Sjb dt_buf_reset(dtp, &ddo->ddo_ldata); 125178479Sjb dt_buf_reset(dtp, &ddo->ddo_udata); 126178479Sjb 127178479Sjb dt_buf_reset(dtp, &ddo->ddo_probes); 128178479Sjb dt_buf_reset(dtp, &ddo->ddo_args); 129178479Sjb dt_buf_reset(dtp, &ddo->ddo_offs); 130178479Sjb dt_buf_reset(dtp, &ddo->ddo_enoffs); 131178479Sjb dt_buf_reset(dtp, &ddo->ddo_rels); 132178479Sjb 133178479Sjb dt_buf_reset(dtp, &ddo->ddo_xlms); 134178479Sjb return (0); 135178479Sjb} 136178479Sjb 137178479Sjb/* 138178479Sjb * Add a loadable DOF section to the file using the specified data buffer and 139178479Sjb * the specified DOF section attributes. DOF_SECF_LOAD must be set in flags. 140178479Sjb * If 'data' is NULL, the caller is responsible for manipulating the ldata buf. 141178479Sjb */ 142178479Sjbstatic dof_secidx_t 143178479Sjbdof_add_lsect(dt_dof_t *ddo, const void *data, uint32_t type, 144178479Sjb uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size) 145178479Sjb{ 146178479Sjb dtrace_hdl_t *dtp = ddo->ddo_hdl; 147178479Sjb dof_sec_t s; 148178479Sjb 149178479Sjb s.dofs_type = type; 150178479Sjb s.dofs_align = align; 151178479Sjb s.dofs_flags = flags | DOF_SECF_LOAD; 152178479Sjb s.dofs_entsize = entsize; 153178479Sjb s.dofs_offset = dt_buf_offset(&ddo->ddo_ldata, align); 154178479Sjb s.dofs_size = size; 155178479Sjb 156178479Sjb dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t)); 157178479Sjb 158178479Sjb if (data != NULL) 159178479Sjb dt_buf_write(dtp, &ddo->ddo_ldata, data, size, align); 160178479Sjb 161178479Sjb return (ddo->ddo_nsecs++); 162178479Sjb} 163178479Sjb 164178479Sjb/* 165178479Sjb * Add an unloadable DOF section to the file using the specified data buffer 166178479Sjb * and DOF section attributes. DOF_SECF_LOAD must *not* be set in flags. 167178479Sjb * If 'data' is NULL, the caller is responsible for manipulating the udata buf. 168178479Sjb */ 169178479Sjbstatic dof_secidx_t 170178479Sjbdof_add_usect(dt_dof_t *ddo, const void *data, uint32_t type, 171178479Sjb uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size) 172178479Sjb{ 173178479Sjb dtrace_hdl_t *dtp = ddo->ddo_hdl; 174178479Sjb dof_sec_t s; 175178479Sjb 176178479Sjb s.dofs_type = type; 177178479Sjb s.dofs_align = align; 178178479Sjb s.dofs_flags = flags & ~DOF_SECF_LOAD; 179178479Sjb s.dofs_entsize = entsize; 180178479Sjb s.dofs_offset = dt_buf_offset(&ddo->ddo_udata, align); 181178479Sjb s.dofs_size = size; 182178479Sjb 183178479Sjb dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t)); 184178479Sjb 185178479Sjb if (data != NULL) 186178479Sjb dt_buf_write(dtp, &ddo->ddo_udata, data, size, align); 187178479Sjb 188178479Sjb return (ddo->ddo_nsecs++); 189178479Sjb} 190178479Sjb 191178479Sjb/* 192178479Sjb * Add a string to the global string table associated with the DOF. The offset 193178479Sjb * of the string is returned as an index into the string table. 194178479Sjb */ 195178479Sjbstatic dof_stridx_t 196178479Sjbdof_add_string(dt_dof_t *ddo, const char *s) 197178479Sjb{ 198178479Sjb dt_buf_t *bp = &ddo->ddo_strs; 199178479Sjb dof_stridx_t i = dt_buf_len(bp); 200178479Sjb 201178479Sjb if (i != 0 && (s == NULL || *s == '\0')) 202178479Sjb return (0); /* string table has \0 at offset 0 */ 203178479Sjb 204178479Sjb dt_buf_write(ddo->ddo_hdl, bp, s, strlen(s) + 1, sizeof (char)); 205178479Sjb return (i); 206178479Sjb} 207178479Sjb 208178479Sjbstatic dof_attr_t 209178479Sjbdof_attr(const dtrace_attribute_t *ap) 210178479Sjb{ 211178479Sjb return (DOF_ATTR(ap->dtat_name, ap->dtat_data, ap->dtat_class)); 212178479Sjb} 213178479Sjb 214178479Sjbstatic dof_secidx_t 215178479Sjbdof_add_difo(dt_dof_t *ddo, const dtrace_difo_t *dp) 216178479Sjb{ 217178479Sjb dof_secidx_t dsecs[5]; /* enough for all possible DIFO sections */ 218178479Sjb uint_t nsecs = 0; 219178479Sjb 220178479Sjb dof_difohdr_t *dofd; 221178479Sjb dof_relohdr_t dofr; 222178479Sjb dof_secidx_t relsec; 223178479Sjb 224178479Sjb dof_secidx_t strsec = DOF_SECIDX_NONE; 225178479Sjb dof_secidx_t intsec = DOF_SECIDX_NONE; 226178479Sjb dof_secidx_t hdrsec = DOF_SECIDX_NONE; 227178479Sjb 228178479Sjb if (dp->dtdo_buf != NULL) { 229178479Sjb dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_buf, 230178479Sjb DOF_SECT_DIF, sizeof (dif_instr_t), 0, 231178479Sjb sizeof (dif_instr_t), sizeof (dif_instr_t) * dp->dtdo_len); 232178479Sjb } 233178479Sjb 234178479Sjb if (dp->dtdo_inttab != NULL) { 235178479Sjb dsecs[nsecs++] = intsec = dof_add_lsect(ddo, dp->dtdo_inttab, 236178479Sjb DOF_SECT_INTTAB, sizeof (uint64_t), 0, 237178479Sjb sizeof (uint64_t), sizeof (uint64_t) * dp->dtdo_intlen); 238178479Sjb } 239178479Sjb 240178479Sjb if (dp->dtdo_strtab != NULL) { 241178479Sjb dsecs[nsecs++] = strsec = dof_add_lsect(ddo, dp->dtdo_strtab, 242178479Sjb DOF_SECT_STRTAB, sizeof (char), 0, 0, dp->dtdo_strlen); 243178479Sjb } 244178479Sjb 245178479Sjb if (dp->dtdo_vartab != NULL) { 246178479Sjb dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_vartab, 247178479Sjb DOF_SECT_VARTAB, sizeof (uint_t), 0, sizeof (dtrace_difv_t), 248178479Sjb sizeof (dtrace_difv_t) * dp->dtdo_varlen); 249178479Sjb } 250178479Sjb 251178479Sjb if (dp->dtdo_xlmtab != NULL) { 252178479Sjb dof_xlref_t *xlt, *xlp; 253178479Sjb dt_node_t **pnp; 254178479Sjb 255178479Sjb xlt = alloca(sizeof (dof_xlref_t) * dp->dtdo_xlmlen); 256178479Sjb pnp = dp->dtdo_xlmtab; 257178479Sjb 258178479Sjb /* 259178479Sjb * dtdo_xlmtab contains pointers to the translator members. 260178479Sjb * The translator itself is in sect ddo_xlimport[dxp->dx_id]. 261178479Sjb * The XLMEMBERS entries are in order by their dn_membid, so 262178479Sjb * the member section offset is the population count of bits 263178479Sjb * in ddo_pgp->dp_xlrefs[] up to and not including dn_membid. 264178479Sjb */ 265178479Sjb for (xlp = xlt; xlp < xlt + dp->dtdo_xlmlen; xlp++) { 266178479Sjb dt_node_t *dnp = *pnp++; 267178479Sjb dt_xlator_t *dxp = dnp->dn_membexpr->dn_xlator; 268178479Sjb 269178479Sjb xlp->dofxr_xlator = ddo->ddo_xlimport[dxp->dx_id]; 270178479Sjb xlp->dofxr_member = dt_popcb( 271178479Sjb ddo->ddo_pgp->dp_xrefs[dxp->dx_id], dnp->dn_membid); 272178479Sjb xlp->dofxr_argn = (uint32_t)dxp->dx_arg; 273178479Sjb } 274178479Sjb 275178479Sjb dsecs[nsecs++] = dof_add_lsect(ddo, xlt, DOF_SECT_XLTAB, 276178479Sjb sizeof (dof_secidx_t), 0, sizeof (dof_xlref_t), 277178479Sjb sizeof (dof_xlref_t) * dp->dtdo_xlmlen); 278178479Sjb } 279178479Sjb 280178479Sjb /* 281178479Sjb * Copy the return type and the array of section indices that form the 282178479Sjb * DIFO into a single dof_difohdr_t and then add DOF_SECT_DIFOHDR. 283178479Sjb */ 284178479Sjb assert(nsecs <= sizeof (dsecs) / sizeof (dsecs[0])); 285178479Sjb dofd = alloca(sizeof (dtrace_diftype_t) + sizeof (dsecs)); 286178479Sjb bcopy(&dp->dtdo_rtype, &dofd->dofd_rtype, sizeof (dtrace_diftype_t)); 287178479Sjb bcopy(dsecs, &dofd->dofd_links, sizeof (dof_secidx_t) * nsecs); 288178479Sjb 289178479Sjb hdrsec = dof_add_lsect(ddo, dofd, DOF_SECT_DIFOHDR, 290178479Sjb sizeof (dof_secidx_t), 0, 0, 291178479Sjb sizeof (dtrace_diftype_t) + sizeof (dof_secidx_t) * nsecs); 292178479Sjb 293178479Sjb /* 294178479Sjb * Add any other sections related to dtrace_difo_t. These are not 295178479Sjb * referenced in dof_difohdr_t because they are not used by emulation. 296178479Sjb */ 297178479Sjb if (dp->dtdo_kreltab != NULL) { 298178479Sjb relsec = dof_add_lsect(ddo, dp->dtdo_kreltab, DOF_SECT_RELTAB, 299178479Sjb sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 300178479Sjb sizeof (dof_relodesc_t) * dp->dtdo_krelen); 301178479Sjb 302178479Sjb /* 303178479Sjb * This code assumes the target of all relocations is the 304178479Sjb * integer table 'intsec' (DOF_SECT_INTTAB). If other sections 305178479Sjb * need relocation in the future this will need to change. 306178479Sjb */ 307178479Sjb dofr.dofr_strtab = strsec; 308178479Sjb dofr.dofr_relsec = relsec; 309178479Sjb dofr.dofr_tgtsec = intsec; 310178479Sjb 311178479Sjb (void) dof_add_lsect(ddo, &dofr, DOF_SECT_KRELHDR, 312178479Sjb sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 313178479Sjb } 314178479Sjb 315178479Sjb if (dp->dtdo_ureltab != NULL) { 316178479Sjb relsec = dof_add_lsect(ddo, dp->dtdo_ureltab, DOF_SECT_RELTAB, 317178479Sjb sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 318178479Sjb sizeof (dof_relodesc_t) * dp->dtdo_urelen); 319178479Sjb 320178479Sjb /* 321178479Sjb * This code assumes the target of all relocations is the 322178479Sjb * integer table 'intsec' (DOF_SECT_INTTAB). If other sections 323178479Sjb * need relocation in the future this will need to change. 324178479Sjb */ 325178479Sjb dofr.dofr_strtab = strsec; 326178479Sjb dofr.dofr_relsec = relsec; 327178479Sjb dofr.dofr_tgtsec = intsec; 328178479Sjb 329178479Sjb (void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR, 330178479Sjb sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 331178479Sjb } 332178479Sjb 333178479Sjb return (hdrsec); 334178479Sjb} 335178479Sjb 336178479Sjbstatic void 337178479Sjbdof_add_translator(dt_dof_t *ddo, const dt_xlator_t *dxp, uint_t type) 338178479Sjb{ 339178479Sjb dtrace_hdl_t *dtp = ddo->ddo_hdl; 340178479Sjb dof_xlmember_t dofxm; 341178479Sjb dof_xlator_t dofxl; 342178479Sjb dof_secidx_t *xst; 343178479Sjb 344178479Sjb char buf[DT_TYPE_NAMELEN]; 345178479Sjb dt_node_t *dnp; 346178479Sjb uint_t i = 0; 347178479Sjb 348178479Sjb assert(type == DOF_SECT_XLIMPORT || type == DOF_SECT_XLEXPORT); 349178479Sjb xst = type == DOF_SECT_XLIMPORT ? ddo->ddo_xlimport : ddo->ddo_xlexport; 350178479Sjb 351178479Sjb if (xst[dxp->dx_id] != DOF_SECIDX_NONE) 352178479Sjb return; /* translator has already been emitted */ 353178479Sjb 354178479Sjb dt_buf_reset(dtp, &ddo->ddo_xlms); 355178479Sjb 356178479Sjb /* 357178479Sjb * Generate an array of dof_xlmember_t's into ddo_xlms. If we are 358178479Sjb * importing the translator, add only those members referenced by the 359178479Sjb * program and set the dofxm_difo reference of each member to NONE. If 360178479Sjb * we're exporting the translator, add all members and a DIFO for each. 361178479Sjb */ 362178479Sjb for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list, i++) { 363178479Sjb if (type == DOF_SECT_XLIMPORT) { 364178479Sjb if (!BT_TEST(ddo->ddo_pgp->dp_xrefs[dxp->dx_id], i)) 365178479Sjb continue; /* member is not referenced */ 366178479Sjb dofxm.dofxm_difo = DOF_SECIDX_NONE; 367178479Sjb } else { 368178479Sjb dofxm.dofxm_difo = dof_add_difo(ddo, 369178479Sjb dxp->dx_membdif[dnp->dn_membid]); 370178479Sjb } 371178479Sjb 372178479Sjb dofxm.dofxm_name = dof_add_string(ddo, dnp->dn_membname); 373178479Sjb dt_node_diftype(dtp, dnp, &dofxm.dofxm_type); 374178479Sjb 375178479Sjb dt_buf_write(dtp, &ddo->ddo_xlms, 376178479Sjb &dofxm, sizeof (dofxm), sizeof (uint32_t)); 377178479Sjb } 378178479Sjb 379178479Sjb dofxl.dofxl_members = dof_add_lsect(ddo, NULL, DOF_SECT_XLMEMBERS, 380178479Sjb sizeof (uint32_t), 0, sizeof (dofxm), dt_buf_len(&ddo->ddo_xlms)); 381178479Sjb 382178479Sjb dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_xlms, sizeof (uint32_t)); 383178479Sjb 384178479Sjb dofxl.dofxl_strtab = ddo->ddo_strsec; 385178479Sjb dofxl.dofxl_argv = dof_add_string(ddo, ctf_type_name( 386178479Sjb dxp->dx_src_ctfp, dxp->dx_src_type, buf, sizeof (buf))); 387178479Sjb dofxl.dofxl_argc = 1; 388178479Sjb dofxl.dofxl_type = dof_add_string(ddo, ctf_type_name( 389178479Sjb dxp->dx_dst_ctfp, dxp->dx_dst_type, buf, sizeof (buf))); 390178479Sjb dofxl.dofxl_attr = dof_attr(&dxp->dx_souid.di_attr); 391178479Sjb 392178479Sjb xst[dxp->dx_id] = dof_add_lsect(ddo, &dofxl, type, 393178479Sjb sizeof (uint32_t), 0, 0, sizeof (dofxl)); 394178479Sjb} 395178479Sjb 396178479Sjb/*ARGSUSED*/ 397178479Sjbstatic int 398178479Sjbdof_add_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 399178479Sjb{ 400178479Sjb dt_dof_t *ddo = data; 401178479Sjb dtrace_hdl_t *dtp = ddo->ddo_hdl; 402178479Sjb dt_probe_t *prp = idp->di_data; 403178479Sjb 404178479Sjb dof_probe_t dofpr; 405178479Sjb dof_relodesc_t dofr; 406178479Sjb dt_probe_instance_t *pip; 407178479Sjb dt_node_t *dnp; 408178479Sjb 409178479Sjb char buf[DT_TYPE_NAMELEN]; 410178479Sjb uint_t i; 411178479Sjb 412178479Sjb dofpr.dofpr_addr = 0; 413178479Sjb dofpr.dofpr_name = dof_add_string(ddo, prp->pr_name); 414178479Sjb dofpr.dofpr_nargv = dt_buf_len(&ddo->ddo_strs); 415178479Sjb 416178479Sjb for (dnp = prp->pr_nargs; dnp != NULL; dnp = dnp->dn_list) { 417178479Sjb (void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp, 418178479Sjb dnp->dn_type, buf, sizeof (buf))); 419178479Sjb } 420178479Sjb 421178479Sjb dofpr.dofpr_xargv = dt_buf_len(&ddo->ddo_strs); 422178479Sjb 423178479Sjb for (dnp = prp->pr_xargs; dnp != NULL; dnp = dnp->dn_list) { 424178479Sjb (void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp, 425178479Sjb dnp->dn_type, buf, sizeof (buf))); 426178479Sjb } 427178479Sjb 428178479Sjb dofpr.dofpr_argidx = dt_buf_len(&ddo->ddo_args) / sizeof (uint8_t); 429178479Sjb 430178479Sjb for (i = 0; i < prp->pr_xargc; i++) { 431178479Sjb dt_buf_write(dtp, &ddo->ddo_args, &prp->pr_mapping[i], 432178479Sjb sizeof (uint8_t), sizeof (uint8_t)); 433178479Sjb } 434178479Sjb 435178479Sjb dofpr.dofpr_nargc = prp->pr_nargc; 436178479Sjb dofpr.dofpr_xargc = prp->pr_xargc; 437178479Sjb dofpr.dofpr_pad1 = 0; 438178479Sjb dofpr.dofpr_pad2 = 0; 439178479Sjb 440178479Sjb for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) { 441178479Sjb dt_dprintf("adding probe for %s:%s\n", pip->pi_fname, 442178479Sjb prp->pr_name); 443178479Sjb 444178479Sjb dofpr.dofpr_func = dof_add_string(ddo, pip->pi_fname); 445178479Sjb 446178479Sjb /* 447178479Sjb * There should be one probe offset or is-enabled probe offset 448178479Sjb * or else this probe instance won't have been created. The 449178479Sjb * kernel will reject DOF which has a probe with no offsets. 450178479Sjb */ 451178479Sjb assert(pip->pi_noffs + pip->pi_nenoffs > 0); 452178479Sjb 453178479Sjb dofpr.dofpr_offidx = 454178479Sjb dt_buf_len(&ddo->ddo_offs) / sizeof (uint32_t); 455178479Sjb dofpr.dofpr_noffs = pip->pi_noffs; 456178479Sjb dt_buf_write(dtp, &ddo->ddo_offs, pip->pi_offs, 457178479Sjb pip->pi_noffs * sizeof (uint32_t), sizeof (uint32_t)); 458178479Sjb 459178479Sjb dofpr.dofpr_enoffidx = 460178479Sjb dt_buf_len(&ddo->ddo_enoffs) / sizeof (uint32_t); 461178479Sjb dofpr.dofpr_nenoffs = pip->pi_nenoffs; 462178479Sjb dt_buf_write(dtp, &ddo->ddo_enoffs, pip->pi_enoffs, 463178479Sjb pip->pi_nenoffs * sizeof (uint32_t), sizeof (uint32_t)); 464178479Sjb 465178479Sjb /* 466178479Sjb * If pi_rname isn't set, the relocation will be against the 467178479Sjb * function name. If it is, the relocation will be against 468178479Sjb * pi_rname. This will be used if the function is scoped 469178479Sjb * locally so an alternate symbol is added for the purpose 470178479Sjb * of this relocation. 471178479Sjb */ 472178479Sjb if (pip->pi_rname[0] == '\0') 473178479Sjb dofr.dofr_name = dofpr.dofpr_func; 474178479Sjb else 475178479Sjb dofr.dofr_name = dof_add_string(ddo, pip->pi_rname); 476178479Sjb dofr.dofr_type = DOF_RELO_SETX; 477178479Sjb dofr.dofr_offset = dt_buf_len(&ddo->ddo_probes); 478178479Sjb dofr.dofr_data = 0; 479178479Sjb 480178479Sjb dt_buf_write(dtp, &ddo->ddo_rels, &dofr, 481178479Sjb sizeof (dofr), sizeof (uint64_t)); 482178479Sjb 483178479Sjb dt_buf_write(dtp, &ddo->ddo_probes, &dofpr, 484178479Sjb sizeof (dofpr), sizeof (uint64_t)); 485178479Sjb } 486178479Sjb 487178479Sjb return (0); 488178479Sjb} 489178479Sjb 490265234Spfgstatic int 491178479Sjbdof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp) 492178479Sjb{ 493178479Sjb dtrace_hdl_t *dtp = ddo->ddo_hdl; 494178479Sjb dof_provider_t dofpv; 495178479Sjb dof_relohdr_t dofr; 496178479Sjb dof_secidx_t *dofs; 497178479Sjb ulong_t xr, nxr; 498178479Sjb size_t sz; 499178479Sjb id_t i; 500178479Sjb 501265234Spfg if (pvp->pv_flags & DT_PROVIDER_IMPL) { 502265234Spfg /* 503265234Spfg * ignore providers that are exported by dtrace(7D) 504265234Spfg */ 505265234Spfg return (0); 506265234Spfg } 507178479Sjb 508178479Sjb nxr = dt_popcb(pvp->pv_xrefs, pvp->pv_xrmax); 509178479Sjb dofs = alloca(sizeof (dof_secidx_t) * (nxr + 1)); 510178479Sjb xr = 1; /* reserve dofs[0] for the provider itself */ 511178479Sjb 512178479Sjb /* 513178479Sjb * For each translator referenced by the provider (pv_xrefs), emit an 514178479Sjb * exported translator section for it if one hasn't been created yet. 515178479Sjb */ 516178479Sjb for (i = 0; i < pvp->pv_xrmax; i++) { 517178479Sjb if (BT_TEST(pvp->pv_xrefs, i) && 518178479Sjb dtp->dt_xlatemode == DT_XL_DYNAMIC) { 519178479Sjb dof_add_translator(ddo, 520178479Sjb dt_xlator_lookup_id(dtp, i), DOF_SECT_XLEXPORT); 521178479Sjb dofs[xr++] = ddo->ddo_xlexport[i]; 522178479Sjb } 523178479Sjb } 524178479Sjb 525178479Sjb dt_buf_reset(dtp, &ddo->ddo_probes); 526178479Sjb dt_buf_reset(dtp, &ddo->ddo_args); 527178479Sjb dt_buf_reset(dtp, &ddo->ddo_offs); 528178479Sjb dt_buf_reset(dtp, &ddo->ddo_enoffs); 529178479Sjb dt_buf_reset(dtp, &ddo->ddo_rels); 530178479Sjb 531178479Sjb (void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo); 532178479Sjb 533265234Spfg if (dt_buf_len(&ddo->ddo_probes) == 0) 534265234Spfg return (dt_set_errno(dtp, EDT_NOPROBES)); 535265234Spfg 536178479Sjb dofpv.dofpv_probes = dof_add_lsect(ddo, NULL, DOF_SECT_PROBES, 537178479Sjb sizeof (uint64_t), 0, sizeof (dof_probe_t), 538178479Sjb dt_buf_len(&ddo->ddo_probes)); 539178479Sjb 540178479Sjb dt_buf_concat(dtp, &ddo->ddo_ldata, 541178479Sjb &ddo->ddo_probes, sizeof (uint64_t)); 542178479Sjb 543178479Sjb dofpv.dofpv_prargs = dof_add_lsect(ddo, NULL, DOF_SECT_PRARGS, 544178479Sjb sizeof (uint8_t), 0, sizeof (uint8_t), dt_buf_len(&ddo->ddo_args)); 545178479Sjb 546178479Sjb dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_args, sizeof (uint8_t)); 547178479Sjb 548178479Sjb dofpv.dofpv_proffs = dof_add_lsect(ddo, NULL, DOF_SECT_PROFFS, 549178479Sjb sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_offs)); 550178479Sjb 551178479Sjb dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_offs, sizeof (uint_t)); 552178479Sjb 553178479Sjb if ((sz = dt_buf_len(&ddo->ddo_enoffs)) != 0) { 554178479Sjb dofpv.dofpv_prenoffs = dof_add_lsect(ddo, NULL, 555178479Sjb DOF_SECT_PRENOFFS, sizeof (uint_t), 0, sizeof (uint_t), sz); 556178479Sjb } else { 557178479Sjb dofpv.dofpv_prenoffs = DOF_SECT_NONE; 558178479Sjb } 559178479Sjb 560178479Sjb dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_enoffs, sizeof (uint_t)); 561178479Sjb 562178479Sjb dofpv.dofpv_strtab = ddo->ddo_strsec; 563178479Sjb dofpv.dofpv_name = dof_add_string(ddo, pvp->pv_desc.dtvd_name); 564178479Sjb 565178479Sjb dofpv.dofpv_provattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_provider); 566178479Sjb dofpv.dofpv_modattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_mod); 567178479Sjb dofpv.dofpv_funcattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_func); 568178479Sjb dofpv.dofpv_nameattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_name); 569178479Sjb dofpv.dofpv_argsattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_args); 570178479Sjb 571178479Sjb dofs[0] = dof_add_lsect(ddo, &dofpv, DOF_SECT_PROVIDER, 572178479Sjb sizeof (dof_secidx_t), 0, 0, sizeof (dof_provider_t)); 573178479Sjb 574178479Sjb dofr.dofr_strtab = dofpv.dofpv_strtab; 575178479Sjb dofr.dofr_tgtsec = dofpv.dofpv_probes; 576178479Sjb dofr.dofr_relsec = dof_add_lsect(ddo, NULL, DOF_SECT_RELTAB, 577178479Sjb sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 578178479Sjb dt_buf_len(&ddo->ddo_rels)); 579178479Sjb 580178479Sjb dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_rels, sizeof (uint64_t)); 581178479Sjb 582178479Sjb (void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR, 583178479Sjb sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 584178479Sjb 585178479Sjb if (nxr != 0 && dtp->dt_xlatemode == DT_XL_DYNAMIC) { 586178479Sjb (void) dof_add_lsect(ddo, dofs, DOF_SECT_PREXPORT, 587178479Sjb sizeof (dof_secidx_t), 0, sizeof (dof_secidx_t), 588178479Sjb sizeof (dof_secidx_t) * (nxr + 1)); 589178479Sjb } 590265234Spfg 591265234Spfg return (0); 592178479Sjb} 593178479Sjb 594178479Sjbstatic int 595178479Sjbdof_hdr(dtrace_hdl_t *dtp, uint8_t dofversion, dof_hdr_t *hp) 596178479Sjb{ 597178479Sjb /* 598178479Sjb * If our config values cannot fit in a uint8_t, we can't generate a 599178479Sjb * DOF header since the values won't fit. This can only happen if the 600178479Sjb * user forcibly compiles a program with an artificial configuration. 601178479Sjb */ 602178479Sjb if (dtp->dt_conf.dtc_difversion > UINT8_MAX || 603178479Sjb dtp->dt_conf.dtc_difintregs > UINT8_MAX || 604178479Sjb dtp->dt_conf.dtc_diftupregs > UINT8_MAX) 605178479Sjb return (dt_set_errno(dtp, EOVERFLOW)); 606178479Sjb 607178479Sjb bzero(hp, sizeof (dof_hdr_t)); 608178479Sjb 609178479Sjb hp->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0; 610178479Sjb hp->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1; 611178479Sjb hp->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2; 612178479Sjb hp->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3; 613178479Sjb 614178479Sjb if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) 615178479Sjb hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_LP64; 616178479Sjb else 617178479Sjb hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_ILP32; 618178479Sjb 619178479Sjb hp->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE; 620178479Sjb hp->dofh_ident[DOF_ID_VERSION] = dofversion; 621178479Sjb hp->dofh_ident[DOF_ID_DIFVERS] = dtp->dt_conf.dtc_difversion; 622178479Sjb hp->dofh_ident[DOF_ID_DIFIREG] = dtp->dt_conf.dtc_difintregs; 623178479Sjb hp->dofh_ident[DOF_ID_DIFTREG] = dtp->dt_conf.dtc_diftupregs; 624178479Sjb 625178479Sjb hp->dofh_hdrsize = sizeof (dof_hdr_t); 626178479Sjb hp->dofh_secsize = sizeof (dof_sec_t); 627178479Sjb hp->dofh_secoff = sizeof (dof_hdr_t); 628178479Sjb 629178479Sjb return (0); 630178479Sjb} 631178479Sjb 632178479Sjbvoid * 633178479Sjbdtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags) 634178479Sjb{ 635178479Sjb dt_dof_t *ddo = &dtp->dt_dof; 636178479Sjb 637178479Sjb const dtrace_ecbdesc_t *edp, *last; 638178479Sjb const dtrace_probedesc_t *pdp; 639178479Sjb const dtrace_actdesc_t *ap; 640178479Sjb const dt_stmt_t *stp; 641178479Sjb 642178479Sjb uint_t maxacts = 0; 643178479Sjb uint_t maxfmt = 0; 644178479Sjb 645178479Sjb dt_provider_t *pvp; 646178479Sjb dt_xlator_t *dxp; 647178479Sjb dof_actdesc_t *dofa; 648178479Sjb dof_sec_t *sp; 649178479Sjb size_t ssize, lsize; 650178479Sjb dof_hdr_t h; 651178479Sjb 652178479Sjb dt_buf_t dof; 653178479Sjb char *fmt; 654178479Sjb uint_t i; 655178479Sjb 656178479Sjb if (flags & ~DTRACE_D_MASK) { 657178479Sjb (void) dt_set_errno(dtp, EINVAL); 658178479Sjb return (NULL); 659178479Sjb } 660178479Sjb 661178479Sjb flags |= dtp->dt_dflags; 662178479Sjb 663178479Sjb if (dof_hdr(dtp, pgp->dp_dofversion, &h) != 0) 664178479Sjb return (NULL); 665178479Sjb 666178479Sjb if (dt_dof_reset(dtp, pgp) != 0) 667178479Sjb return (NULL); 668178479Sjb 669178479Sjb /* 670178479Sjb * Iterate through the statement list computing the maximum number of 671178479Sjb * actions and the maximum format string for allocating local buffers. 672178479Sjb */ 673178479Sjb for (last = NULL, stp = dt_list_next(&pgp->dp_stmts); 674178479Sjb stp != NULL; stp = dt_list_next(stp), last = edp) { 675178479Sjb 676178479Sjb dtrace_stmtdesc_t *sdp = stp->ds_desc; 677178479Sjb dtrace_actdesc_t *ap = sdp->dtsd_action; 678178479Sjb 679178479Sjb if (sdp->dtsd_fmtdata != NULL) { 680178479Sjb i = dtrace_printf_format(dtp, 681178479Sjb sdp->dtsd_fmtdata, NULL, 0); 682178479Sjb maxfmt = MAX(maxfmt, i); 683178479Sjb } 684178479Sjb 685178479Sjb if ((edp = sdp->dtsd_ecbdesc) == last) 686178479Sjb continue; /* same ecb as previous statement */ 687178479Sjb 688178479Sjb for (i = 0, ap = edp->dted_action; ap; ap = ap->dtad_next) 689178479Sjb i++; 690178479Sjb 691178479Sjb maxacts = MAX(maxacts, i); 692178479Sjb } 693178479Sjb 694178479Sjb dofa = alloca(sizeof (dof_actdesc_t) * maxacts); 695178479Sjb fmt = alloca(maxfmt + 1); 696178479Sjb 697178479Sjb ddo->ddo_strsec = dof_add_lsect(ddo, NULL, DOF_SECT_STRTAB, 1, 0, 0, 0); 698178479Sjb (void) dof_add_string(ddo, ""); 699178479Sjb 700178479Sjb /* 701178479Sjb * If there are references to dynamic translators in the program, add 702178479Sjb * an imported translator table entry for each referenced translator. 703178479Sjb */ 704178479Sjb if (pgp->dp_xrefslen != 0) { 705178479Sjb for (dxp = dt_list_next(&dtp->dt_xlators); 706178479Sjb dxp != NULL; dxp = dt_list_next(dxp)) { 707178479Sjb if (dxp->dx_id < pgp->dp_xrefslen && 708178479Sjb pgp->dp_xrefs[dxp->dx_id] != NULL) 709178479Sjb dof_add_translator(ddo, dxp, DOF_SECT_XLIMPORT); 710178479Sjb } 711178479Sjb } 712178479Sjb 713178479Sjb /* 714178479Sjb * Now iterate through the statement list, creating the DOF section 715178479Sjb * headers and data for each one and adding them to our buffers. 716178479Sjb */ 717178479Sjb for (last = NULL, stp = dt_list_next(&pgp->dp_stmts); 718178479Sjb stp != NULL; stp = dt_list_next(stp), last = edp) { 719178479Sjb 720178479Sjb dof_secidx_t probesec = DOF_SECIDX_NONE; 721178479Sjb dof_secidx_t prdsec = DOF_SECIDX_NONE; 722178479Sjb dof_secidx_t actsec = DOF_SECIDX_NONE; 723178479Sjb 724178479Sjb const dt_stmt_t *next = stp; 725178479Sjb dtrace_stmtdesc_t *sdp = stp->ds_desc; 726178479Sjb dof_stridx_t strndx = 0; 727178479Sjb dof_probedesc_t dofp; 728178479Sjb dof_ecbdesc_t dofe; 729178479Sjb uint_t i; 730178479Sjb 731178479Sjb if ((edp = stp->ds_desc->dtsd_ecbdesc) == last) 732178479Sjb continue; /* same ecb as previous statement */ 733178479Sjb 734178479Sjb pdp = &edp->dted_probe; 735178479Sjb 736178479Sjb /* 737178479Sjb * Add a DOF_SECT_PROBEDESC for the ECB's probe description, 738178479Sjb * and copy the probe description strings into the string table. 739178479Sjb */ 740178479Sjb dofp.dofp_strtab = ddo->ddo_strsec; 741178479Sjb dofp.dofp_provider = dof_add_string(ddo, pdp->dtpd_provider); 742178479Sjb dofp.dofp_mod = dof_add_string(ddo, pdp->dtpd_mod); 743178479Sjb dofp.dofp_func = dof_add_string(ddo, pdp->dtpd_func); 744178479Sjb dofp.dofp_name = dof_add_string(ddo, pdp->dtpd_name); 745178479Sjb dofp.dofp_id = pdp->dtpd_id; 746178479Sjb 747178479Sjb probesec = dof_add_lsect(ddo, &dofp, DOF_SECT_PROBEDESC, 748178479Sjb sizeof (dof_secidx_t), 0, 749178479Sjb sizeof (dof_probedesc_t), sizeof (dof_probedesc_t)); 750178479Sjb 751178479Sjb /* 752178479Sjb * If there is a predicate DIFO associated with the ecbdesc, 753178479Sjb * write out the DIFO sections and save the DIFO section index. 754178479Sjb */ 755178479Sjb if (edp->dted_pred.dtpdd_difo != NULL) 756178479Sjb prdsec = dof_add_difo(ddo, edp->dted_pred.dtpdd_difo); 757178479Sjb 758178479Sjb /* 759178479Sjb * Now iterate through the action list generating DIFOs as 760178479Sjb * referenced therein and adding action descriptions to 'dofa'. 761178479Sjb */ 762178479Sjb for (i = 0, ap = edp->dted_action; 763178479Sjb ap != NULL; ap = ap->dtad_next, i++) { 764178479Sjb 765178479Sjb if (ap->dtad_difo != NULL) { 766178479Sjb dofa[i].dofa_difo = 767178479Sjb dof_add_difo(ddo, ap->dtad_difo); 768178479Sjb } else 769178479Sjb dofa[i].dofa_difo = DOF_SECIDX_NONE; 770178479Sjb 771178479Sjb /* 772248708Spfg * If the first action in a statement has string data, 773248708Spfg * add the string to the global string table. This can 774248708Spfg * be due either to a printf() format string 775248708Spfg * (dtsd_fmtdata) or a print() type string 776248708Spfg * (dtsd_strdata). 777178479Sjb */ 778178479Sjb if (sdp != NULL && ap == sdp->dtsd_action) { 779178479Sjb if (sdp->dtsd_fmtdata != NULL) { 780178479Sjb (void) dtrace_printf_format(dtp, 781178479Sjb sdp->dtsd_fmtdata, fmt, maxfmt + 1); 782178479Sjb strndx = dof_add_string(ddo, fmt); 783248708Spfg } else if (sdp->dtsd_strdata != NULL) { 784248708Spfg strndx = dof_add_string(ddo, 785248708Spfg sdp->dtsd_strdata); 786248708Spfg } else { 787178479Sjb strndx = 0; /* use dtad_arg instead */ 788248708Spfg } 789178479Sjb 790178479Sjb if ((next = dt_list_next(next)) != NULL) 791178479Sjb sdp = next->ds_desc; 792178479Sjb else 793178479Sjb sdp = NULL; 794178479Sjb } 795178479Sjb 796178479Sjb if (strndx != 0) { 797178479Sjb dofa[i].dofa_arg = strndx; 798178479Sjb dofa[i].dofa_strtab = ddo->ddo_strsec; 799178479Sjb } else { 800178479Sjb dofa[i].dofa_arg = ap->dtad_arg; 801178479Sjb dofa[i].dofa_strtab = DOF_SECIDX_NONE; 802178479Sjb } 803178479Sjb 804178479Sjb dofa[i].dofa_kind = ap->dtad_kind; 805178479Sjb dofa[i].dofa_ntuple = ap->dtad_ntuple; 806178479Sjb dofa[i].dofa_uarg = ap->dtad_uarg; 807178479Sjb } 808178479Sjb 809178479Sjb if (i > 0) { 810178479Sjb actsec = dof_add_lsect(ddo, dofa, DOF_SECT_ACTDESC, 811178479Sjb sizeof (uint64_t), 0, sizeof (dof_actdesc_t), 812178479Sjb sizeof (dof_actdesc_t) * i); 813178479Sjb } 814178479Sjb 815178479Sjb /* 816178479Sjb * Now finally, add the DOF_SECT_ECBDESC referencing all the 817178479Sjb * previously created sub-sections. 818178479Sjb */ 819178479Sjb dofe.dofe_probes = probesec; 820178479Sjb dofe.dofe_pred = prdsec; 821178479Sjb dofe.dofe_actions = actsec; 822178479Sjb dofe.dofe_pad = 0; 823178479Sjb dofe.dofe_uarg = edp->dted_uarg; 824178479Sjb 825178479Sjb (void) dof_add_lsect(ddo, &dofe, DOF_SECT_ECBDESC, 826178479Sjb sizeof (uint64_t), 0, 0, sizeof (dof_ecbdesc_t)); 827178479Sjb } 828178479Sjb 829178479Sjb /* 830178479Sjb * If any providers are user-defined, output DOF sections corresponding 831178479Sjb * to the providers and the probes and arguments that they define. 832178479Sjb */ 833178479Sjb if (flags & DTRACE_D_PROBES) { 834178479Sjb for (pvp = dt_list_next(&dtp->dt_provlist); 835265234Spfg pvp != NULL; pvp = dt_list_next(pvp)) { 836265234Spfg if (dof_add_provider(ddo, pvp) != 0) 837265234Spfg return (NULL); 838265234Spfg } 839178479Sjb } 840178479Sjb 841178479Sjb /* 842178479Sjb * If we're not stripping unloadable sections, generate compiler 843178479Sjb * comments and any other unloadable miscellany. 844178479Sjb */ 845178479Sjb if (!(flags & DTRACE_D_STRIP)) { 846178479Sjb (void) dof_add_usect(ddo, _dtrace_version, DOF_SECT_COMMENTS, 847178479Sjb sizeof (char), 0, 0, strlen(_dtrace_version) + 1); 848178479Sjb (void) dof_add_usect(ddo, &dtp->dt_uts, DOF_SECT_UTSNAME, 849178479Sjb sizeof (char), 0, 0, sizeof (struct utsname)); 850178479Sjb } 851178479Sjb 852178479Sjb /* 853178479Sjb * Compute and fill in the appropriate values for the dof_hdr_t's 854178479Sjb * dofh_secnum, dofh_loadsz, and dofh_filez values. 855178479Sjb */ 856178479Sjb h.dofh_secnum = ddo->ddo_nsecs; 857178479Sjb ssize = sizeof (h) + dt_buf_len(&ddo->ddo_secs); 858178479Sjb 859178479Sjb h.dofh_loadsz = ssize + 860178479Sjb dt_buf_len(&ddo->ddo_ldata) + 861178479Sjb dt_buf_len(&ddo->ddo_strs); 862178479Sjb 863178479Sjb if (dt_buf_len(&ddo->ddo_udata) != 0) { 864178479Sjb lsize = roundup(h.dofh_loadsz, sizeof (uint64_t)); 865178479Sjb h.dofh_filesz = lsize + dt_buf_len(&ddo->ddo_udata); 866178479Sjb } else { 867178479Sjb lsize = h.dofh_loadsz; 868178479Sjb h.dofh_filesz = lsize; 869178479Sjb } 870178479Sjb 871178479Sjb /* 872178479Sjb * Set the global DOF_SECT_STRTAB's offset to be after the header, 873178479Sjb * section headers, and other loadable data. Since we're going to 874178479Sjb * iterate over the buffer data directly, we must check for errors. 875178479Sjb */ 876178479Sjb if ((i = dt_buf_error(&ddo->ddo_secs)) != 0) { 877178479Sjb (void) dt_set_errno(dtp, i); 878178479Sjb return (NULL); 879178479Sjb } 880178479Sjb 881178479Sjb sp = dt_buf_ptr(&ddo->ddo_secs); 882178479Sjb assert(sp[ddo->ddo_strsec].dofs_type == DOF_SECT_STRTAB); 883210767Srpaulo assert(ssize == sizeof (h) + sizeof (dof_sec_t) * ddo->ddo_nsecs); 884178479Sjb 885178479Sjb sp[ddo->ddo_strsec].dofs_offset = ssize + dt_buf_len(&ddo->ddo_ldata); 886178479Sjb sp[ddo->ddo_strsec].dofs_size = dt_buf_len(&ddo->ddo_strs); 887178479Sjb 888178479Sjb /* 889178479Sjb * Now relocate all the other section headers by adding the appropriate 890178479Sjb * delta to their respective dofs_offset values. 891178479Sjb */ 892178479Sjb for (i = 0; i < ddo->ddo_nsecs; i++, sp++) { 893178479Sjb if (i == ddo->ddo_strsec) 894178479Sjb continue; /* already relocated above */ 895178479Sjb 896178479Sjb if (sp->dofs_flags & DOF_SECF_LOAD) 897178479Sjb sp->dofs_offset += ssize; 898178479Sjb else 899178479Sjb sp->dofs_offset += lsize; 900178479Sjb } 901178479Sjb 902178479Sjb /* 903178479Sjb * Finally, assemble the complete in-memory DOF buffer by writing the 904178479Sjb * header and then concatenating all our buffers. dt_buf_concat() will 905178479Sjb * propagate any errors and cause dt_buf_claim() to return NULL. 906178479Sjb */ 907178479Sjb dt_buf_create(dtp, &dof, "dof", h.dofh_filesz); 908178479Sjb 909178479Sjb dt_buf_write(dtp, &dof, &h, sizeof (h), sizeof (uint64_t)); 910178479Sjb dt_buf_concat(dtp, &dof, &ddo->ddo_secs, sizeof (uint64_t)); 911178479Sjb dt_buf_concat(dtp, &dof, &ddo->ddo_ldata, sizeof (uint64_t)); 912178479Sjb dt_buf_concat(dtp, &dof, &ddo->ddo_strs, sizeof (char)); 913178479Sjb dt_buf_concat(dtp, &dof, &ddo->ddo_udata, sizeof (uint64_t)); 914178479Sjb 915178479Sjb return (dt_buf_claim(dtp, &dof)); 916178479Sjb} 917178479Sjb 918178479Sjbvoid 919178479Sjbdtrace_dof_destroy(dtrace_hdl_t *dtp, void *dof) 920178479Sjb{ 921178479Sjb dt_free(dtp, dof); 922178479Sjb} 923178479Sjb 924178479Sjbvoid * 925178479Sjbdtrace_getopt_dof(dtrace_hdl_t *dtp) 926178479Sjb{ 927178479Sjb dof_hdr_t *dof; 928178479Sjb dof_sec_t *sec; 929178479Sjb dof_optdesc_t *dofo; 930178479Sjb int i, nopts = 0, len = sizeof (dof_hdr_t) + 931178479Sjb roundup(sizeof (dof_sec_t), sizeof (uint64_t)); 932178479Sjb 933178479Sjb for (i = 0; i < DTRACEOPT_MAX; i++) { 934178479Sjb if (dtp->dt_options[i] != DTRACEOPT_UNSET) 935178479Sjb nopts++; 936178479Sjb } 937178479Sjb 938178479Sjb len += sizeof (dof_optdesc_t) * nopts; 939178479Sjb 940178479Sjb if ((dof = dt_zalloc(dtp, len)) == NULL || 941178479Sjb dof_hdr(dtp, DOF_VERSION, dof) != 0) { 942178479Sjb dt_free(dtp, dof); 943178479Sjb return (NULL); 944178479Sjb } 945178479Sjb 946178479Sjb dof->dofh_secnum = 1; /* only DOF_SECT_OPTDESC */ 947178479Sjb dof->dofh_loadsz = len; 948178479Sjb dof->dofh_filesz = len; 949178479Sjb 950178479Sjb /* 951178479Sjb * Fill in the option section header... 952178479Sjb */ 953178479Sjb sec = (dof_sec_t *)((uintptr_t)dof + sizeof (dof_hdr_t)); 954178479Sjb sec->dofs_type = DOF_SECT_OPTDESC; 955178479Sjb sec->dofs_align = sizeof (uint64_t); 956178479Sjb sec->dofs_flags = DOF_SECF_LOAD; 957178479Sjb sec->dofs_entsize = sizeof (dof_optdesc_t); 958178479Sjb 959178479Sjb dofo = (dof_optdesc_t *)((uintptr_t)sec + 960178479Sjb roundup(sizeof (dof_sec_t), sizeof (uint64_t))); 961178479Sjb 962178479Sjb sec->dofs_offset = (uintptr_t)dofo - (uintptr_t)dof; 963178479Sjb sec->dofs_size = sizeof (dof_optdesc_t) * nopts; 964178479Sjb 965178479Sjb for (i = 0; i < DTRACEOPT_MAX; i++) { 966178479Sjb if (dtp->dt_options[i] == DTRACEOPT_UNSET) 967178479Sjb continue; 968178479Sjb 969178479Sjb dofo->dofo_option = i; 970178479Sjb dofo->dofo_strtab = DOF_SECIDX_NONE; 971178479Sjb dofo->dofo_value = dtp->dt_options[i]; 972178479Sjb dofo++; 973178479Sjb } 974178479Sjb 975178479Sjb return (dof); 976178479Sjb} 977178479Sjb 978178479Sjbvoid * 979178479Sjbdtrace_geterr_dof(dtrace_hdl_t *dtp) 980178479Sjb{ 981178479Sjb if (dtp->dt_errprog != NULL) 982178479Sjb return (dtrace_dof_create(dtp, dtp->dt_errprog, 0)); 983178479Sjb 984178479Sjb (void) dt_set_errno(dtp, EDT_BADERROR); 985178479Sjb return (NULL); 986178479Sjb} 987