17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5ac448965Sahl * Common Development and Distribution License (the "License"). 6ac448965Sahl * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21ac448965Sahl 227c478bd9Sstevel@tonic-gate /* 23c9a6ea2eSBryan Cantrill * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24deef35fdSEric Schrock * Copyright (c) 2011 by Delphix. All rights reserved. 25*54a20ab4SBryan Cantrill * Copyright (c) 2013, Joyent, Inc. All rights reserved. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/types.h> 297c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <strings.h> 327c478bd9Sstevel@tonic-gate #include <alloca.h> 337c478bd9Sstevel@tonic-gate #include <assert.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate #include <limits.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include <dt_impl.h> 397c478bd9Sstevel@tonic-gate #include <dt_strtab.h> 401a7c1b72Smws #include <dt_program.h> 417c478bd9Sstevel@tonic-gate #include <dt_provider.h> 421a7c1b72Smws #include <dt_xlator.h> 437c478bd9Sstevel@tonic-gate #include <dt_dof.h> 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate void 467c478bd9Sstevel@tonic-gate dt_dof_init(dtrace_hdl_t *dtp) 477c478bd9Sstevel@tonic-gate { 487c478bd9Sstevel@tonic-gate dt_dof_t *ddo = &dtp->dt_dof; 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate ddo->ddo_hdl = dtp; 517c478bd9Sstevel@tonic-gate ddo->ddo_nsecs = 0; 527c478bd9Sstevel@tonic-gate ddo->ddo_strsec = DOF_SECIDX_NONE; 531a7c1b72Smws ddo->ddo_xlimport = NULL; 541a7c1b72Smws ddo->ddo_xlexport = NULL; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_secs, "section headers", 0); 577c478bd9Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_strs, "string table", 0); 587c478bd9Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_ldata, "loadable data", 0); 597c478bd9Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_udata, "unloadable data", 0); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_probes, "probe data", 0); 627c478bd9Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_args, "probe args", 0); 637c478bd9Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_offs, "probe offs", 0); 64ac448965Sahl dt_buf_create(dtp, &ddo->ddo_enoffs, "probe is-enabled offs", 0); 657c478bd9Sstevel@tonic-gate dt_buf_create(dtp, &ddo->ddo_rels, "probe rels", 0); 661a7c1b72Smws 671a7c1b72Smws dt_buf_create(dtp, &ddo->ddo_xlms, "xlate members", 0); 687c478bd9Sstevel@tonic-gate } 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate void 717c478bd9Sstevel@tonic-gate dt_dof_fini(dtrace_hdl_t *dtp) 727c478bd9Sstevel@tonic-gate { 737c478bd9Sstevel@tonic-gate dt_dof_t *ddo = &dtp->dt_dof; 747c478bd9Sstevel@tonic-gate 751a7c1b72Smws dt_free(dtp, ddo->ddo_xlimport); 761a7c1b72Smws dt_free(dtp, ddo->ddo_xlexport); 771a7c1b72Smws 787c478bd9Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_secs); 797c478bd9Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_strs); 807c478bd9Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_ldata); 817c478bd9Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_udata); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_probes); 847c478bd9Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_args); 857c478bd9Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_offs); 86ac448965Sahl dt_buf_destroy(dtp, &ddo->ddo_enoffs); 877c478bd9Sstevel@tonic-gate dt_buf_destroy(dtp, &ddo->ddo_rels); 881a7c1b72Smws 891a7c1b72Smws dt_buf_destroy(dtp, &ddo->ddo_xlms); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 921a7c1b72Smws static int 931a7c1b72Smws dt_dof_reset(dtrace_hdl_t *dtp, dtrace_prog_t *pgp) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate dt_dof_t *ddo = &dtp->dt_dof; 961a7c1b72Smws uint_t i, nx = dtp->dt_xlatorid; 971a7c1b72Smws 981a7c1b72Smws assert(ddo->ddo_hdl == dtp); 991a7c1b72Smws ddo->ddo_pgp = pgp; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate ddo->ddo_nsecs = 0; 1027c478bd9Sstevel@tonic-gate ddo->ddo_strsec = DOF_SECIDX_NONE; 1037c478bd9Sstevel@tonic-gate 1041a7c1b72Smws dt_free(dtp, ddo->ddo_xlimport); 1051a7c1b72Smws dt_free(dtp, ddo->ddo_xlexport); 1061a7c1b72Smws 1071a7c1b72Smws ddo->ddo_xlimport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx); 1081a7c1b72Smws ddo->ddo_xlexport = dt_alloc(dtp, sizeof (dof_secidx_t) * nx); 1091a7c1b72Smws 1101a7c1b72Smws if (nx != 0 && (ddo->ddo_xlimport == NULL || ddo->ddo_xlexport == NULL)) 1111a7c1b72Smws return (-1); /* errno is set for us */ 1121a7c1b72Smws 1131a7c1b72Smws for (i = 0; i < nx; i++) { 1141a7c1b72Smws ddo->ddo_xlimport[i] = DOF_SECIDX_NONE; 1151a7c1b72Smws ddo->ddo_xlexport[i] = DOF_SECIDX_NONE; 1161a7c1b72Smws } 1171a7c1b72Smws 1187c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_secs); 1197c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_strs); 1207c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_ldata); 1217c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_udata); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_probes); 1247c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_args); 1257c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_offs); 126ac448965Sahl dt_buf_reset(dtp, &ddo->ddo_enoffs); 1277c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_rels); 1281a7c1b72Smws 1291a7c1b72Smws dt_buf_reset(dtp, &ddo->ddo_xlms); 1301a7c1b72Smws return (0); 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * Add a loadable DOF section to the file using the specified data buffer and 1357c478bd9Sstevel@tonic-gate * the specified DOF section attributes. DOF_SECF_LOAD must be set in flags. 1367c478bd9Sstevel@tonic-gate * If 'data' is NULL, the caller is responsible for manipulating the ldata buf. 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate static dof_secidx_t 1397c478bd9Sstevel@tonic-gate dof_add_lsect(dt_dof_t *ddo, const void *data, uint32_t type, 1407c478bd9Sstevel@tonic-gate uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size) 1417c478bd9Sstevel@tonic-gate { 1427c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = ddo->ddo_hdl; 1437c478bd9Sstevel@tonic-gate dof_sec_t s; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate s.dofs_type = type; 1467c478bd9Sstevel@tonic-gate s.dofs_align = align; 1477c478bd9Sstevel@tonic-gate s.dofs_flags = flags | DOF_SECF_LOAD; 1487c478bd9Sstevel@tonic-gate s.dofs_entsize = entsize; 1497c478bd9Sstevel@tonic-gate s.dofs_offset = dt_buf_offset(&ddo->ddo_ldata, align); 1507c478bd9Sstevel@tonic-gate s.dofs_size = size; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t)); 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate if (data != NULL) 1557c478bd9Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_ldata, data, size, align); 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate return (ddo->ddo_nsecs++); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate /* 1617c478bd9Sstevel@tonic-gate * Add an unloadable DOF section to the file using the specified data buffer 1627c478bd9Sstevel@tonic-gate * and DOF section attributes. DOF_SECF_LOAD must *not* be set in flags. 1637c478bd9Sstevel@tonic-gate * If 'data' is NULL, the caller is responsible for manipulating the udata buf. 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate static dof_secidx_t 1667c478bd9Sstevel@tonic-gate dof_add_usect(dt_dof_t *ddo, const void *data, uint32_t type, 1677c478bd9Sstevel@tonic-gate uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size) 1687c478bd9Sstevel@tonic-gate { 1697c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = ddo->ddo_hdl; 1707c478bd9Sstevel@tonic-gate dof_sec_t s; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate s.dofs_type = type; 1737c478bd9Sstevel@tonic-gate s.dofs_align = align; 1747c478bd9Sstevel@tonic-gate s.dofs_flags = flags & ~DOF_SECF_LOAD; 1757c478bd9Sstevel@tonic-gate s.dofs_entsize = entsize; 1767c478bd9Sstevel@tonic-gate s.dofs_offset = dt_buf_offset(&ddo->ddo_udata, align); 1777c478bd9Sstevel@tonic-gate s.dofs_size = size; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t)); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate if (data != NULL) 1827c478bd9Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_udata, data, size, align); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate return (ddo->ddo_nsecs++); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate /* 1887c478bd9Sstevel@tonic-gate * Add a string to the global string table associated with the DOF. The offset 1897c478bd9Sstevel@tonic-gate * of the string is returned as an index into the string table. 1907c478bd9Sstevel@tonic-gate */ 1917c478bd9Sstevel@tonic-gate static dof_stridx_t 1927c478bd9Sstevel@tonic-gate dof_add_string(dt_dof_t *ddo, const char *s) 1937c478bd9Sstevel@tonic-gate { 1947c478bd9Sstevel@tonic-gate dt_buf_t *bp = &ddo->ddo_strs; 1957c478bd9Sstevel@tonic-gate dof_stridx_t i = dt_buf_len(bp); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if (i != 0 && (s == NULL || *s == '\0')) 1987c478bd9Sstevel@tonic-gate return (0); /* string table has \0 at offset 0 */ 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate dt_buf_write(ddo->ddo_hdl, bp, s, strlen(s) + 1, sizeof (char)); 2017c478bd9Sstevel@tonic-gate return (i); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate static dof_attr_t 2057c478bd9Sstevel@tonic-gate dof_attr(const dtrace_attribute_t *ap) 2067c478bd9Sstevel@tonic-gate { 2077c478bd9Sstevel@tonic-gate return (DOF_ATTR(ap->dtat_name, ap->dtat_data, ap->dtat_class)); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate static dof_secidx_t 2117c478bd9Sstevel@tonic-gate dof_add_difo(dt_dof_t *ddo, const dtrace_difo_t *dp) 2127c478bd9Sstevel@tonic-gate { 2131a7c1b72Smws dof_secidx_t dsecs[5]; /* enough for all possible DIFO sections */ 2147c478bd9Sstevel@tonic-gate uint_t nsecs = 0; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate dof_difohdr_t *dofd; 2177c478bd9Sstevel@tonic-gate dof_relohdr_t dofr; 2187c478bd9Sstevel@tonic-gate dof_secidx_t relsec; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate dof_secidx_t strsec = DOF_SECIDX_NONE; 2217c478bd9Sstevel@tonic-gate dof_secidx_t intsec = DOF_SECIDX_NONE; 2227c478bd9Sstevel@tonic-gate dof_secidx_t hdrsec = DOF_SECIDX_NONE; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate if (dp->dtdo_buf != NULL) { 2257c478bd9Sstevel@tonic-gate dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_buf, 2267c478bd9Sstevel@tonic-gate DOF_SECT_DIF, sizeof (dif_instr_t), 0, 2277c478bd9Sstevel@tonic-gate sizeof (dif_instr_t), sizeof (dif_instr_t) * dp->dtdo_len); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate if (dp->dtdo_inttab != NULL) { 2317c478bd9Sstevel@tonic-gate dsecs[nsecs++] = intsec = dof_add_lsect(ddo, dp->dtdo_inttab, 2327c478bd9Sstevel@tonic-gate DOF_SECT_INTTAB, sizeof (uint64_t), 0, 2337c478bd9Sstevel@tonic-gate sizeof (uint64_t), sizeof (uint64_t) * dp->dtdo_intlen); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate if (dp->dtdo_strtab != NULL) { 2377c478bd9Sstevel@tonic-gate dsecs[nsecs++] = strsec = dof_add_lsect(ddo, dp->dtdo_strtab, 2387c478bd9Sstevel@tonic-gate DOF_SECT_STRTAB, sizeof (char), 0, 0, dp->dtdo_strlen); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate if (dp->dtdo_vartab != NULL) { 2427c478bd9Sstevel@tonic-gate dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_vartab, 2437c478bd9Sstevel@tonic-gate DOF_SECT_VARTAB, sizeof (uint_t), 0, sizeof (dtrace_difv_t), 2447c478bd9Sstevel@tonic-gate sizeof (dtrace_difv_t) * dp->dtdo_varlen); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2471a7c1b72Smws if (dp->dtdo_xlmtab != NULL) { 2481a7c1b72Smws dof_xlref_t *xlt, *xlp; 2491a7c1b72Smws dt_node_t **pnp; 2501a7c1b72Smws 2511a7c1b72Smws xlt = alloca(sizeof (dof_xlref_t) * dp->dtdo_xlmlen); 2521a7c1b72Smws pnp = dp->dtdo_xlmtab; 2531a7c1b72Smws 2541a7c1b72Smws /* 2551a7c1b72Smws * dtdo_xlmtab contains pointers to the translator members. 2561a7c1b72Smws * The translator itself is in sect ddo_xlimport[dxp->dx_id]. 2571a7c1b72Smws * The XLMEMBERS entries are in order by their dn_membid, so 2581a7c1b72Smws * the member section offset is the population count of bits 2591a7c1b72Smws * in ddo_pgp->dp_xlrefs[] up to and not including dn_membid. 2601a7c1b72Smws */ 2611a7c1b72Smws for (xlp = xlt; xlp < xlt + dp->dtdo_xlmlen; xlp++) { 2621a7c1b72Smws dt_node_t *dnp = *pnp++; 2631a7c1b72Smws dt_xlator_t *dxp = dnp->dn_membexpr->dn_xlator; 2641a7c1b72Smws 2651a7c1b72Smws xlp->dofxr_xlator = ddo->ddo_xlimport[dxp->dx_id]; 2661a7c1b72Smws xlp->dofxr_member = dt_popcb( 2671a7c1b72Smws ddo->ddo_pgp->dp_xrefs[dxp->dx_id], dnp->dn_membid); 2681a7c1b72Smws xlp->dofxr_argn = (uint32_t)dxp->dx_arg; 2691a7c1b72Smws } 2701a7c1b72Smws 2711a7c1b72Smws dsecs[nsecs++] = dof_add_lsect(ddo, xlt, DOF_SECT_XLTAB, 2721a7c1b72Smws sizeof (dof_secidx_t), 0, sizeof (dof_xlref_t), 2731a7c1b72Smws sizeof (dof_xlref_t) * dp->dtdo_xlmlen); 2741a7c1b72Smws } 2751a7c1b72Smws 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate * Copy the return type and the array of section indices that form the 2787c478bd9Sstevel@tonic-gate * DIFO into a single dof_difohdr_t and then add DOF_SECT_DIFOHDR. 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate assert(nsecs <= sizeof (dsecs) / sizeof (dsecs[0])); 2817c478bd9Sstevel@tonic-gate dofd = alloca(sizeof (dtrace_diftype_t) + sizeof (dsecs)); 2827c478bd9Sstevel@tonic-gate bcopy(&dp->dtdo_rtype, &dofd->dofd_rtype, sizeof (dtrace_diftype_t)); 2837c478bd9Sstevel@tonic-gate bcopy(dsecs, &dofd->dofd_links, sizeof (dof_secidx_t) * nsecs); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate hdrsec = dof_add_lsect(ddo, dofd, DOF_SECT_DIFOHDR, 2867c478bd9Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, 2877c478bd9Sstevel@tonic-gate sizeof (dtrace_diftype_t) + sizeof (dof_secidx_t) * nsecs); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * Add any other sections related to dtrace_difo_t. These are not 2917c478bd9Sstevel@tonic-gate * referenced in dof_difohdr_t because they are not used by emulation. 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate if (dp->dtdo_kreltab != NULL) { 2947c478bd9Sstevel@tonic-gate relsec = dof_add_lsect(ddo, dp->dtdo_kreltab, DOF_SECT_RELTAB, 2957c478bd9Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 2967c478bd9Sstevel@tonic-gate sizeof (dof_relodesc_t) * dp->dtdo_krelen); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate /* 2997c478bd9Sstevel@tonic-gate * This code assumes the target of all relocations is the 3007c478bd9Sstevel@tonic-gate * integer table 'intsec' (DOF_SECT_INTTAB). If other sections 3017c478bd9Sstevel@tonic-gate * need relocation in the future this will need to change. 3027c478bd9Sstevel@tonic-gate */ 3037c478bd9Sstevel@tonic-gate dofr.dofr_strtab = strsec; 3047c478bd9Sstevel@tonic-gate dofr.dofr_relsec = relsec; 3057c478bd9Sstevel@tonic-gate dofr.dofr_tgtsec = intsec; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate (void) dof_add_lsect(ddo, &dofr, DOF_SECT_KRELHDR, 3087c478bd9Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if (dp->dtdo_ureltab != NULL) { 3127c478bd9Sstevel@tonic-gate relsec = dof_add_lsect(ddo, dp->dtdo_ureltab, DOF_SECT_RELTAB, 3137c478bd9Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 3147c478bd9Sstevel@tonic-gate sizeof (dof_relodesc_t) * dp->dtdo_urelen); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * This code assumes the target of all relocations is the 3187c478bd9Sstevel@tonic-gate * integer table 'intsec' (DOF_SECT_INTTAB). If other sections 3197c478bd9Sstevel@tonic-gate * need relocation in the future this will need to change. 3207c478bd9Sstevel@tonic-gate */ 3217c478bd9Sstevel@tonic-gate dofr.dofr_strtab = strsec; 3227c478bd9Sstevel@tonic-gate dofr.dofr_relsec = relsec; 3237c478bd9Sstevel@tonic-gate dofr.dofr_tgtsec = intsec; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate (void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR, 3267c478bd9Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate return (hdrsec); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3321a7c1b72Smws static void 3331a7c1b72Smws dof_add_translator(dt_dof_t *ddo, const dt_xlator_t *dxp, uint_t type) 3341a7c1b72Smws { 3351a7c1b72Smws dtrace_hdl_t *dtp = ddo->ddo_hdl; 3361a7c1b72Smws dof_xlmember_t dofxm; 3371a7c1b72Smws dof_xlator_t dofxl; 3381a7c1b72Smws dof_secidx_t *xst; 3391a7c1b72Smws 3401a7c1b72Smws char buf[DT_TYPE_NAMELEN]; 3411a7c1b72Smws dt_node_t *dnp; 3421a7c1b72Smws uint_t i = 0; 3431a7c1b72Smws 3441a7c1b72Smws assert(type == DOF_SECT_XLIMPORT || type == DOF_SECT_XLEXPORT); 3451a7c1b72Smws xst = type == DOF_SECT_XLIMPORT ? ddo->ddo_xlimport : ddo->ddo_xlexport; 3461a7c1b72Smws 3471a7c1b72Smws if (xst[dxp->dx_id] != DOF_SECIDX_NONE) 3481a7c1b72Smws return; /* translator has already been emitted */ 3491a7c1b72Smws 3501a7c1b72Smws dt_buf_reset(dtp, &ddo->ddo_xlms); 3511a7c1b72Smws 3521a7c1b72Smws /* 3531a7c1b72Smws * Generate an array of dof_xlmember_t's into ddo_xlms. If we are 3541a7c1b72Smws * importing the translator, add only those members referenced by the 3551a7c1b72Smws * program and set the dofxm_difo reference of each member to NONE. If 3561a7c1b72Smws * we're exporting the translator, add all members and a DIFO for each. 3571a7c1b72Smws */ 3581a7c1b72Smws for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list, i++) { 3591a7c1b72Smws if (type == DOF_SECT_XLIMPORT) { 3601a7c1b72Smws if (!BT_TEST(ddo->ddo_pgp->dp_xrefs[dxp->dx_id], i)) 3611a7c1b72Smws continue; /* member is not referenced */ 3621a7c1b72Smws dofxm.dofxm_difo = DOF_SECIDX_NONE; 3631a7c1b72Smws } else { 3641a7c1b72Smws dofxm.dofxm_difo = dof_add_difo(ddo, 3651a7c1b72Smws dxp->dx_membdif[dnp->dn_membid]); 3661a7c1b72Smws } 3671a7c1b72Smws 3681a7c1b72Smws dofxm.dofxm_name = dof_add_string(ddo, dnp->dn_membname); 3691a7c1b72Smws dt_node_diftype(dtp, dnp, &dofxm.dofxm_type); 3701a7c1b72Smws 3711a7c1b72Smws dt_buf_write(dtp, &ddo->ddo_xlms, 3721a7c1b72Smws &dofxm, sizeof (dofxm), sizeof (uint32_t)); 3731a7c1b72Smws } 3741a7c1b72Smws 3751a7c1b72Smws dofxl.dofxl_members = dof_add_lsect(ddo, NULL, DOF_SECT_XLMEMBERS, 3761a7c1b72Smws sizeof (uint32_t), 0, sizeof (dofxm), dt_buf_len(&ddo->ddo_xlms)); 3771a7c1b72Smws 3781a7c1b72Smws dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_xlms, sizeof (uint32_t)); 3791a7c1b72Smws 3801a7c1b72Smws dofxl.dofxl_strtab = ddo->ddo_strsec; 3811a7c1b72Smws dofxl.dofxl_argv = dof_add_string(ddo, ctf_type_name( 3821a7c1b72Smws dxp->dx_src_ctfp, dxp->dx_src_type, buf, sizeof (buf))); 3831a7c1b72Smws dofxl.dofxl_argc = 1; 3841a7c1b72Smws dofxl.dofxl_type = dof_add_string(ddo, ctf_type_name( 3851a7c1b72Smws dxp->dx_dst_ctfp, dxp->dx_dst_type, buf, sizeof (buf))); 3861a7c1b72Smws dofxl.dofxl_attr = dof_attr(&dxp->dx_souid.di_attr); 3871a7c1b72Smws 3881a7c1b72Smws xst[dxp->dx_id] = dof_add_lsect(ddo, &dofxl, type, 3891a7c1b72Smws sizeof (uint32_t), 0, 0, sizeof (dofxl)); 3901a7c1b72Smws } 3911a7c1b72Smws 3927c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3937c478bd9Sstevel@tonic-gate static int 3947c478bd9Sstevel@tonic-gate dof_add_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 3957c478bd9Sstevel@tonic-gate { 3967c478bd9Sstevel@tonic-gate dt_dof_t *ddo = data; 3977c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = ddo->ddo_hdl; 3987c478bd9Sstevel@tonic-gate dt_probe_t *prp = idp->di_data; 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate dof_probe_t dofpr; 4017c478bd9Sstevel@tonic-gate dof_relodesc_t dofr; 4027c478bd9Sstevel@tonic-gate dt_probe_instance_t *pip; 4037c478bd9Sstevel@tonic-gate dt_node_t *dnp; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate char buf[DT_TYPE_NAMELEN]; 4067c478bd9Sstevel@tonic-gate uint_t i; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate dofpr.dofpr_addr = 0; 4097c478bd9Sstevel@tonic-gate dofpr.dofpr_name = dof_add_string(ddo, prp->pr_name); 4107c478bd9Sstevel@tonic-gate dofpr.dofpr_nargv = dt_buf_len(&ddo->ddo_strs); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate for (dnp = prp->pr_nargs; dnp != NULL; dnp = dnp->dn_list) { 4137c478bd9Sstevel@tonic-gate (void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp, 4147c478bd9Sstevel@tonic-gate dnp->dn_type, buf, sizeof (buf))); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate dofpr.dofpr_xargv = dt_buf_len(&ddo->ddo_strs); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate for (dnp = prp->pr_xargs; dnp != NULL; dnp = dnp->dn_list) { 4207c478bd9Sstevel@tonic-gate (void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp, 4217c478bd9Sstevel@tonic-gate dnp->dn_type, buf, sizeof (buf))); 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate dofpr.dofpr_argidx = dt_buf_len(&ddo->ddo_args) / sizeof (uint8_t); 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate for (i = 0; i < prp->pr_xargc; i++) { 4277c478bd9Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_args, &prp->pr_mapping[i], 4287c478bd9Sstevel@tonic-gate sizeof (uint8_t), sizeof (uint8_t)); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate dofpr.dofpr_nargc = prp->pr_nargc; 4327c478bd9Sstevel@tonic-gate dofpr.dofpr_xargc = prp->pr_xargc; 433ac448965Sahl dofpr.dofpr_pad1 = 0; 434ac448965Sahl dofpr.dofpr_pad2 = 0; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) { 437ac448965Sahl dt_dprintf("adding probe for %s:%s\n", pip->pi_fname, 438ac448965Sahl prp->pr_name); 439ac448965Sahl 4407c478bd9Sstevel@tonic-gate dofpr.dofpr_func = dof_add_string(ddo, pip->pi_fname); 441ac448965Sahl 442ab9a77c7Sahl /* 443ab9a77c7Sahl * There should be one probe offset or is-enabled probe offset 444ab9a77c7Sahl * or else this probe instance won't have been created. The 445ab9a77c7Sahl * kernel will reject DOF which has a probe with no offsets. 446ab9a77c7Sahl */ 447ab9a77c7Sahl assert(pip->pi_noffs + pip->pi_nenoffs > 0); 448ac448965Sahl 4497c478bd9Sstevel@tonic-gate dofpr.dofpr_offidx = 4507c478bd9Sstevel@tonic-gate dt_buf_len(&ddo->ddo_offs) / sizeof (uint32_t); 4517c478bd9Sstevel@tonic-gate dofpr.dofpr_noffs = pip->pi_noffs; 4527c478bd9Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_offs, pip->pi_offs, 4537c478bd9Sstevel@tonic-gate pip->pi_noffs * sizeof (uint32_t), sizeof (uint32_t)); 4547c478bd9Sstevel@tonic-gate 455ac448965Sahl dofpr.dofpr_enoffidx = 456ac448965Sahl dt_buf_len(&ddo->ddo_enoffs) / sizeof (uint32_t); 457ac448965Sahl dofpr.dofpr_nenoffs = pip->pi_nenoffs; 458ac448965Sahl dt_buf_write(dtp, &ddo->ddo_enoffs, pip->pi_enoffs, 4590f7e3708Sahl pip->pi_nenoffs * sizeof (uint32_t), sizeof (uint32_t)); 460ac448965Sahl 4614b499cecSahl /* 4624b499cecSahl * If pi_rname isn't set, the relocation will be against the 4634b499cecSahl * function name. If it is, the relocation will be against 4644b499cecSahl * pi_rname. This will be used if the function is scoped 4654b499cecSahl * locally so an alternate symbol is added for the purpose 4664b499cecSahl * of this relocation. 4674b499cecSahl */ 4684b499cecSahl if (pip->pi_rname[0] == '\0') 4697c478bd9Sstevel@tonic-gate dofr.dofr_name = dofpr.dofpr_func; 4704b499cecSahl else 4714b499cecSahl dofr.dofr_name = dof_add_string(ddo, pip->pi_rname); 4727c478bd9Sstevel@tonic-gate dofr.dofr_type = DOF_RELO_SETX; 4737c478bd9Sstevel@tonic-gate dofr.dofr_offset = dt_buf_len(&ddo->ddo_probes); 4747c478bd9Sstevel@tonic-gate dofr.dofr_data = 0; 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_rels, &dofr, 4777c478bd9Sstevel@tonic-gate sizeof (dofr), sizeof (uint64_t)); 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate dt_buf_write(dtp, &ddo->ddo_probes, &dofpr, 4807c478bd9Sstevel@tonic-gate sizeof (dofpr), sizeof (uint64_t)); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate return (0); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 486*54a20ab4SBryan Cantrill static int 4877c478bd9Sstevel@tonic-gate dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp) 4887c478bd9Sstevel@tonic-gate { 4897c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = ddo->ddo_hdl; 4907c478bd9Sstevel@tonic-gate dof_provider_t dofpv; 4917c478bd9Sstevel@tonic-gate dof_relohdr_t dofr; 4921a7c1b72Smws dof_secidx_t *dofs; 4931a7c1b72Smws ulong_t xr, nxr; 494ab9a77c7Sahl size_t sz; 4951a7c1b72Smws id_t i; 4967c478bd9Sstevel@tonic-gate 497*54a20ab4SBryan Cantrill if (pvp->pv_flags & DT_PROVIDER_IMPL) { 498*54a20ab4SBryan Cantrill /* 499*54a20ab4SBryan Cantrill * ignore providers that are exported by dtrace(7D) 500*54a20ab4SBryan Cantrill */ 501*54a20ab4SBryan Cantrill return (0); 502*54a20ab4SBryan Cantrill } 5037c478bd9Sstevel@tonic-gate 5041a7c1b72Smws nxr = dt_popcb(pvp->pv_xrefs, pvp->pv_xrmax); 5051a7c1b72Smws dofs = alloca(sizeof (dof_secidx_t) * (nxr + 1)); 5061a7c1b72Smws xr = 1; /* reserve dofs[0] for the provider itself */ 5071a7c1b72Smws 5081a7c1b72Smws /* 5091a7c1b72Smws * For each translator referenced by the provider (pv_xrefs), emit an 5101a7c1b72Smws * exported translator section for it if one hasn't been created yet. 5111a7c1b72Smws */ 5121a7c1b72Smws for (i = 0; i < pvp->pv_xrmax; i++) { 5131a7c1b72Smws if (BT_TEST(pvp->pv_xrefs, i) && 5141a7c1b72Smws dtp->dt_xlatemode == DT_XL_DYNAMIC) { 5151a7c1b72Smws dof_add_translator(ddo, 5161a7c1b72Smws dt_xlator_lookup_id(dtp, i), DOF_SECT_XLEXPORT); 5171a7c1b72Smws dofs[xr++] = ddo->ddo_xlexport[i]; 5181a7c1b72Smws } 5191a7c1b72Smws } 5201a7c1b72Smws 5217c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_probes); 5227c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_args); 5237c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_offs); 524ac448965Sahl dt_buf_reset(dtp, &ddo->ddo_enoffs); 5257c478bd9Sstevel@tonic-gate dt_buf_reset(dtp, &ddo->ddo_rels); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo); 5287c478bd9Sstevel@tonic-gate 529*54a20ab4SBryan Cantrill if (dt_buf_len(&ddo->ddo_probes) == 0) 530*54a20ab4SBryan Cantrill return (dt_set_errno(dtp, EDT_NOPROBES)); 531*54a20ab4SBryan Cantrill 5327c478bd9Sstevel@tonic-gate dofpv.dofpv_probes = dof_add_lsect(ddo, NULL, DOF_SECT_PROBES, 5337c478bd9Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_probe_t), 5347c478bd9Sstevel@tonic-gate dt_buf_len(&ddo->ddo_probes)); 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate dt_buf_concat(dtp, &ddo->ddo_ldata, 5377c478bd9Sstevel@tonic-gate &ddo->ddo_probes, sizeof (uint64_t)); 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate dofpv.dofpv_prargs = dof_add_lsect(ddo, NULL, DOF_SECT_PRARGS, 5407c478bd9Sstevel@tonic-gate sizeof (uint8_t), 0, sizeof (uint8_t), dt_buf_len(&ddo->ddo_args)); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_args, sizeof (uint8_t)); 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate dofpv.dofpv_proffs = dof_add_lsect(ddo, NULL, DOF_SECT_PROFFS, 5457c478bd9Sstevel@tonic-gate sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_offs)); 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_offs, sizeof (uint_t)); 5487c478bd9Sstevel@tonic-gate 549ab9a77c7Sahl if ((sz = dt_buf_len(&ddo->ddo_enoffs)) != 0) { 550ab9a77c7Sahl dofpv.dofpv_prenoffs = dof_add_lsect(ddo, NULL, 551ab9a77c7Sahl DOF_SECT_PRENOFFS, sizeof (uint_t), 0, sizeof (uint_t), sz); 552ab9a77c7Sahl } else { 553ab9a77c7Sahl dofpv.dofpv_prenoffs = DOF_SECT_NONE; 554ab9a77c7Sahl } 555ac448965Sahl 556ac448965Sahl dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_enoffs, sizeof (uint_t)); 557ac448965Sahl 5587c478bd9Sstevel@tonic-gate dofpv.dofpv_strtab = ddo->ddo_strsec; 5597c478bd9Sstevel@tonic-gate dofpv.dofpv_name = dof_add_string(ddo, pvp->pv_desc.dtvd_name); 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate dofpv.dofpv_provattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_provider); 5627c478bd9Sstevel@tonic-gate dofpv.dofpv_modattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_mod); 5637c478bd9Sstevel@tonic-gate dofpv.dofpv_funcattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_func); 5647c478bd9Sstevel@tonic-gate dofpv.dofpv_nameattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_name); 5657c478bd9Sstevel@tonic-gate dofpv.dofpv_argsattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_args); 5667c478bd9Sstevel@tonic-gate 5671a7c1b72Smws dofs[0] = dof_add_lsect(ddo, &dofpv, DOF_SECT_PROVIDER, 5687c478bd9Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, sizeof (dof_provider_t)); 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate dofr.dofr_strtab = dofpv.dofpv_strtab; 5717c478bd9Sstevel@tonic-gate dofr.dofr_tgtsec = dofpv.dofpv_probes; 5727c478bd9Sstevel@tonic-gate dofr.dofr_relsec = dof_add_lsect(ddo, NULL, DOF_SECT_RELTAB, 5737c478bd9Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 5747c478bd9Sstevel@tonic-gate dt_buf_len(&ddo->ddo_rels)); 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_rels, sizeof (uint64_t)); 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate (void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR, 5797c478bd9Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 5801a7c1b72Smws 5811a7c1b72Smws if (nxr != 0 && dtp->dt_xlatemode == DT_XL_DYNAMIC) { 5821a7c1b72Smws (void) dof_add_lsect(ddo, dofs, DOF_SECT_PREXPORT, 5831a7c1b72Smws sizeof (dof_secidx_t), 0, sizeof (dof_secidx_t), 5841a7c1b72Smws sizeof (dof_secidx_t) * (nxr + 1)); 5851a7c1b72Smws } 586*54a20ab4SBryan Cantrill 587*54a20ab4SBryan Cantrill return (0); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate static int 591ac448965Sahl dof_hdr(dtrace_hdl_t *dtp, uint8_t dofversion, dof_hdr_t *hp) 5927c478bd9Sstevel@tonic-gate { 5937c478bd9Sstevel@tonic-gate /* 5947c478bd9Sstevel@tonic-gate * If our config values cannot fit in a uint8_t, we can't generate a 5957c478bd9Sstevel@tonic-gate * DOF header since the values won't fit. This can only happen if the 5967c478bd9Sstevel@tonic-gate * user forcibly compiles a program with an artificial configuration. 5977c478bd9Sstevel@tonic-gate */ 5987c478bd9Sstevel@tonic-gate if (dtp->dt_conf.dtc_difversion > UINT8_MAX || 5997c478bd9Sstevel@tonic-gate dtp->dt_conf.dtc_difintregs > UINT8_MAX || 6007c478bd9Sstevel@tonic-gate dtp->dt_conf.dtc_diftupregs > UINT8_MAX) 6017c478bd9Sstevel@tonic-gate return (dt_set_errno(dtp, EOVERFLOW)); 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate bzero(hp, sizeof (dof_hdr_t)); 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0; 6067c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1; 6077c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2; 6087c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3; 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) 6117c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_LP64; 6127c478bd9Sstevel@tonic-gate else 6137c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_ILP32; 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE; 616ac448965Sahl hp->dofh_ident[DOF_ID_VERSION] = dofversion; 6177c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_DIFVERS] = dtp->dt_conf.dtc_difversion; 6187c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_DIFIREG] = dtp->dt_conf.dtc_difintregs; 6197c478bd9Sstevel@tonic-gate hp->dofh_ident[DOF_ID_DIFTREG] = dtp->dt_conf.dtc_diftupregs; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate hp->dofh_hdrsize = sizeof (dof_hdr_t); 6227c478bd9Sstevel@tonic-gate hp->dofh_secsize = sizeof (dof_sec_t); 6237c478bd9Sstevel@tonic-gate hp->dofh_secoff = sizeof (dof_hdr_t); 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate return (0); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate void * 6297c478bd9Sstevel@tonic-gate dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags) 6307c478bd9Sstevel@tonic-gate { 6317c478bd9Sstevel@tonic-gate dt_dof_t *ddo = &dtp->dt_dof; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate const dtrace_ecbdesc_t *edp, *last; 6347c478bd9Sstevel@tonic-gate const dtrace_probedesc_t *pdp; 6357c478bd9Sstevel@tonic-gate const dtrace_actdesc_t *ap; 6367c478bd9Sstevel@tonic-gate const dt_stmt_t *stp; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate uint_t maxacts = 0; 6397c478bd9Sstevel@tonic-gate uint_t maxfmt = 0; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate dt_provider_t *pvp; 6421a7c1b72Smws dt_xlator_t *dxp; 6437c478bd9Sstevel@tonic-gate dof_actdesc_t *dofa; 6447c478bd9Sstevel@tonic-gate dof_sec_t *sp; 6457c478bd9Sstevel@tonic-gate size_t ssize, lsize; 6467c478bd9Sstevel@tonic-gate dof_hdr_t h; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate dt_buf_t dof; 6497c478bd9Sstevel@tonic-gate char *fmt; 6507c478bd9Sstevel@tonic-gate uint_t i; 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate if (flags & ~DTRACE_D_MASK) { 6537c478bd9Sstevel@tonic-gate (void) dt_set_errno(dtp, EINVAL); 6547c478bd9Sstevel@tonic-gate return (NULL); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate flags |= dtp->dt_dflags; 6587c478bd9Sstevel@tonic-gate 659ac448965Sahl if (dof_hdr(dtp, pgp->dp_dofversion, &h) != 0) 6607c478bd9Sstevel@tonic-gate return (NULL); 6617c478bd9Sstevel@tonic-gate 6621a7c1b72Smws if (dt_dof_reset(dtp, pgp) != 0) 6631a7c1b72Smws return (NULL); 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* 6667c478bd9Sstevel@tonic-gate * Iterate through the statement list computing the maximum number of 6677c478bd9Sstevel@tonic-gate * actions and the maximum format string for allocating local buffers. 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate for (last = NULL, stp = dt_list_next(&pgp->dp_stmts); 6707c478bd9Sstevel@tonic-gate stp != NULL; stp = dt_list_next(stp), last = edp) { 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate dtrace_stmtdesc_t *sdp = stp->ds_desc; 6737c478bd9Sstevel@tonic-gate dtrace_actdesc_t *ap = sdp->dtsd_action; 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate if (sdp->dtsd_fmtdata != NULL) { 6767c478bd9Sstevel@tonic-gate i = dtrace_printf_format(dtp, 6777c478bd9Sstevel@tonic-gate sdp->dtsd_fmtdata, NULL, 0); 6787c478bd9Sstevel@tonic-gate maxfmt = MAX(maxfmt, i); 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate if ((edp = sdp->dtsd_ecbdesc) == last) 6827c478bd9Sstevel@tonic-gate continue; /* same ecb as previous statement */ 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate for (i = 0, ap = edp->dted_action; ap; ap = ap->dtad_next) 6857c478bd9Sstevel@tonic-gate i++; 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate maxacts = MAX(maxacts, i); 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate dofa = alloca(sizeof (dof_actdesc_t) * maxacts); 6917c478bd9Sstevel@tonic-gate fmt = alloca(maxfmt + 1); 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate ddo->ddo_strsec = dof_add_lsect(ddo, NULL, DOF_SECT_STRTAB, 1, 0, 0, 0); 6947c478bd9Sstevel@tonic-gate (void) dof_add_string(ddo, ""); 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate /* 6971a7c1b72Smws * If there are references to dynamic translators in the program, add 6981a7c1b72Smws * an imported translator table entry for each referenced translator. 6991a7c1b72Smws */ 7001a7c1b72Smws if (pgp->dp_xrefslen != 0) { 7011a7c1b72Smws for (dxp = dt_list_next(&dtp->dt_xlators); 7021a7c1b72Smws dxp != NULL; dxp = dt_list_next(dxp)) { 7031a7c1b72Smws if (dxp->dx_id < pgp->dp_xrefslen && 7041a7c1b72Smws pgp->dp_xrefs[dxp->dx_id] != NULL) 7051a7c1b72Smws dof_add_translator(ddo, dxp, DOF_SECT_XLIMPORT); 7061a7c1b72Smws } 7071a7c1b72Smws } 7081a7c1b72Smws 7091a7c1b72Smws /* 7107c478bd9Sstevel@tonic-gate * Now iterate through the statement list, creating the DOF section 7117c478bd9Sstevel@tonic-gate * headers and data for each one and adding them to our buffers. 7127c478bd9Sstevel@tonic-gate */ 7137c478bd9Sstevel@tonic-gate for (last = NULL, stp = dt_list_next(&pgp->dp_stmts); 7147c478bd9Sstevel@tonic-gate stp != NULL; stp = dt_list_next(stp), last = edp) { 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate dof_secidx_t probesec = DOF_SECIDX_NONE; 7177c478bd9Sstevel@tonic-gate dof_secidx_t prdsec = DOF_SECIDX_NONE; 7187c478bd9Sstevel@tonic-gate dof_secidx_t actsec = DOF_SECIDX_NONE; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate const dt_stmt_t *next = stp; 7217c478bd9Sstevel@tonic-gate dtrace_stmtdesc_t *sdp = stp->ds_desc; 7227c478bd9Sstevel@tonic-gate dof_stridx_t strndx = 0; 7237c478bd9Sstevel@tonic-gate dof_probedesc_t dofp; 7247c478bd9Sstevel@tonic-gate dof_ecbdesc_t dofe; 7257c478bd9Sstevel@tonic-gate uint_t i; 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate if ((edp = stp->ds_desc->dtsd_ecbdesc) == last) 7287c478bd9Sstevel@tonic-gate continue; /* same ecb as previous statement */ 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate pdp = &edp->dted_probe; 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate /* 7337c478bd9Sstevel@tonic-gate * Add a DOF_SECT_PROBEDESC for the ECB's probe description, 7347c478bd9Sstevel@tonic-gate * and copy the probe description strings into the string table. 7357c478bd9Sstevel@tonic-gate */ 7367c478bd9Sstevel@tonic-gate dofp.dofp_strtab = ddo->ddo_strsec; 7377c478bd9Sstevel@tonic-gate dofp.dofp_provider = dof_add_string(ddo, pdp->dtpd_provider); 7387c478bd9Sstevel@tonic-gate dofp.dofp_mod = dof_add_string(ddo, pdp->dtpd_mod); 7397c478bd9Sstevel@tonic-gate dofp.dofp_func = dof_add_string(ddo, pdp->dtpd_func); 7407c478bd9Sstevel@tonic-gate dofp.dofp_name = dof_add_string(ddo, pdp->dtpd_name); 7417c478bd9Sstevel@tonic-gate dofp.dofp_id = pdp->dtpd_id; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate probesec = dof_add_lsect(ddo, &dofp, DOF_SECT_PROBEDESC, 7447c478bd9Sstevel@tonic-gate sizeof (dof_secidx_t), 0, 7457c478bd9Sstevel@tonic-gate sizeof (dof_probedesc_t), sizeof (dof_probedesc_t)); 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate /* 7487c478bd9Sstevel@tonic-gate * If there is a predicate DIFO associated with the ecbdesc, 7497c478bd9Sstevel@tonic-gate * write out the DIFO sections and save the DIFO section index. 7507c478bd9Sstevel@tonic-gate */ 7517c478bd9Sstevel@tonic-gate if (edp->dted_pred.dtpdd_difo != NULL) 7527c478bd9Sstevel@tonic-gate prdsec = dof_add_difo(ddo, edp->dted_pred.dtpdd_difo); 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate /* 7557c478bd9Sstevel@tonic-gate * Now iterate through the action list generating DIFOs as 7567c478bd9Sstevel@tonic-gate * referenced therein and adding action descriptions to 'dofa'. 7577c478bd9Sstevel@tonic-gate */ 7587c478bd9Sstevel@tonic-gate for (i = 0, ap = edp->dted_action; 7597c478bd9Sstevel@tonic-gate ap != NULL; ap = ap->dtad_next, i++) { 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate if (ap->dtad_difo != NULL) { 7627c478bd9Sstevel@tonic-gate dofa[i].dofa_difo = 7637c478bd9Sstevel@tonic-gate dof_add_difo(ddo, ap->dtad_difo); 7647c478bd9Sstevel@tonic-gate } else 7657c478bd9Sstevel@tonic-gate dofa[i].dofa_difo = DOF_SECIDX_NONE; 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate /* 768deef35fdSEric Schrock * If the first action in a statement has string data, 769deef35fdSEric Schrock * add the string to the global string table. This can 770deef35fdSEric Schrock * be due either to a printf() format string 771deef35fdSEric Schrock * (dtsd_fmtdata) or a print() type string 772deef35fdSEric Schrock * (dtsd_strdata). 7737c478bd9Sstevel@tonic-gate */ 7747c478bd9Sstevel@tonic-gate if (sdp != NULL && ap == sdp->dtsd_action) { 7757c478bd9Sstevel@tonic-gate if (sdp->dtsd_fmtdata != NULL) { 7767c478bd9Sstevel@tonic-gate (void) dtrace_printf_format(dtp, 7777c478bd9Sstevel@tonic-gate sdp->dtsd_fmtdata, fmt, maxfmt + 1); 7787c478bd9Sstevel@tonic-gate strndx = dof_add_string(ddo, fmt); 779deef35fdSEric Schrock } else if (sdp->dtsd_strdata != NULL) { 780deef35fdSEric Schrock strndx = dof_add_string(ddo, 781deef35fdSEric Schrock sdp->dtsd_strdata); 782deef35fdSEric Schrock } else { 7837c478bd9Sstevel@tonic-gate strndx = 0; /* use dtad_arg instead */ 784deef35fdSEric Schrock } 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate if ((next = dt_list_next(next)) != NULL) 7877c478bd9Sstevel@tonic-gate sdp = next->ds_desc; 7887c478bd9Sstevel@tonic-gate else 7897c478bd9Sstevel@tonic-gate sdp = NULL; 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (strndx != 0) { 7937c478bd9Sstevel@tonic-gate dofa[i].dofa_arg = strndx; 7947c478bd9Sstevel@tonic-gate dofa[i].dofa_strtab = ddo->ddo_strsec; 7957c478bd9Sstevel@tonic-gate } else { 7967c478bd9Sstevel@tonic-gate dofa[i].dofa_arg = ap->dtad_arg; 7977c478bd9Sstevel@tonic-gate dofa[i].dofa_strtab = DOF_SECIDX_NONE; 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate dofa[i].dofa_kind = ap->dtad_kind; 8017c478bd9Sstevel@tonic-gate dofa[i].dofa_ntuple = ap->dtad_ntuple; 8027c478bd9Sstevel@tonic-gate dofa[i].dofa_uarg = ap->dtad_uarg; 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate if (i > 0) { 8067c478bd9Sstevel@tonic-gate actsec = dof_add_lsect(ddo, dofa, DOF_SECT_ACTDESC, 8077c478bd9Sstevel@tonic-gate sizeof (uint64_t), 0, sizeof (dof_actdesc_t), 8087c478bd9Sstevel@tonic-gate sizeof (dof_actdesc_t) * i); 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate /* 8127c478bd9Sstevel@tonic-gate * Now finally, add the DOF_SECT_ECBDESC referencing all the 8137c478bd9Sstevel@tonic-gate * previously created sub-sections. 8147c478bd9Sstevel@tonic-gate */ 8157c478bd9Sstevel@tonic-gate dofe.dofe_probes = probesec; 8167c478bd9Sstevel@tonic-gate dofe.dofe_pred = prdsec; 8177c478bd9Sstevel@tonic-gate dofe.dofe_actions = actsec; 8187c478bd9Sstevel@tonic-gate dofe.dofe_pad = 0; 8197c478bd9Sstevel@tonic-gate dofe.dofe_uarg = edp->dted_uarg; 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate (void) dof_add_lsect(ddo, &dofe, DOF_SECT_ECBDESC, 8227c478bd9Sstevel@tonic-gate sizeof (uint64_t), 0, 0, sizeof (dof_ecbdesc_t)); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate /* 8267c478bd9Sstevel@tonic-gate * If any providers are user-defined, output DOF sections corresponding 8277c478bd9Sstevel@tonic-gate * to the providers and the probes and arguments that they define. 8287c478bd9Sstevel@tonic-gate */ 8297c478bd9Sstevel@tonic-gate if (flags & DTRACE_D_PROBES) { 8307c478bd9Sstevel@tonic-gate for (pvp = dt_list_next(&dtp->dt_provlist); 831*54a20ab4SBryan Cantrill pvp != NULL; pvp = dt_list_next(pvp)) { 832*54a20ab4SBryan Cantrill if (dof_add_provider(ddo, pvp) != 0) 833*54a20ab4SBryan Cantrill return (NULL); 834*54a20ab4SBryan Cantrill } 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate /* 8387c478bd9Sstevel@tonic-gate * If we're not stripping unloadable sections, generate compiler 8397c478bd9Sstevel@tonic-gate * comments and any other unloadable miscellany. 8407c478bd9Sstevel@tonic-gate */ 8417c478bd9Sstevel@tonic-gate if (!(flags & DTRACE_D_STRIP)) { 8427c478bd9Sstevel@tonic-gate (void) dof_add_usect(ddo, _dtrace_version, DOF_SECT_COMMENTS, 8437c478bd9Sstevel@tonic-gate sizeof (char), 0, 0, strlen(_dtrace_version) + 1); 8447c478bd9Sstevel@tonic-gate (void) dof_add_usect(ddo, &dtp->dt_uts, DOF_SECT_UTSNAME, 8457c478bd9Sstevel@tonic-gate sizeof (char), 0, 0, sizeof (struct utsname)); 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate /* 8497c478bd9Sstevel@tonic-gate * Compute and fill in the appropriate values for the dof_hdr_t's 8507c478bd9Sstevel@tonic-gate * dofh_secnum, dofh_loadsz, and dofh_filez values. 8517c478bd9Sstevel@tonic-gate */ 8527c478bd9Sstevel@tonic-gate h.dofh_secnum = ddo->ddo_nsecs; 8537c478bd9Sstevel@tonic-gate ssize = sizeof (h) + dt_buf_len(&ddo->ddo_secs); 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate h.dofh_loadsz = ssize + 8567c478bd9Sstevel@tonic-gate dt_buf_len(&ddo->ddo_ldata) + 8577c478bd9Sstevel@tonic-gate dt_buf_len(&ddo->ddo_strs); 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate if (dt_buf_len(&ddo->ddo_udata) != 0) { 8607c478bd9Sstevel@tonic-gate lsize = roundup(h.dofh_loadsz, sizeof (uint64_t)); 8617c478bd9Sstevel@tonic-gate h.dofh_filesz = lsize + dt_buf_len(&ddo->ddo_udata); 8627c478bd9Sstevel@tonic-gate } else { 8637c478bd9Sstevel@tonic-gate lsize = h.dofh_loadsz; 8647c478bd9Sstevel@tonic-gate h.dofh_filesz = lsize; 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate /* 8687c478bd9Sstevel@tonic-gate * Set the global DOF_SECT_STRTAB's offset to be after the header, 8697c478bd9Sstevel@tonic-gate * section headers, and other loadable data. Since we're going to 8707c478bd9Sstevel@tonic-gate * iterate over the buffer data directly, we must check for errors. 8717c478bd9Sstevel@tonic-gate */ 8727c478bd9Sstevel@tonic-gate if ((i = dt_buf_error(&ddo->ddo_secs)) != 0) { 8737c478bd9Sstevel@tonic-gate (void) dt_set_errno(dtp, i); 8747c478bd9Sstevel@tonic-gate return (NULL); 8757c478bd9Sstevel@tonic-gate } 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate sp = dt_buf_ptr(&ddo->ddo_secs); 8787c478bd9Sstevel@tonic-gate assert(sp[ddo->ddo_strsec].dofs_type == DOF_SECT_STRTAB); 879c9a6ea2eSBryan Cantrill assert(ssize == sizeof (h) + sizeof (dof_sec_t) * ddo->ddo_nsecs); 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate sp[ddo->ddo_strsec].dofs_offset = ssize + dt_buf_len(&ddo->ddo_ldata); 8827c478bd9Sstevel@tonic-gate sp[ddo->ddo_strsec].dofs_size = dt_buf_len(&ddo->ddo_strs); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate /* 8857c478bd9Sstevel@tonic-gate * Now relocate all the other section headers by adding the appropriate 8867c478bd9Sstevel@tonic-gate * delta to their respective dofs_offset values. 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate for (i = 0; i < ddo->ddo_nsecs; i++, sp++) { 8897c478bd9Sstevel@tonic-gate if (i == ddo->ddo_strsec) 8907c478bd9Sstevel@tonic-gate continue; /* already relocated above */ 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate if (sp->dofs_flags & DOF_SECF_LOAD) 8937c478bd9Sstevel@tonic-gate sp->dofs_offset += ssize; 8947c478bd9Sstevel@tonic-gate else 8957c478bd9Sstevel@tonic-gate sp->dofs_offset += lsize; 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate /* 8997c478bd9Sstevel@tonic-gate * Finally, assemble the complete in-memory DOF buffer by writing the 9007c478bd9Sstevel@tonic-gate * header and then concatenating all our buffers. dt_buf_concat() will 9017c478bd9Sstevel@tonic-gate * propagate any errors and cause dt_buf_claim() to return NULL. 9027c478bd9Sstevel@tonic-gate */ 9037c478bd9Sstevel@tonic-gate dt_buf_create(dtp, &dof, "dof", h.dofh_filesz); 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate dt_buf_write(dtp, &dof, &h, sizeof (h), sizeof (uint64_t)); 9067c478bd9Sstevel@tonic-gate dt_buf_concat(dtp, &dof, &ddo->ddo_secs, sizeof (uint64_t)); 9077c478bd9Sstevel@tonic-gate dt_buf_concat(dtp, &dof, &ddo->ddo_ldata, sizeof (uint64_t)); 9087c478bd9Sstevel@tonic-gate dt_buf_concat(dtp, &dof, &ddo->ddo_strs, sizeof (char)); 9097c478bd9Sstevel@tonic-gate dt_buf_concat(dtp, &dof, &ddo->ddo_udata, sizeof (uint64_t)); 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate return (dt_buf_claim(dtp, &dof)); 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate void 9157c478bd9Sstevel@tonic-gate dtrace_dof_destroy(dtrace_hdl_t *dtp, void *dof) 9167c478bd9Sstevel@tonic-gate { 9177c478bd9Sstevel@tonic-gate dt_free(dtp, dof); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate void * 9217c478bd9Sstevel@tonic-gate dtrace_getopt_dof(dtrace_hdl_t *dtp) 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate dof_hdr_t *dof; 9247c478bd9Sstevel@tonic-gate dof_sec_t *sec; 9257c478bd9Sstevel@tonic-gate dof_optdesc_t *dofo; 9267c478bd9Sstevel@tonic-gate int i, nopts = 0, len = sizeof (dof_hdr_t) + 9277c478bd9Sstevel@tonic-gate roundup(sizeof (dof_sec_t), sizeof (uint64_t)); 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate for (i = 0; i < DTRACEOPT_MAX; i++) { 9307c478bd9Sstevel@tonic-gate if (dtp->dt_options[i] != DTRACEOPT_UNSET) 9317c478bd9Sstevel@tonic-gate nopts++; 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate len += sizeof (dof_optdesc_t) * nopts; 9357c478bd9Sstevel@tonic-gate 936ac448965Sahl if ((dof = dt_zalloc(dtp, len)) == NULL || 937ac448965Sahl dof_hdr(dtp, DOF_VERSION, dof) != 0) { 9387c478bd9Sstevel@tonic-gate dt_free(dtp, dof); 9397c478bd9Sstevel@tonic-gate return (NULL); 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate dof->dofh_secnum = 1; /* only DOF_SECT_OPTDESC */ 9437c478bd9Sstevel@tonic-gate dof->dofh_loadsz = len; 9447c478bd9Sstevel@tonic-gate dof->dofh_filesz = len; 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate /* 9477c478bd9Sstevel@tonic-gate * Fill in the option section header... 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate sec = (dof_sec_t *)((uintptr_t)dof + sizeof (dof_hdr_t)); 9507c478bd9Sstevel@tonic-gate sec->dofs_type = DOF_SECT_OPTDESC; 9517c478bd9Sstevel@tonic-gate sec->dofs_align = sizeof (uint64_t); 9527c478bd9Sstevel@tonic-gate sec->dofs_flags = DOF_SECF_LOAD; 9537c478bd9Sstevel@tonic-gate sec->dofs_entsize = sizeof (dof_optdesc_t); 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate dofo = (dof_optdesc_t *)((uintptr_t)sec + 9567c478bd9Sstevel@tonic-gate roundup(sizeof (dof_sec_t), sizeof (uint64_t))); 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate sec->dofs_offset = (uintptr_t)dofo - (uintptr_t)dof; 9597c478bd9Sstevel@tonic-gate sec->dofs_size = sizeof (dof_optdesc_t) * nopts; 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate for (i = 0; i < DTRACEOPT_MAX; i++) { 9627c478bd9Sstevel@tonic-gate if (dtp->dt_options[i] == DTRACEOPT_UNSET) 9637c478bd9Sstevel@tonic-gate continue; 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate dofo->dofo_option = i; 9667c478bd9Sstevel@tonic-gate dofo->dofo_strtab = DOF_SECIDX_NONE; 9677c478bd9Sstevel@tonic-gate dofo->dofo_value = dtp->dt_options[i]; 9687c478bd9Sstevel@tonic-gate dofo++; 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate return (dof); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate void * 9757c478bd9Sstevel@tonic-gate dtrace_geterr_dof(dtrace_hdl_t *dtp) 9767c478bd9Sstevel@tonic-gate { 9777c478bd9Sstevel@tonic-gate if (dtp->dt_errprog != NULL) 9787c478bd9Sstevel@tonic-gate return (dtrace_dof_create(dtp, dtp->dt_errprog, 0)); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_BADERROR); 9817c478bd9Sstevel@tonic-gate return (NULL); 9827c478bd9Sstevel@tonic-gate } 983