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