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