4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011 by Delphix. All rights reserved.
25 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
28 #include <sys/types.h>
29 #include <sys/sysmacros.h>
39 #include <dt_strtab.h>
40 #include <dt_program.h>
41 #include <dt_provider.h>
42 #include <dt_xlator.h>
46 dt_dof_init(dtrace_hdl_t
*dtp
)
48 dt_dof_t
*ddo
= &dtp
->dt_dof
;
52 ddo
->ddo_strsec
= DOF_SECIDX_NONE
;
53 ddo
->ddo_xlimport
= NULL
;
54 ddo
->ddo_xlexport
= NULL
;
56 dt_buf_create(dtp
, &ddo
->ddo_secs
, "section headers", 0);
57 dt_buf_create(dtp
, &ddo
->ddo_strs
, "string table", 0);
58 dt_buf_create(dtp
, &ddo
->ddo_ldata
, "loadable data", 0);
59 dt_buf_create(dtp
, &ddo
->ddo_udata
, "unloadable data", 0);
61 dt_buf_create(dtp
, &ddo
->ddo_probes
, "probe data", 0);
62 dt_buf_create(dtp
, &ddo
->ddo_args
, "probe args", 0);
63 dt_buf_create(dtp
, &ddo
->ddo_offs
, "probe offs", 0);
64 dt_buf_create(dtp
, &ddo
->ddo_enoffs
, "probe is-enabled offs", 0);
65 dt_buf_create(dtp
, &ddo
->ddo_rels
, "probe rels", 0);
67 dt_buf_create(dtp
, &ddo
->ddo_xlms
, "xlate members", 0);
71 dt_dof_fini(dtrace_hdl_t
*dtp
)
73 dt_dof_t
*ddo
= &dtp
->dt_dof
;
75 dt_free(dtp
, ddo
->ddo_xlimport
);
76 dt_free(dtp
, ddo
->ddo_xlexport
);
78 dt_buf_destroy(dtp
, &ddo
->ddo_secs
);
79 dt_buf_destroy(dtp
, &ddo
->ddo_strs
);
80 dt_buf_destroy(dtp
, &ddo
->ddo_ldata
);
81 dt_buf_destroy(dtp
, &ddo
->ddo_udata
);
83 dt_buf_destroy(dtp
, &ddo
->ddo_probes
);
84 dt_buf_destroy(dtp
, &ddo
->ddo_args
);
85 dt_buf_destroy(dtp
, &ddo
->ddo_offs
);
86 dt_buf_destroy(dtp
, &ddo
->ddo_enoffs
);
87 dt_buf_destroy(dtp
, &ddo
->ddo_rels
);
89 dt_buf_destroy(dtp
, &ddo
->ddo_xlms
);
93 dt_dof_reset(dtrace_hdl_t
*dtp
, dtrace_prog_t
*pgp
)
95 dt_dof_t
*ddo
= &dtp
->dt_dof
;
96 uint_t i
, nx
= dtp
->dt_xlatorid
;
98 assert(ddo
->ddo_hdl
== dtp
);
102 ddo
->ddo_strsec
= DOF_SECIDX_NONE
;
104 dt_free(dtp
, ddo
->ddo_xlimport
);
105 dt_free(dtp
, ddo
->ddo_xlexport
);
107 ddo
->ddo_xlimport
= dt_alloc(dtp
, sizeof (dof_secidx_t
) * nx
);
108 ddo
->ddo_xlexport
= dt_alloc(dtp
, sizeof (dof_secidx_t
) * nx
);
110 if (nx
!= 0 && (ddo
->ddo_xlimport
== NULL
|| ddo
->ddo_xlexport
== NULL
))
111 return (-1); /* errno is set for us */
113 for (i
= 0; i
< nx
; i
++) {
114 ddo
->ddo_xlimport
[i
] = DOF_SECIDX_NONE
;
115 ddo
->ddo_xlexport
[i
] = DOF_SECIDX_NONE
;
118 dt_buf_reset(dtp
, &ddo
->ddo_secs
);
119 dt_buf_reset(dtp
, &ddo
->ddo_strs
);
120 dt_buf_reset(dtp
, &ddo
->ddo_ldata
);
121 dt_buf_reset(dtp
, &ddo
->ddo_udata
);
123 dt_buf_reset(dtp
, &ddo
->ddo_probes
);
124 dt_buf_reset(dtp
, &ddo
->ddo_args
);
125 dt_buf_reset(dtp
, &ddo
->ddo_offs
);
126 dt_buf_reset(dtp
, &ddo
->ddo_enoffs
);
127 dt_buf_reset(dtp
, &ddo
->ddo_rels
);
129 dt_buf_reset(dtp
, &ddo
->ddo_xlms
);
134 * Add a loadable DOF section to the file using the specified data buffer and
135 * the specified DOF section attributes. DOF_SECF_LOAD must be set in flags.
136 * If 'data' is NULL, the caller is responsible for manipulating the ldata buf.
139 dof_add_lsect(dt_dof_t
*ddo
, const void *data
, uint32_t type
,
140 uint32_t align
, uint32_t flags
, uint32_t entsize
, uint64_t size
)
142 dtrace_hdl_t
*dtp
= ddo
->ddo_hdl
;
146 s
.dofs_align
= align
;
147 s
.dofs_flags
= flags
| DOF_SECF_LOAD
;
148 s
.dofs_entsize
= entsize
;
149 s
.dofs_offset
= dt_buf_offset(&ddo
->ddo_ldata
, align
);
152 dt_buf_write(dtp
, &ddo
->ddo_secs
, &s
, sizeof (s
), sizeof (uint64_t));
155 dt_buf_write(dtp
, &ddo
->ddo_ldata
, data
, size
, align
);
157 return (ddo
->ddo_nsecs
++);
161 * Add an unloadable DOF section to the file using the specified data buffer
162 * and DOF section attributes. DOF_SECF_LOAD must *not* be set in flags.
163 * If 'data' is NULL, the caller is responsible for manipulating the udata buf.
166 dof_add_usect(dt_dof_t
*ddo
, const void *data
, uint32_t type
,
167 uint32_t align
, uint32_t flags
, uint32_t entsize
, uint64_t size
)
169 dtrace_hdl_t
*dtp
= ddo
->ddo_hdl
;
173 s
.dofs_align
= align
;
174 s
.dofs_flags
= flags
& ~DOF_SECF_LOAD
;
175 s
.dofs_entsize
= entsize
;
176 s
.dofs_offset
= dt_buf_offset(&ddo
->ddo_udata
, align
);
179 dt_buf_write(dtp
, &ddo
->ddo_secs
, &s
, sizeof (s
), sizeof (uint64_t));
182 dt_buf_write(dtp
, &ddo
->ddo_udata
, data
, size
, align
);
184 return (ddo
->ddo_nsecs
++);
188 * Add a string to the global string table associated with the DOF. The offset
189 * of the string is returned as an index into the string table.
192 dof_add_string(dt_dof_t
*ddo
, const char *s
)
194 dt_buf_t
*bp
= &ddo
->ddo_strs
;
195 dof_stridx_t i
= dt_buf_len(bp
);
197 if (i
!= 0 && (s
== NULL
|| *s
== '\0'))
198 return (0); /* string table has \0 at offset 0 */
200 dt_buf_write(ddo
->ddo_hdl
, bp
, s
, strlen(s
) + 1, sizeof (char));
205 dof_attr(const dtrace_attribute_t
*ap
)
207 return (DOF_ATTR(ap
->dtat_name
, ap
->dtat_data
, ap
->dtat_class
));
211 dof_add_difo(dt_dof_t
*ddo
, const dtrace_difo_t
*dp
)
213 dof_secidx_t dsecs
[5]; /* enough for all possible DIFO sections */
220 dof_secidx_t strsec
= DOF_SECIDX_NONE
;
221 dof_secidx_t intsec
= DOF_SECIDX_NONE
;
222 dof_secidx_t hdrsec
= DOF_SECIDX_NONE
;
224 if (dp
->dtdo_buf
!= NULL
) {
225 dsecs
[nsecs
++] = dof_add_lsect(ddo
, dp
->dtdo_buf
,
226 DOF_SECT_DIF
, sizeof (dif_instr_t
), 0,
227 sizeof (dif_instr_t
), sizeof (dif_instr_t
) * dp
->dtdo_len
);
230 if (dp
->dtdo_inttab
!= NULL
) {
231 dsecs
[nsecs
++] = intsec
= dof_add_lsect(ddo
, dp
->dtdo_inttab
,
232 DOF_SECT_INTTAB
, sizeof (uint64_t), 0,
233 sizeof (uint64_t), sizeof (uint64_t) * dp
->dtdo_intlen
);
236 if (dp
->dtdo_strtab
!= NULL
) {
237 dsecs
[nsecs
++] = strsec
= dof_add_lsect(ddo
, dp
->dtdo_strtab
,
238 DOF_SECT_STRTAB
, sizeof (char), 0, 0, dp
->dtdo_strlen
);
241 if (dp
->dtdo_vartab
!= NULL
) {
242 dsecs
[nsecs
++] = dof_add_lsect(ddo
, dp
->dtdo_vartab
,
243 DOF_SECT_VARTAB
, sizeof (uint_t
), 0, sizeof (dtrace_difv_t
),
244 sizeof (dtrace_difv_t
) * dp
->dtdo_varlen
);
247 if (dp
->dtdo_xlmtab
!= NULL
) {
248 dof_xlref_t
*xlt
, *xlp
;
251 xlt
= alloca(sizeof (dof_xlref_t
) * dp
->dtdo_xlmlen
);
252 pnp
= dp
->dtdo_xlmtab
;
255 * dtdo_xlmtab contains pointers to the translator members.
256 * The translator itself is in sect ddo_xlimport[dxp->dx_id].
257 * The XLMEMBERS entries are in order by their dn_membid, so
258 * the member section offset is the population count of bits
259 * in ddo_pgp->dp_xlrefs[] up to and not including dn_membid.
261 for (xlp
= xlt
; xlp
< xlt
+ dp
->dtdo_xlmlen
; xlp
++) {
262 dt_node_t
*dnp
= *pnp
++;
263 dt_xlator_t
*dxp
= dnp
->dn_membexpr
->dn_xlator
;
265 xlp
->dofxr_xlator
= ddo
->ddo_xlimport
[dxp
->dx_id
];
266 xlp
->dofxr_member
= dt_popcb(
267 ddo
->ddo_pgp
->dp_xrefs
[dxp
->dx_id
], dnp
->dn_membid
);
268 xlp
->dofxr_argn
= (uint32_t)dxp
->dx_arg
;
271 dsecs
[nsecs
++] = dof_add_lsect(ddo
, xlt
, DOF_SECT_XLTAB
,
272 sizeof (dof_secidx_t
), 0, sizeof (dof_xlref_t
),
273 sizeof (dof_xlref_t
) * dp
->dtdo_xlmlen
);
277 * Copy the return type and the array of section indices that form the
278 * DIFO into a single dof_difohdr_t and then add DOF_SECT_DIFOHDR.
280 assert(nsecs
<= sizeof (dsecs
) / sizeof (dsecs
[0]));
281 dofd
= alloca(sizeof (dtrace_diftype_t
) + sizeof (dsecs
));
282 bcopy(&dp
->dtdo_rtype
, &dofd
->dofd_rtype
, sizeof (dtrace_diftype_t
));
283 bcopy(dsecs
, &dofd
->dofd_links
, sizeof (dof_secidx_t
) * nsecs
);
285 hdrsec
= dof_add_lsect(ddo
, dofd
, DOF_SECT_DIFOHDR
,
286 sizeof (dof_secidx_t
), 0, 0,
287 sizeof (dtrace_diftype_t
) + sizeof (dof_secidx_t
) * nsecs
);
290 * Add any other sections related to dtrace_difo_t. These are not
291 * referenced in dof_difohdr_t because they are not used by emulation.
293 if (dp
->dtdo_kreltab
!= NULL
) {
294 relsec
= dof_add_lsect(ddo
, dp
->dtdo_kreltab
, DOF_SECT_RELTAB
,
295 sizeof (uint64_t), 0, sizeof (dof_relodesc_t
),
296 sizeof (dof_relodesc_t
) * dp
->dtdo_krelen
);
299 * This code assumes the target of all relocations is the
300 * integer table 'intsec' (DOF_SECT_INTTAB). If other sections
301 * need relocation in the future this will need to change.
303 dofr
.dofr_strtab
= strsec
;
304 dofr
.dofr_relsec
= relsec
;
305 dofr
.dofr_tgtsec
= intsec
;
307 (void) dof_add_lsect(ddo
, &dofr
, DOF_SECT_KRELHDR
,
308 sizeof (dof_secidx_t
), 0, 0, sizeof (dof_relohdr_t
));
311 if (dp
->dtdo_ureltab
!= NULL
) {
312 relsec
= dof_add_lsect(ddo
, dp
->dtdo_ureltab
, DOF_SECT_RELTAB
,
313 sizeof (uint64_t), 0, sizeof (dof_relodesc_t
),
314 sizeof (dof_relodesc_t
) * dp
->dtdo_urelen
);
317 * This code assumes the target of all relocations is the
318 * integer table 'intsec' (DOF_SECT_INTTAB). If other sections
319 * need relocation in the future this will need to change.
321 dofr
.dofr_strtab
= strsec
;
322 dofr
.dofr_relsec
= relsec
;
323 dofr
.dofr_tgtsec
= intsec
;
325 (void) dof_add_lsect(ddo
, &dofr
, DOF_SECT_URELHDR
,
326 sizeof (dof_secidx_t
), 0, 0, sizeof (dof_relohdr_t
));
333 dof_add_translator(dt_dof_t
*ddo
, const dt_xlator_t
*dxp
, uint_t type
)
335 dtrace_hdl_t
*dtp
= ddo
->ddo_hdl
;
336 dof_xlmember_t dofxm
;
340 char buf
[DT_TYPE_NAMELEN
];
344 assert(type
== DOF_SECT_XLIMPORT
|| type
== DOF_SECT_XLEXPORT
);
345 xst
= type
== DOF_SECT_XLIMPORT
? ddo
->ddo_xlimport
: ddo
->ddo_xlexport
;
347 if (xst
[dxp
->dx_id
] != DOF_SECIDX_NONE
)
348 return; /* translator has already been emitted */
350 dt_buf_reset(dtp
, &ddo
->ddo_xlms
);
353 * Generate an array of dof_xlmember_t's into ddo_xlms. If we are
354 * importing the translator, add only those members referenced by the
355 * program and set the dofxm_difo reference of each member to NONE. If
356 * we're exporting the translator, add all members and a DIFO for each.
358 for (dnp
= dxp
->dx_members
; dnp
!= NULL
; dnp
= dnp
->dn_list
, i
++) {
359 if (type
== DOF_SECT_XLIMPORT
) {
360 if (!BT_TEST(ddo
->ddo_pgp
->dp_xrefs
[dxp
->dx_id
], i
))
361 continue; /* member is not referenced */
362 dofxm
.dofxm_difo
= DOF_SECIDX_NONE
;
364 dofxm
.dofxm_difo
= dof_add_difo(ddo
,
365 dxp
->dx_membdif
[dnp
->dn_membid
]);
368 dofxm
.dofxm_name
= dof_add_string(ddo
, dnp
->dn_membname
);
369 dt_node_diftype(dtp
, dnp
, &dofxm
.dofxm_type
);
371 dt_buf_write(dtp
, &ddo
->ddo_xlms
,
372 &dofxm
, sizeof (dofxm
), sizeof (uint32_t));
375 dofxl
.dofxl_members
= dof_add_lsect(ddo
, NULL
, DOF_SECT_XLMEMBERS
,
376 sizeof (uint32_t), 0, sizeof (dofxm
), dt_buf_len(&ddo
->ddo_xlms
));
378 dt_buf_concat(dtp
, &ddo
->ddo_ldata
, &ddo
->ddo_xlms
, sizeof (uint32_t));
380 dofxl
.dofxl_strtab
= ddo
->ddo_strsec
;
381 dofxl
.dofxl_argv
= dof_add_string(ddo
, ctf_type_name(
382 dxp
->dx_src_ctfp
, dxp
->dx_src_type
, buf
, sizeof (buf
)));
383 dofxl
.dofxl_argc
= 1;
384 dofxl
.dofxl_type
= dof_add_string(ddo
, ctf_type_name(
385 dxp
->dx_dst_ctfp
, dxp
->dx_dst_type
, buf
, sizeof (buf
)));
386 dofxl
.dofxl_attr
= dof_attr(&dxp
->dx_souid
.di_attr
);
388 xst
[dxp
->dx_id
] = dof_add_lsect(ddo
, &dofxl
, type
,
389 sizeof (uint32_t), 0, 0, sizeof (dofxl
));
394 dof_add_probe(dt_idhash_t
*dhp
, dt_ident_t
*idp
, void *data
)
396 dt_dof_t
*ddo
= data
;
397 dtrace_hdl_t
*dtp
= ddo
->ddo_hdl
;
398 dt_probe_t
*prp
= idp
->di_data
;
402 dt_probe_instance_t
*pip
;
405 char buf
[DT_TYPE_NAMELEN
];
408 dofpr
.dofpr_addr
= 0;
409 dofpr
.dofpr_name
= dof_add_string(ddo
, prp
->pr_name
);
410 dofpr
.dofpr_nargv
= dt_buf_len(&ddo
->ddo_strs
);
412 for (dnp
= prp
->pr_nargs
; dnp
!= NULL
; dnp
= dnp
->dn_list
) {
413 (void) dof_add_string(ddo
, ctf_type_name(dnp
->dn_ctfp
,
414 dnp
->dn_type
, buf
, sizeof (buf
)));
417 dofpr
.dofpr_xargv
= dt_buf_len(&ddo
->ddo_strs
);
419 for (dnp
= prp
->pr_xargs
; dnp
!= NULL
; dnp
= dnp
->dn_list
) {
420 (void) dof_add_string(ddo
, ctf_type_name(dnp
->dn_ctfp
,
421 dnp
->dn_type
, buf
, sizeof (buf
)));
424 dofpr
.dofpr_argidx
= dt_buf_len(&ddo
->ddo_args
) / sizeof (uint8_t);
426 for (i
= 0; i
< prp
->pr_xargc
; i
++) {
427 dt_buf_write(dtp
, &ddo
->ddo_args
, &prp
->pr_mapping
[i
],
428 sizeof (uint8_t), sizeof (uint8_t));
431 dofpr
.dofpr_nargc
= prp
->pr_nargc
;
432 dofpr
.dofpr_xargc
= prp
->pr_xargc
;
433 dofpr
.dofpr_pad1
= 0;
434 dofpr
.dofpr_pad2
= 0;
436 for (pip
= prp
->pr_inst
; pip
!= NULL
; pip
= pip
->pi_next
) {
437 dt_dprintf("adding probe for %s:%s\n", pip
->pi_fname
,
440 dofpr
.dofpr_func
= dof_add_string(ddo
, pip
->pi_fname
);
443 * There should be one probe offset or is-enabled probe offset
444 * or else this probe instance won't have been created. The
445 * kernel will reject DOF which has a probe with no offsets.
447 assert(pip
->pi_noffs
+ pip
->pi_nenoffs
> 0);
450 dt_buf_len(&ddo
->ddo_offs
) / sizeof (uint32_t);
451 dofpr
.dofpr_noffs
= pip
->pi_noffs
;
452 dt_buf_write(dtp
, &ddo
->ddo_offs
, pip
->pi_offs
,
453 pip
->pi_noffs
* sizeof (uint32_t), sizeof (uint32_t));
455 dofpr
.dofpr_enoffidx
=
456 dt_buf_len(&ddo
->ddo_enoffs
) / sizeof (uint32_t);
457 dofpr
.dofpr_nenoffs
= pip
->pi_nenoffs
;
458 dt_buf_write(dtp
, &ddo
->ddo_enoffs
, pip
->pi_enoffs
,
459 pip
->pi_nenoffs
* sizeof (uint32_t), sizeof (uint32_t));
462 * If pi_rname isn't set, the relocation will be against the
463 * function name. If it is, the relocation will be against
464 * pi_rname. This will be used if the function is scoped
465 * locally so an alternate symbol is added for the purpose
466 * of this relocation.
468 if (pip
->pi_rname
[0] == '\0')
469 dofr
.dofr_name
= dofpr
.dofpr_func
;
471 dofr
.dofr_name
= dof_add_string(ddo
, pip
->pi_rname
);
472 dofr
.dofr_type
= DOF_RELO_SETX
;
473 dofr
.dofr_offset
= dt_buf_len(&ddo
->ddo_probes
);
476 dt_buf_write(dtp
, &ddo
->ddo_rels
, &dofr
,
477 sizeof (dofr
), sizeof (uint64_t));
479 dt_buf_write(dtp
, &ddo
->ddo_probes
, &dofpr
,
480 sizeof (dofpr
), sizeof (uint64_t));
487 dof_add_provider(dt_dof_t
*ddo
, const dt_provider_t
*pvp
)
489 dtrace_hdl_t
*dtp
= ddo
->ddo_hdl
;
490 dof_provider_t dofpv
;
497 if (pvp
->pv_flags
& DT_PROVIDER_IMPL
) {
499 * ignore providers that are exported by dtrace(7D)
504 nxr
= dt_popcb(pvp
->pv_xrefs
, pvp
->pv_xrmax
);
505 dofs
= alloca(sizeof (dof_secidx_t
) * (nxr
+ 1));
506 xr
= 1; /* reserve dofs[0] for the provider itself */
509 * For each translator referenced by the provider (pv_xrefs), emit an
510 * exported translator section for it if one hasn't been created yet.
512 for (i
= 0; i
< pvp
->pv_xrmax
; i
++) {
513 if (BT_TEST(pvp
->pv_xrefs
, i
) &&
514 dtp
->dt_xlatemode
== DT_XL_DYNAMIC
) {
515 dof_add_translator(ddo
,
516 dt_xlator_lookup_id(dtp
, i
), DOF_SECT_XLEXPORT
);
517 dofs
[xr
++] = ddo
->ddo_xlexport
[i
];
521 dt_buf_reset(dtp
, &ddo
->ddo_probes
);
522 dt_buf_reset(dtp
, &ddo
->ddo_args
);
523 dt_buf_reset(dtp
, &ddo
->ddo_offs
);
524 dt_buf_reset(dtp
, &ddo
->ddo_enoffs
);
525 dt_buf_reset(dtp
, &ddo
->ddo_rels
);
527 (void) dt_idhash_iter(pvp
->pv_probes
, dof_add_probe
, ddo
);
529 if (dt_buf_len(&ddo
->ddo_probes
) == 0)
530 return (dt_set_errno(dtp
, EDT_NOPROBES
));
532 dofpv
.dofpv_probes
= dof_add_lsect(ddo
, NULL
, DOF_SECT_PROBES
,
533 sizeof (uint64_t), 0, sizeof (dof_probe_t
),
534 dt_buf_len(&ddo
->ddo_probes
));
536 dt_buf_concat(dtp
, &ddo
->ddo_ldata
,
537 &ddo
->ddo_probes
, sizeof (uint64_t));
539 dofpv
.dofpv_prargs
= dof_add_lsect(ddo
, NULL
, DOF_SECT_PRARGS
,
540 sizeof (uint8_t), 0, sizeof (uint8_t), dt_buf_len(&ddo
->ddo_args
));
542 dt_buf_concat(dtp
, &ddo
->ddo_ldata
, &ddo
->ddo_args
, sizeof (uint8_t));
544 dofpv
.dofpv_proffs
= dof_add_lsect(ddo
, NULL
, DOF_SECT_PROFFS
,
545 sizeof (uint_t
), 0, sizeof (uint_t
), dt_buf_len(&ddo
->ddo_offs
));
547 dt_buf_concat(dtp
, &ddo
->ddo_ldata
, &ddo
->ddo_offs
, sizeof (uint_t
));
549 if ((sz
= dt_buf_len(&ddo
->ddo_enoffs
)) != 0) {
550 dofpv
.dofpv_prenoffs
= dof_add_lsect(ddo
, NULL
,
551 DOF_SECT_PRENOFFS
, sizeof (uint_t
), 0, sizeof (uint_t
), sz
);
553 dofpv
.dofpv_prenoffs
= DOF_SECT_NONE
;
556 dt_buf_concat(dtp
, &ddo
->ddo_ldata
, &ddo
->ddo_enoffs
, sizeof (uint_t
));
558 dofpv
.dofpv_strtab
= ddo
->ddo_strsec
;
559 dofpv
.dofpv_name
= dof_add_string(ddo
, pvp
->pv_desc
.dtvd_name
);
561 dofpv
.dofpv_provattr
= dof_attr(&pvp
->pv_desc
.dtvd_attr
.dtpa_provider
);
562 dofpv
.dofpv_modattr
= dof_attr(&pvp
->pv_desc
.dtvd_attr
.dtpa_mod
);
563 dofpv
.dofpv_funcattr
= dof_attr(&pvp
->pv_desc
.dtvd_attr
.dtpa_func
);
564 dofpv
.dofpv_nameattr
= dof_attr(&pvp
->pv_desc
.dtvd_attr
.dtpa_name
);
565 dofpv
.dofpv_argsattr
= dof_attr(&pvp
->pv_desc
.dtvd_attr
.dtpa_args
);
567 dofs
[0] = dof_add_lsect(ddo
, &dofpv
, DOF_SECT_PROVIDER
,
568 sizeof (dof_secidx_t
), 0, 0, sizeof (dof_provider_t
));
570 dofr
.dofr_strtab
= dofpv
.dofpv_strtab
;
571 dofr
.dofr_tgtsec
= dofpv
.dofpv_probes
;
572 dofr
.dofr_relsec
= dof_add_lsect(ddo
, NULL
, DOF_SECT_RELTAB
,
573 sizeof (uint64_t), 0, sizeof (dof_relodesc_t
),
574 dt_buf_len(&ddo
->ddo_rels
));
576 dt_buf_concat(dtp
, &ddo
->ddo_ldata
, &ddo
->ddo_rels
, sizeof (uint64_t));
578 (void) dof_add_lsect(ddo
, &dofr
, DOF_SECT_URELHDR
,
579 sizeof (dof_secidx_t
), 0, 0, sizeof (dof_relohdr_t
));
581 if (nxr
!= 0 && dtp
->dt_xlatemode
== DT_XL_DYNAMIC
) {
582 (void) dof_add_lsect(ddo
, dofs
, DOF_SECT_PREXPORT
,
583 sizeof (dof_secidx_t
), 0, sizeof (dof_secidx_t
),
584 sizeof (dof_secidx_t
) * (nxr
+ 1));
591 dof_hdr(dtrace_hdl_t
*dtp
, uint8_t dofversion
, dof_hdr_t
*hp
)
594 * If our config values cannot fit in a uint8_t, we can't generate a
595 * DOF header since the values won't fit. This can only happen if the
596 * user forcibly compiles a program with an artificial configuration.
598 if (dtp
->dt_conf
.dtc_difversion
> UINT8_MAX
||
599 dtp
->dt_conf
.dtc_difintregs
> UINT8_MAX
||
600 dtp
->dt_conf
.dtc_diftupregs
> UINT8_MAX
)
601 return (dt_set_errno(dtp
, EOVERFLOW
));
603 bzero(hp
, sizeof (dof_hdr_t
));
605 hp
->dofh_ident
[DOF_ID_MAG0
] = DOF_MAG_MAG0
;
606 hp
->dofh_ident
[DOF_ID_MAG1
] = DOF_MAG_MAG1
;
607 hp
->dofh_ident
[DOF_ID_MAG2
] = DOF_MAG_MAG2
;
608 hp
->dofh_ident
[DOF_ID_MAG3
] = DOF_MAG_MAG3
;
610 if (dtp
->dt_conf
.dtc_ctfmodel
== CTF_MODEL_LP64
)
611 hp
->dofh_ident
[DOF_ID_MODEL
] = DOF_MODEL_LP64
;
613 hp
->dofh_ident
[DOF_ID_MODEL
] = DOF_MODEL_ILP32
;
615 hp
->dofh_ident
[DOF_ID_ENCODING
] = DOF_ENCODE_NATIVE
;
616 hp
->dofh_ident
[DOF_ID_VERSION
] = dofversion
;
617 hp
->dofh_ident
[DOF_ID_DIFVERS
] = dtp
->dt_conf
.dtc_difversion
;
618 hp
->dofh_ident
[DOF_ID_DIFIREG
] = dtp
->dt_conf
.dtc_difintregs
;
619 hp
->dofh_ident
[DOF_ID_DIFTREG
] = dtp
->dt_conf
.dtc_diftupregs
;
621 hp
->dofh_hdrsize
= sizeof (dof_hdr_t
);
622 hp
->dofh_secsize
= sizeof (dof_sec_t
);
623 hp
->dofh_secoff
= sizeof (dof_hdr_t
);
629 dtrace_dof_create(dtrace_hdl_t
*dtp
, dtrace_prog_t
*pgp
, uint_t flags
)
631 dt_dof_t
*ddo
= &dtp
->dt_dof
;
633 const dtrace_ecbdesc_t
*edp
, *last
;
634 const dtrace_probedesc_t
*pdp
;
635 const dtrace_actdesc_t
*ap
;
636 const dt_stmt_t
*stp
;
652 if (flags
& ~DTRACE_D_MASK
) {
653 (void) dt_set_errno(dtp
, EINVAL
);
657 flags
|= dtp
->dt_dflags
;
659 if (dof_hdr(dtp
, pgp
->dp_dofversion
, &h
) != 0)
662 if (dt_dof_reset(dtp
, pgp
) != 0)
666 * Iterate through the statement list computing the maximum number of
667 * actions and the maximum format string for allocating local buffers.
669 for (last
= NULL
, stp
= dt_list_next(&pgp
->dp_stmts
);
670 stp
!= NULL
; stp
= dt_list_next(stp
), last
= edp
) {
672 dtrace_stmtdesc_t
*sdp
= stp
->ds_desc
;
673 dtrace_actdesc_t
*ap
= sdp
->dtsd_action
;
675 if (sdp
->dtsd_fmtdata
!= NULL
) {
676 i
= dtrace_printf_format(dtp
,
677 sdp
->dtsd_fmtdata
, NULL
, 0);
678 maxfmt
= MAX(maxfmt
, i
);
681 if ((edp
= sdp
->dtsd_ecbdesc
) == last
)
682 continue; /* same ecb as previous statement */
684 for (i
= 0, ap
= edp
->dted_action
; ap
; ap
= ap
->dtad_next
)
687 maxacts
= MAX(maxacts
, i
);
690 dofa
= alloca(sizeof (dof_actdesc_t
) * maxacts
);
691 fmt
= alloca(maxfmt
+ 1);
693 ddo
->ddo_strsec
= dof_add_lsect(ddo
, NULL
, DOF_SECT_STRTAB
, 1, 0, 0, 0);
694 (void) dof_add_string(ddo
, "");
697 * If there are references to dynamic translators in the program, add
698 * an imported translator table entry for each referenced translator.
700 if (pgp
->dp_xrefslen
!= 0) {
701 for (dxp
= dt_list_next(&dtp
->dt_xlators
);
702 dxp
!= NULL
; dxp
= dt_list_next(dxp
)) {
703 if (dxp
->dx_id
< pgp
->dp_xrefslen
&&
704 pgp
->dp_xrefs
[dxp
->dx_id
] != NULL
)
705 dof_add_translator(ddo
, dxp
, DOF_SECT_XLIMPORT
);
710 * Now iterate through the statement list, creating the DOF section
711 * headers and data for each one and adding them to our buffers.
713 for (last
= NULL
, stp
= dt_list_next(&pgp
->dp_stmts
);
714 stp
!= NULL
; stp
= dt_list_next(stp
), last
= edp
) {
716 dof_secidx_t probesec
= DOF_SECIDX_NONE
;
717 dof_secidx_t prdsec
= DOF_SECIDX_NONE
;
718 dof_secidx_t actsec
= DOF_SECIDX_NONE
;
720 const dt_stmt_t
*next
= stp
;
721 dtrace_stmtdesc_t
*sdp
= stp
->ds_desc
;
722 dof_stridx_t strndx
= 0;
723 dof_probedesc_t dofp
;
727 if ((edp
= stp
->ds_desc
->dtsd_ecbdesc
) == last
)
728 continue; /* same ecb as previous statement */
730 pdp
= &edp
->dted_probe
;
733 * Add a DOF_SECT_PROBEDESC for the ECB's probe description,
734 * and copy the probe description strings into the string table.
736 dofp
.dofp_strtab
= ddo
->ddo_strsec
;
737 dofp
.dofp_provider
= dof_add_string(ddo
, pdp
->dtpd_provider
);
738 dofp
.dofp_mod
= dof_add_string(ddo
, pdp
->dtpd_mod
);
739 dofp
.dofp_func
= dof_add_string(ddo
, pdp
->dtpd_func
);
740 dofp
.dofp_name
= dof_add_string(ddo
, pdp
->dtpd_name
);
741 dofp
.dofp_id
= pdp
->dtpd_id
;
743 probesec
= dof_add_lsect(ddo
, &dofp
, DOF_SECT_PROBEDESC
,
744 sizeof (dof_secidx_t
), 0,
745 sizeof (dof_probedesc_t
), sizeof (dof_probedesc_t
));
748 * If there is a predicate DIFO associated with the ecbdesc,
749 * write out the DIFO sections and save the DIFO section index.
751 if (edp
->dted_pred
.dtpdd_difo
!= NULL
)
752 prdsec
= dof_add_difo(ddo
, edp
->dted_pred
.dtpdd_difo
);
755 * Now iterate through the action list generating DIFOs as
756 * referenced therein and adding action descriptions to 'dofa'.
758 for (i
= 0, ap
= edp
->dted_action
;
759 ap
!= NULL
; ap
= ap
->dtad_next
, i
++) {
761 if (ap
->dtad_difo
!= NULL
) {
763 dof_add_difo(ddo
, ap
->dtad_difo
);
765 dofa
[i
].dofa_difo
= DOF_SECIDX_NONE
;
768 * If the first action in a statement has string data,
769 * add the string to the global string table. This can
770 * be due either to a printf() format string
771 * (dtsd_fmtdata) or a print() type string
774 if (sdp
!= NULL
&& ap
== sdp
->dtsd_action
) {
775 if (sdp
->dtsd_fmtdata
!= NULL
) {
776 (void) dtrace_printf_format(dtp
,
777 sdp
->dtsd_fmtdata
, fmt
, maxfmt
+ 1);
778 strndx
= dof_add_string(ddo
, fmt
);
779 } else if (sdp
->dtsd_strdata
!= NULL
) {
780 strndx
= dof_add_string(ddo
,
783 strndx
= 0; /* use dtad_arg instead */
786 if ((next
= dt_list_next(next
)) != NULL
)
793 dofa
[i
].dofa_arg
= strndx
;
794 dofa
[i
].dofa_strtab
= ddo
->ddo_strsec
;
796 dofa
[i
].dofa_arg
= ap
->dtad_arg
;
797 dofa
[i
].dofa_strtab
= DOF_SECIDX_NONE
;
800 dofa
[i
].dofa_kind
= ap
->dtad_kind
;
801 dofa
[i
].dofa_ntuple
= ap
->dtad_ntuple
;
802 dofa
[i
].dofa_uarg
= ap
->dtad_uarg
;
806 actsec
= dof_add_lsect(ddo
, dofa
, DOF_SECT_ACTDESC
,
807 sizeof (uint64_t), 0, sizeof (dof_actdesc_t
),
808 sizeof (dof_actdesc_t
) * i
);
812 * Now finally, add the DOF_SECT_ECBDESC referencing all the
813 * previously created sub-sections.
815 dofe
.dofe_probes
= probesec
;
816 dofe
.dofe_pred
= prdsec
;
817 dofe
.dofe_actions
= actsec
;
819 dofe
.dofe_uarg
= edp
->dted_uarg
;
821 (void) dof_add_lsect(ddo
, &dofe
, DOF_SECT_ECBDESC
,
822 sizeof (uint64_t), 0, 0, sizeof (dof_ecbdesc_t
));
826 * If any providers are user-defined, output DOF sections corresponding
827 * to the providers and the probes and arguments that they define.
829 if (flags
& DTRACE_D_PROBES
) {
830 for (pvp
= dt_list_next(&dtp
->dt_provlist
);
831 pvp
!= NULL
; pvp
= dt_list_next(pvp
)) {
832 if (dof_add_provider(ddo
, pvp
) != 0)
838 * If we're not stripping unloadable sections, generate compiler
839 * comments and any other unloadable miscellany.
841 if (!(flags
& DTRACE_D_STRIP
)) {
842 (void) dof_add_usect(ddo
, _dtrace_version
, DOF_SECT_COMMENTS
,
843 sizeof (char), 0, 0, strlen(_dtrace_version
) + 1);
844 (void) dof_add_usect(ddo
, &dtp
->dt_uts
, DOF_SECT_UTSNAME
,
845 sizeof (char), 0, 0, sizeof (struct utsname
));
849 * Compute and fill in the appropriate values for the dof_hdr_t's
850 * dofh_secnum, dofh_loadsz, and dofh_filez values.
852 h
.dofh_secnum
= ddo
->ddo_nsecs
;
853 ssize
= sizeof (h
) + dt_buf_len(&ddo
->ddo_secs
);
855 h
.dofh_loadsz
= ssize
+
856 dt_buf_len(&ddo
->ddo_ldata
) +
857 dt_buf_len(&ddo
->ddo_strs
);
859 if (dt_buf_len(&ddo
->ddo_udata
) != 0) {
860 lsize
= roundup(h
.dofh_loadsz
, sizeof (uint64_t));
861 h
.dofh_filesz
= lsize
+ dt_buf_len(&ddo
->ddo_udata
);
863 lsize
= h
.dofh_loadsz
;
864 h
.dofh_filesz
= lsize
;
868 * Set the global DOF_SECT_STRTAB's offset to be after the header,
869 * section headers, and other loadable data. Since we're going to
870 * iterate over the buffer data directly, we must check for errors.
872 if ((i
= dt_buf_error(&ddo
->ddo_secs
)) != 0) {
873 (void) dt_set_errno(dtp
, i
);
877 sp
= dt_buf_ptr(&ddo
->ddo_secs
);
878 assert(sp
[ddo
->ddo_strsec
].dofs_type
== DOF_SECT_STRTAB
);
879 assert(ssize
== sizeof (h
) + sizeof (dof_sec_t
) * ddo
->ddo_nsecs
);
881 sp
[ddo
->ddo_strsec
].dofs_offset
= ssize
+ dt_buf_len(&ddo
->ddo_ldata
);
882 sp
[ddo
->ddo_strsec
].dofs_size
= dt_buf_len(&ddo
->ddo_strs
);
885 * Now relocate all the other section headers by adding the appropriate
886 * delta to their respective dofs_offset values.
888 for (i
= 0; i
< ddo
->ddo_nsecs
; i
++, sp
++) {
889 if (i
== ddo
->ddo_strsec
)
890 continue; /* already relocated above */
892 if (sp
->dofs_flags
& DOF_SECF_LOAD
)
893 sp
->dofs_offset
+= ssize
;
895 sp
->dofs_offset
+= lsize
;
899 * Finally, assemble the complete in-memory DOF buffer by writing the
900 * header and then concatenating all our buffers. dt_buf_concat() will
901 * propagate any errors and cause dt_buf_claim() to return NULL.
903 dt_buf_create(dtp
, &dof
, "dof", h
.dofh_filesz
);
905 dt_buf_write(dtp
, &dof
, &h
, sizeof (h
), sizeof (uint64_t));
906 dt_buf_concat(dtp
, &dof
, &ddo
->ddo_secs
, sizeof (uint64_t));
907 dt_buf_concat(dtp
, &dof
, &ddo
->ddo_ldata
, sizeof (uint64_t));
908 dt_buf_concat(dtp
, &dof
, &ddo
->ddo_strs
, sizeof (char));
909 dt_buf_concat(dtp
, &dof
, &ddo
->ddo_udata
, sizeof (uint64_t));
911 return (dt_buf_claim(dtp
, &dof
));
915 dtrace_dof_destroy(dtrace_hdl_t
*dtp
, void *dof
)
921 dtrace_getopt_dof(dtrace_hdl_t
*dtp
)
926 int i
, nopts
= 0, len
= sizeof (dof_hdr_t
) +
927 roundup(sizeof (dof_sec_t
), sizeof (uint64_t));
929 for (i
= 0; i
< DTRACEOPT_MAX
; i
++) {
930 if (dtp
->dt_options
[i
] != DTRACEOPT_UNSET
)
934 len
+= sizeof (dof_optdesc_t
) * nopts
;
936 if ((dof
= dt_zalloc(dtp
, len
)) == NULL
||
937 dof_hdr(dtp
, DOF_VERSION
, dof
) != 0) {
942 dof
->dofh_secnum
= 1; /* only DOF_SECT_OPTDESC */
943 dof
->dofh_loadsz
= len
;
944 dof
->dofh_filesz
= len
;
947 * Fill in the option section header...
949 sec
= (dof_sec_t
*)((uintptr_t)dof
+ sizeof (dof_hdr_t
));
950 sec
->dofs_type
= DOF_SECT_OPTDESC
;
951 sec
->dofs_align
= sizeof (uint64_t);
952 sec
->dofs_flags
= DOF_SECF_LOAD
;
953 sec
->dofs_entsize
= sizeof (dof_optdesc_t
);
955 dofo
= (dof_optdesc_t
*)((uintptr_t)sec
+
956 roundup(sizeof (dof_sec_t
), sizeof (uint64_t)));
958 sec
->dofs_offset
= (uintptr_t)dofo
- (uintptr_t)dof
;
959 sec
->dofs_size
= sizeof (dof_optdesc_t
) * nopts
;
961 for (i
= 0; i
< DTRACEOPT_MAX
; i
++) {
962 if (dtp
->dt_options
[i
] == DTRACEOPT_UNSET
)
965 dofo
->dofo_option
= i
;
966 dofo
->dofo_strtab
= DOF_SECIDX_NONE
;
967 dofo
->dofo_value
= dtp
->dt_options
[i
];
975 dtrace_geterr_dof(dtrace_hdl_t
*dtp
)
977 if (dtp
->dt_errprog
!= NULL
)
978 return (dtrace_dof_create(dtp
, dtp
->dt_errprog
, 0));
980 (void) dt_set_errno(dtp
, EDT_BADERROR
);