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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/sysmacros.h> 31 32 #include <strings.h> 33 #include <alloca.h> 34 #include <assert.h> 35 #include <stdlib.h> 36 #include <errno.h> 37 #include <limits.h> 38 39 #include <dt_impl.h> 40 #include <dt_strtab.h> 41 #include <dt_provider.h> 42 #include <dt_dof.h> 43 44 void 45 dt_dof_init(dtrace_hdl_t *dtp) 46 { 47 dt_dof_t *ddo = &dtp->dt_dof; 48 49 ddo->ddo_hdl = dtp; 50 ddo->ddo_nsecs = 0; 51 ddo->ddo_strsec = DOF_SECIDX_NONE; 52 53 dt_buf_create(dtp, &ddo->ddo_secs, "section headers", 0); 54 dt_buf_create(dtp, &ddo->ddo_strs, "string table", 0); 55 dt_buf_create(dtp, &ddo->ddo_ldata, "loadable data", 0); 56 dt_buf_create(dtp, &ddo->ddo_udata, "unloadable data", 0); 57 58 dt_buf_create(dtp, &ddo->ddo_probes, "probe data", 0); 59 dt_buf_create(dtp, &ddo->ddo_args, "probe args", 0); 60 dt_buf_create(dtp, &ddo->ddo_offs, "probe offs", 0); 61 dt_buf_create(dtp, &ddo->ddo_rels, "probe rels", 0); 62 } 63 64 void 65 dt_dof_fini(dtrace_hdl_t *dtp) 66 { 67 dt_dof_t *ddo = &dtp->dt_dof; 68 69 dt_buf_destroy(dtp, &ddo->ddo_secs); 70 dt_buf_destroy(dtp, &ddo->ddo_strs); 71 dt_buf_destroy(dtp, &ddo->ddo_ldata); 72 dt_buf_destroy(dtp, &ddo->ddo_udata); 73 74 dt_buf_destroy(dtp, &ddo->ddo_probes); 75 dt_buf_destroy(dtp, &ddo->ddo_args); 76 dt_buf_destroy(dtp, &ddo->ddo_offs); 77 dt_buf_destroy(dtp, &ddo->ddo_rels); 78 } 79 80 void 81 dt_dof_reset(dtrace_hdl_t *dtp) 82 { 83 dt_dof_t *ddo = &dtp->dt_dof; 84 85 ddo->ddo_nsecs = 0; 86 ddo->ddo_strsec = DOF_SECIDX_NONE; 87 88 dt_buf_reset(dtp, &ddo->ddo_secs); 89 dt_buf_reset(dtp, &ddo->ddo_strs); 90 dt_buf_reset(dtp, &ddo->ddo_ldata); 91 dt_buf_reset(dtp, &ddo->ddo_udata); 92 93 dt_buf_reset(dtp, &ddo->ddo_probes); 94 dt_buf_reset(dtp, &ddo->ddo_args); 95 dt_buf_reset(dtp, &ddo->ddo_offs); 96 dt_buf_reset(dtp, &ddo->ddo_rels); 97 } 98 99 /* 100 * Add a loadable DOF section to the file using the specified data buffer and 101 * the specified DOF section attributes. DOF_SECF_LOAD must be set in flags. 102 * If 'data' is NULL, the caller is responsible for manipulating the ldata buf. 103 */ 104 static dof_secidx_t 105 dof_add_lsect(dt_dof_t *ddo, const void *data, uint32_t type, 106 uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size) 107 { 108 dtrace_hdl_t *dtp = ddo->ddo_hdl; 109 dof_sec_t s; 110 111 s.dofs_type = type; 112 s.dofs_align = align; 113 s.dofs_flags = flags | DOF_SECF_LOAD; 114 s.dofs_entsize = entsize; 115 s.dofs_offset = dt_buf_offset(&ddo->ddo_ldata, align); 116 s.dofs_size = size; 117 118 dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t)); 119 120 if (data != NULL) 121 dt_buf_write(dtp, &ddo->ddo_ldata, data, size, align); 122 123 return (ddo->ddo_nsecs++); 124 } 125 126 /* 127 * Add an unloadable DOF section to the file using the specified data buffer 128 * and DOF section attributes. DOF_SECF_LOAD must *not* be set in flags. 129 * If 'data' is NULL, the caller is responsible for manipulating the udata buf. 130 */ 131 static dof_secidx_t 132 dof_add_usect(dt_dof_t *ddo, const void *data, uint32_t type, 133 uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size) 134 { 135 dtrace_hdl_t *dtp = ddo->ddo_hdl; 136 dof_sec_t s; 137 138 s.dofs_type = type; 139 s.dofs_align = align; 140 s.dofs_flags = flags & ~DOF_SECF_LOAD; 141 s.dofs_entsize = entsize; 142 s.dofs_offset = dt_buf_offset(&ddo->ddo_udata, align); 143 s.dofs_size = size; 144 145 dt_buf_write(dtp, &ddo->ddo_secs, &s, sizeof (s), sizeof (uint64_t)); 146 147 if (data != NULL) 148 dt_buf_write(dtp, &ddo->ddo_udata, data, size, align); 149 150 return (ddo->ddo_nsecs++); 151 } 152 153 /* 154 * Add a string to the global string table associated with the DOF. The offset 155 * of the string is returned as an index into the string table. 156 */ 157 static dof_stridx_t 158 dof_add_string(dt_dof_t *ddo, const char *s) 159 { 160 dt_buf_t *bp = &ddo->ddo_strs; 161 dof_stridx_t i = dt_buf_len(bp); 162 163 if (i != 0 && (s == NULL || *s == '\0')) 164 return (0); /* string table has \0 at offset 0 */ 165 166 dt_buf_write(ddo->ddo_hdl, bp, s, strlen(s) + 1, sizeof (char)); 167 return (i); 168 } 169 170 static dof_attr_t 171 dof_attr(const dtrace_attribute_t *ap) 172 { 173 return (DOF_ATTR(ap->dtat_name, ap->dtat_data, ap->dtat_class)); 174 } 175 176 static dof_secidx_t 177 dof_add_difo(dt_dof_t *ddo, const dtrace_difo_t *dp) 178 { 179 dof_secidx_t dsecs[4]; /* enough for all possible DIFO sections */ 180 uint_t nsecs = 0; 181 182 dof_difohdr_t *dofd; 183 dof_relohdr_t dofr; 184 dof_secidx_t relsec; 185 186 dof_secidx_t strsec = DOF_SECIDX_NONE; 187 dof_secidx_t intsec = DOF_SECIDX_NONE; 188 dof_secidx_t hdrsec = DOF_SECIDX_NONE; 189 190 if (dp->dtdo_buf != NULL) { 191 dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_buf, 192 DOF_SECT_DIF, sizeof (dif_instr_t), 0, 193 sizeof (dif_instr_t), sizeof (dif_instr_t) * dp->dtdo_len); 194 } 195 196 if (dp->dtdo_inttab != NULL) { 197 dsecs[nsecs++] = intsec = dof_add_lsect(ddo, dp->dtdo_inttab, 198 DOF_SECT_INTTAB, sizeof (uint64_t), 0, 199 sizeof (uint64_t), sizeof (uint64_t) * dp->dtdo_intlen); 200 } 201 202 if (dp->dtdo_strtab != NULL) { 203 dsecs[nsecs++] = strsec = dof_add_lsect(ddo, dp->dtdo_strtab, 204 DOF_SECT_STRTAB, sizeof (char), 0, 0, dp->dtdo_strlen); 205 } 206 207 if (dp->dtdo_vartab != NULL) { 208 dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_vartab, 209 DOF_SECT_VARTAB, sizeof (uint_t), 0, sizeof (dtrace_difv_t), 210 sizeof (dtrace_difv_t) * dp->dtdo_varlen); 211 } 212 213 /* 214 * Copy the return type and the array of section indices that form the 215 * DIFO into a single dof_difohdr_t and then add DOF_SECT_DIFOHDR. 216 */ 217 assert(nsecs <= sizeof (dsecs) / sizeof (dsecs[0])); 218 dofd = alloca(sizeof (dtrace_diftype_t) + sizeof (dsecs)); 219 bcopy(&dp->dtdo_rtype, &dofd->dofd_rtype, sizeof (dtrace_diftype_t)); 220 bcopy(dsecs, &dofd->dofd_links, sizeof (dof_secidx_t) * nsecs); 221 222 hdrsec = dof_add_lsect(ddo, dofd, DOF_SECT_DIFOHDR, 223 sizeof (dof_secidx_t), 0, 0, 224 sizeof (dtrace_diftype_t) + sizeof (dof_secidx_t) * nsecs); 225 226 /* 227 * Add any other sections related to dtrace_difo_t. These are not 228 * referenced in dof_difohdr_t because they are not used by emulation. 229 */ 230 if (dp->dtdo_kreltab != NULL) { 231 relsec = dof_add_lsect(ddo, dp->dtdo_kreltab, DOF_SECT_RELTAB, 232 sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 233 sizeof (dof_relodesc_t) * dp->dtdo_krelen); 234 235 /* 236 * This code assumes the target of all relocations is the 237 * integer table 'intsec' (DOF_SECT_INTTAB). If other sections 238 * need relocation in the future this will need to change. 239 */ 240 dofr.dofr_strtab = strsec; 241 dofr.dofr_relsec = relsec; 242 dofr.dofr_tgtsec = intsec; 243 244 (void) dof_add_lsect(ddo, &dofr, DOF_SECT_KRELHDR, 245 sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 246 } 247 248 if (dp->dtdo_ureltab != NULL) { 249 relsec = dof_add_lsect(ddo, dp->dtdo_ureltab, DOF_SECT_RELTAB, 250 sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 251 sizeof (dof_relodesc_t) * dp->dtdo_urelen); 252 253 /* 254 * This code assumes the target of all relocations is the 255 * integer table 'intsec' (DOF_SECT_INTTAB). If other sections 256 * need relocation in the future this will need to change. 257 */ 258 dofr.dofr_strtab = strsec; 259 dofr.dofr_relsec = relsec; 260 dofr.dofr_tgtsec = intsec; 261 262 (void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR, 263 sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 264 } 265 266 return (hdrsec); 267 } 268 269 /*ARGSUSED*/ 270 static int 271 dof_add_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) 272 { 273 dt_dof_t *ddo = data; 274 dtrace_hdl_t *dtp = ddo->ddo_hdl; 275 dt_probe_t *prp = idp->di_data; 276 277 dof_probe_t dofpr; 278 dof_relodesc_t dofr; 279 dt_probe_instance_t *pip; 280 dt_node_t *dnp; 281 282 char buf[DT_TYPE_NAMELEN]; 283 uint_t i; 284 285 dofpr.dofpr_addr = 0; 286 dofpr.dofpr_name = dof_add_string(ddo, prp->pr_name); 287 dofpr.dofpr_nargv = dt_buf_len(&ddo->ddo_strs); 288 289 for (dnp = prp->pr_nargs; dnp != NULL; dnp = dnp->dn_list) { 290 (void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp, 291 dnp->dn_type, buf, sizeof (buf))); 292 } 293 294 dofpr.dofpr_xargv = dt_buf_len(&ddo->ddo_strs); 295 296 for (dnp = prp->pr_xargs; dnp != NULL; dnp = dnp->dn_list) { 297 (void) dof_add_string(ddo, ctf_type_name(dnp->dn_ctfp, 298 dnp->dn_type, buf, sizeof (buf))); 299 } 300 301 dofpr.dofpr_argidx = dt_buf_len(&ddo->ddo_args) / sizeof (uint8_t); 302 303 for (i = 0; i < prp->pr_xargc; i++) { 304 dt_buf_write(dtp, &ddo->ddo_args, &prp->pr_mapping[i], 305 sizeof (uint8_t), sizeof (uint8_t)); 306 } 307 308 dofpr.dofpr_nargc = prp->pr_nargc; 309 dofpr.dofpr_xargc = prp->pr_xargc; 310 dofpr.dofpr_pad = 0; 311 312 for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) { 313 dofpr.dofpr_func = dof_add_string(ddo, pip->pi_fname); 314 dofpr.dofpr_offidx = 315 dt_buf_len(&ddo->ddo_offs) / sizeof (uint32_t); 316 dofpr.dofpr_noffs = pip->pi_noffs; 317 318 dt_buf_write(dtp, &ddo->ddo_offs, pip->pi_offs, 319 pip->pi_noffs * sizeof (uint32_t), sizeof (uint32_t)); 320 321 dofr.dofr_name = dofpr.dofpr_func; 322 dofr.dofr_type = DOF_RELO_SETX; 323 dofr.dofr_offset = dt_buf_len(&ddo->ddo_probes); 324 dofr.dofr_data = 0; 325 326 dt_buf_write(dtp, &ddo->ddo_rels, &dofr, 327 sizeof (dofr), sizeof (uint64_t)); 328 329 dt_buf_write(dtp, &ddo->ddo_probes, &dofpr, 330 sizeof (dofpr), sizeof (uint64_t)); 331 } 332 333 return (0); 334 } 335 336 static void 337 dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp) 338 { 339 dtrace_hdl_t *dtp = ddo->ddo_hdl; 340 dof_provider_t dofpv; 341 dof_relohdr_t dofr; 342 343 if (pvp->pv_flags & DT_PROVIDER_IMPL) 344 return; /* ignore providers that are exported by dtrace(7D) */ 345 346 dt_buf_reset(dtp, &ddo->ddo_probes); 347 dt_buf_reset(dtp, &ddo->ddo_args); 348 dt_buf_reset(dtp, &ddo->ddo_offs); 349 dt_buf_reset(dtp, &ddo->ddo_rels); 350 351 (void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo); 352 353 dofpv.dofpv_probes = dof_add_lsect(ddo, NULL, DOF_SECT_PROBES, 354 sizeof (uint64_t), 0, sizeof (dof_probe_t), 355 dt_buf_len(&ddo->ddo_probes)); 356 357 dt_buf_concat(dtp, &ddo->ddo_ldata, 358 &ddo->ddo_probes, sizeof (uint64_t)); 359 360 dofpv.dofpv_prargs = dof_add_lsect(ddo, NULL, DOF_SECT_PRARGS, 361 sizeof (uint8_t), 0, sizeof (uint8_t), dt_buf_len(&ddo->ddo_args)); 362 363 dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_args, sizeof (uint8_t)); 364 365 dofpv.dofpv_proffs = dof_add_lsect(ddo, NULL, DOF_SECT_PROFFS, 366 sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_offs)); 367 368 dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_offs, sizeof (uint_t)); 369 370 dofpv.dofpv_strtab = ddo->ddo_strsec; 371 dofpv.dofpv_name = dof_add_string(ddo, pvp->pv_desc.dtvd_name); 372 373 dofpv.dofpv_provattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_provider); 374 dofpv.dofpv_modattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_mod); 375 dofpv.dofpv_funcattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_func); 376 dofpv.dofpv_nameattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_name); 377 dofpv.dofpv_argsattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_args); 378 379 (void) dof_add_lsect(ddo, &dofpv, DOF_SECT_PROVIDER, 380 sizeof (dof_secidx_t), 0, 0, sizeof (dof_provider_t)); 381 382 dofr.dofr_strtab = dofpv.dofpv_strtab; 383 dofr.dofr_tgtsec = dofpv.dofpv_probes; 384 dofr.dofr_relsec = dof_add_lsect(ddo, NULL, DOF_SECT_RELTAB, 385 sizeof (uint64_t), 0, sizeof (dof_relodesc_t), 386 dt_buf_len(&ddo->ddo_rels)); 387 388 dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_rels, sizeof (uint64_t)); 389 390 (void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR, 391 sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); 392 } 393 394 static int 395 dof_hdr(dtrace_hdl_t *dtp, dof_hdr_t *hp) 396 { 397 /* 398 * If our config values cannot fit in a uint8_t, we can't generate a 399 * DOF header since the values won't fit. This can only happen if the 400 * user forcibly compiles a program with an artificial configuration. 401 */ 402 if (dtp->dt_conf.dtc_difversion > UINT8_MAX || 403 dtp->dt_conf.dtc_difintregs > UINT8_MAX || 404 dtp->dt_conf.dtc_diftupregs > UINT8_MAX) 405 return (dt_set_errno(dtp, EOVERFLOW)); 406 407 bzero(hp, sizeof (dof_hdr_t)); 408 409 hp->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0; 410 hp->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1; 411 hp->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2; 412 hp->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3; 413 414 if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) 415 hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_LP64; 416 else 417 hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_ILP32; 418 419 hp->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE; 420 hp->dofh_ident[DOF_ID_VERSION] = DOF_VERSION_1; 421 hp->dofh_ident[DOF_ID_DIFVERS] = dtp->dt_conf.dtc_difversion; 422 hp->dofh_ident[DOF_ID_DIFIREG] = dtp->dt_conf.dtc_difintregs; 423 hp->dofh_ident[DOF_ID_DIFTREG] = dtp->dt_conf.dtc_diftupregs; 424 425 hp->dofh_hdrsize = sizeof (dof_hdr_t); 426 hp->dofh_secsize = sizeof (dof_sec_t); 427 hp->dofh_secoff = sizeof (dof_hdr_t); 428 429 return (0); 430 } 431 432 void * 433 dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags) 434 { 435 dt_dof_t *ddo = &dtp->dt_dof; 436 437 const dtrace_ecbdesc_t *edp, *last; 438 const dtrace_probedesc_t *pdp; 439 const dtrace_actdesc_t *ap; 440 const dt_stmt_t *stp; 441 442 uint_t maxacts = 0; 443 uint_t maxfmt = 0; 444 445 dt_provider_t *pvp; 446 dof_actdesc_t *dofa; 447 dof_sec_t *sp; 448 size_t ssize, lsize; 449 dof_hdr_t h; 450 451 dt_buf_t dof; 452 char *fmt; 453 uint_t i; 454 455 if (flags & ~DTRACE_D_MASK) { 456 (void) dt_set_errno(dtp, EINVAL); 457 return (NULL); 458 } 459 460 flags |= dtp->dt_dflags; 461 462 if (dof_hdr(dtp, &h) != 0) 463 return (NULL); 464 465 assert(ddo->ddo_hdl == dtp); 466 dt_dof_reset(dtp); 467 468 /* 469 * Iterate through the statement list computing the maximum number of 470 * actions and the maximum format string for allocating local buffers. 471 */ 472 for (last = NULL, stp = dt_list_next(&pgp->dp_stmts); 473 stp != NULL; stp = dt_list_next(stp), last = edp) { 474 475 dtrace_stmtdesc_t *sdp = stp->ds_desc; 476 dtrace_actdesc_t *ap = sdp->dtsd_action; 477 478 if (sdp->dtsd_fmtdata != NULL) { 479 i = dtrace_printf_format(dtp, 480 sdp->dtsd_fmtdata, NULL, 0); 481 maxfmt = MAX(maxfmt, i); 482 } 483 484 if ((edp = sdp->dtsd_ecbdesc) == last) 485 continue; /* same ecb as previous statement */ 486 487 for (i = 0, ap = edp->dted_action; ap; ap = ap->dtad_next) 488 i++; 489 490 maxacts = MAX(maxacts, i); 491 } 492 493 dofa = alloca(sizeof (dof_actdesc_t) * maxacts); 494 fmt = alloca(maxfmt + 1); 495 496 ddo->ddo_strsec = dof_add_lsect(ddo, NULL, DOF_SECT_STRTAB, 1, 0, 0, 0); 497 (void) dof_add_string(ddo, ""); 498 499 /* 500 * Now iterate through the statement list, creating the DOF section 501 * headers and data for each one and adding them to our buffers. 502 */ 503 for (last = NULL, stp = dt_list_next(&pgp->dp_stmts); 504 stp != NULL; stp = dt_list_next(stp), last = edp) { 505 506 dof_secidx_t probesec = DOF_SECIDX_NONE; 507 dof_secidx_t prdsec = DOF_SECIDX_NONE; 508 dof_secidx_t actsec = DOF_SECIDX_NONE; 509 510 const dt_stmt_t *next = stp; 511 dtrace_stmtdesc_t *sdp = stp->ds_desc; 512 dof_stridx_t strndx = 0; 513 dof_probedesc_t dofp; 514 dof_ecbdesc_t dofe; 515 uint_t i; 516 517 if ((edp = stp->ds_desc->dtsd_ecbdesc) == last) 518 continue; /* same ecb as previous statement */ 519 520 pdp = &edp->dted_probe; 521 522 /* 523 * Add a DOF_SECT_PROBEDESC for the ECB's probe description, 524 * and copy the probe description strings into the string table. 525 */ 526 dofp.dofp_strtab = ddo->ddo_strsec; 527 dofp.dofp_provider = dof_add_string(ddo, pdp->dtpd_provider); 528 dofp.dofp_mod = dof_add_string(ddo, pdp->dtpd_mod); 529 dofp.dofp_func = dof_add_string(ddo, pdp->dtpd_func); 530 dofp.dofp_name = dof_add_string(ddo, pdp->dtpd_name); 531 dofp.dofp_id = pdp->dtpd_id; 532 533 probesec = dof_add_lsect(ddo, &dofp, DOF_SECT_PROBEDESC, 534 sizeof (dof_secidx_t), 0, 535 sizeof (dof_probedesc_t), sizeof (dof_probedesc_t)); 536 537 /* 538 * If there is a predicate DIFO associated with the ecbdesc, 539 * write out the DIFO sections and save the DIFO section index. 540 */ 541 if (edp->dted_pred.dtpdd_difo != NULL) 542 prdsec = dof_add_difo(ddo, edp->dted_pred.dtpdd_difo); 543 544 /* 545 * Now iterate through the action list generating DIFOs as 546 * referenced therein and adding action descriptions to 'dofa'. 547 */ 548 for (i = 0, ap = edp->dted_action; 549 ap != NULL; ap = ap->dtad_next, i++) { 550 551 if (ap->dtad_difo != NULL) { 552 dofa[i].dofa_difo = 553 dof_add_difo(ddo, ap->dtad_difo); 554 } else 555 dofa[i].dofa_difo = DOF_SECIDX_NONE; 556 557 /* 558 * If the first action in a statement has format data, 559 * add the format string to the global string table. 560 */ 561 if (sdp != NULL && ap == sdp->dtsd_action) { 562 if (sdp->dtsd_fmtdata != NULL) { 563 (void) dtrace_printf_format(dtp, 564 sdp->dtsd_fmtdata, fmt, maxfmt + 1); 565 strndx = dof_add_string(ddo, fmt); 566 } else 567 strndx = 0; /* use dtad_arg instead */ 568 569 if ((next = dt_list_next(next)) != NULL) 570 sdp = next->ds_desc; 571 else 572 sdp = NULL; 573 } 574 575 if (strndx != 0) { 576 dofa[i].dofa_arg = strndx; 577 dofa[i].dofa_strtab = ddo->ddo_strsec; 578 } else { 579 dofa[i].dofa_arg = ap->dtad_arg; 580 dofa[i].dofa_strtab = DOF_SECIDX_NONE; 581 } 582 583 dofa[i].dofa_kind = ap->dtad_kind; 584 dofa[i].dofa_ntuple = ap->dtad_ntuple; 585 dofa[i].dofa_uarg = ap->dtad_uarg; 586 } 587 588 if (i > 0) { 589 actsec = dof_add_lsect(ddo, dofa, DOF_SECT_ACTDESC, 590 sizeof (uint64_t), 0, sizeof (dof_actdesc_t), 591 sizeof (dof_actdesc_t) * i); 592 } 593 594 /* 595 * Now finally, add the DOF_SECT_ECBDESC referencing all the 596 * previously created sub-sections. 597 */ 598 dofe.dofe_probes = probesec; 599 dofe.dofe_pred = prdsec; 600 dofe.dofe_actions = actsec; 601 dofe.dofe_pad = 0; 602 dofe.dofe_uarg = edp->dted_uarg; 603 604 (void) dof_add_lsect(ddo, &dofe, DOF_SECT_ECBDESC, 605 sizeof (uint64_t), 0, 0, sizeof (dof_ecbdesc_t)); 606 } 607 608 /* 609 * If any providers are user-defined, output DOF sections corresponding 610 * to the providers and the probes and arguments that they define. 611 */ 612 if (flags & DTRACE_D_PROBES) { 613 for (pvp = dt_list_next(&dtp->dt_provlist); 614 pvp != NULL; pvp = dt_list_next(pvp)) 615 dof_add_provider(ddo, pvp); 616 } 617 618 /* 619 * If we're not stripping unloadable sections, generate compiler 620 * comments and any other unloadable miscellany. 621 */ 622 if (!(flags & DTRACE_D_STRIP)) { 623 (void) dof_add_usect(ddo, _dtrace_version, DOF_SECT_COMMENTS, 624 sizeof (char), 0, 0, strlen(_dtrace_version) + 1); 625 (void) dof_add_usect(ddo, &dtp->dt_uts, DOF_SECT_UTSNAME, 626 sizeof (char), 0, 0, sizeof (struct utsname)); 627 } 628 629 /* 630 * Compute and fill in the appropriate values for the dof_hdr_t's 631 * dofh_secnum, dofh_loadsz, and dofh_filez values. 632 */ 633 h.dofh_secnum = ddo->ddo_nsecs; 634 ssize = sizeof (h) + dt_buf_len(&ddo->ddo_secs); 635 assert(ssize == sizeof (h) + sizeof (dof_sec_t) * ddo->ddo_nsecs); 636 637 h.dofh_loadsz = ssize + 638 dt_buf_len(&ddo->ddo_ldata) + 639 dt_buf_len(&ddo->ddo_strs); 640 641 if (dt_buf_len(&ddo->ddo_udata) != 0) { 642 lsize = roundup(h.dofh_loadsz, sizeof (uint64_t)); 643 h.dofh_filesz = lsize + dt_buf_len(&ddo->ddo_udata); 644 } else { 645 lsize = h.dofh_loadsz; 646 h.dofh_filesz = lsize; 647 } 648 649 /* 650 * Set the global DOF_SECT_STRTAB's offset to be after the header, 651 * section headers, and other loadable data. Since we're going to 652 * iterate over the buffer data directly, we must check for errors. 653 */ 654 if ((i = dt_buf_error(&ddo->ddo_secs)) != 0) { 655 (void) dt_set_errno(dtp, i); 656 return (NULL); 657 } 658 659 sp = dt_buf_ptr(&ddo->ddo_secs); 660 assert(sp[ddo->ddo_strsec].dofs_type == DOF_SECT_STRTAB); 661 662 sp[ddo->ddo_strsec].dofs_offset = ssize + dt_buf_len(&ddo->ddo_ldata); 663 sp[ddo->ddo_strsec].dofs_size = dt_buf_len(&ddo->ddo_strs); 664 665 /* 666 * Now relocate all the other section headers by adding the appropriate 667 * delta to their respective dofs_offset values. 668 */ 669 for (i = 0; i < ddo->ddo_nsecs; i++, sp++) { 670 if (i == ddo->ddo_strsec) 671 continue; /* already relocated above */ 672 673 if (sp->dofs_flags & DOF_SECF_LOAD) 674 sp->dofs_offset += ssize; 675 else 676 sp->dofs_offset += lsize; 677 } 678 679 /* 680 * Finally, assemble the complete in-memory DOF buffer by writing the 681 * header and then concatenating all our buffers. dt_buf_concat() will 682 * propagate any errors and cause dt_buf_claim() to return NULL. 683 */ 684 dt_buf_create(dtp, &dof, "dof", h.dofh_filesz); 685 686 dt_buf_write(dtp, &dof, &h, sizeof (h), sizeof (uint64_t)); 687 dt_buf_concat(dtp, &dof, &ddo->ddo_secs, sizeof (uint64_t)); 688 dt_buf_concat(dtp, &dof, &ddo->ddo_ldata, sizeof (uint64_t)); 689 dt_buf_concat(dtp, &dof, &ddo->ddo_strs, sizeof (char)); 690 dt_buf_concat(dtp, &dof, &ddo->ddo_udata, sizeof (uint64_t)); 691 692 return (dt_buf_claim(dtp, &dof)); 693 } 694 695 void 696 dtrace_dof_destroy(dtrace_hdl_t *dtp, void *dof) 697 { 698 dt_free(dtp, dof); 699 } 700 701 void * 702 dtrace_getopt_dof(dtrace_hdl_t *dtp) 703 { 704 dof_hdr_t *dof; 705 dof_sec_t *sec; 706 dof_optdesc_t *dofo; 707 int i, nopts = 0, len = sizeof (dof_hdr_t) + 708 roundup(sizeof (dof_sec_t), sizeof (uint64_t)); 709 710 for (i = 0; i < DTRACEOPT_MAX; i++) { 711 if (dtp->dt_options[i] != DTRACEOPT_UNSET) 712 nopts++; 713 } 714 715 len += sizeof (dof_optdesc_t) * nopts; 716 717 if ((dof = dt_zalloc(dtp, len)) == NULL || dof_hdr(dtp, dof) != 0) { 718 dt_free(dtp, dof); 719 return (NULL); 720 } 721 722 dof->dofh_secnum = 1; /* only DOF_SECT_OPTDESC */ 723 dof->dofh_loadsz = len; 724 dof->dofh_filesz = len; 725 726 /* 727 * Fill in the option section header... 728 */ 729 sec = (dof_sec_t *)((uintptr_t)dof + sizeof (dof_hdr_t)); 730 sec->dofs_type = DOF_SECT_OPTDESC; 731 sec->dofs_align = sizeof (uint64_t); 732 sec->dofs_flags = DOF_SECF_LOAD; 733 sec->dofs_entsize = sizeof (dof_optdesc_t); 734 735 dofo = (dof_optdesc_t *)((uintptr_t)sec + 736 roundup(sizeof (dof_sec_t), sizeof (uint64_t))); 737 738 sec->dofs_offset = (uintptr_t)dofo - (uintptr_t)dof; 739 sec->dofs_size = sizeof (dof_optdesc_t) * nopts; 740 741 for (i = 0; i < DTRACEOPT_MAX; i++) { 742 if (dtp->dt_options[i] == DTRACEOPT_UNSET) 743 continue; 744 745 dofo->dofo_option = i; 746 dofo->dofo_strtab = DOF_SECIDX_NONE; 747 dofo->dofo_value = dtp->dt_options[i]; 748 dofo++; 749 } 750 751 return (dof); 752 } 753 754 void * 755 dtrace_geterr_dof(dtrace_hdl_t *dtp) 756 { 757 if (dtp->dt_errprog != NULL) 758 return (dtrace_dof_create(dtp, dtp->dt_errprog, 0)); 759 760 (void) dt_set_errno(dtp, EDT_BADERROR); 761 return (NULL); 762 } 763