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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright (c) 2011 by Delphix. All rights reserved. 28 */ 29 30 #include <stdlib.h> 31 #include <strings.h> 32 #include <errno.h> 33 #include <unistd.h> 34 #include <assert.h> 35 36 #include <dt_impl.h> 37 #include <dt_printf.h> 38 39 static int 40 dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max) 41 { 42 int maxformat; 43 dtrace_fmtdesc_t fmt; 44 void *result; 45 46 if (rec->dtrd_format == 0) 47 return (0); 48 49 if (rec->dtrd_format <= *max && 50 (*data)[rec->dtrd_format - 1] != NULL) { 51 return (0); 52 } 53 54 bzero(&fmt, sizeof (fmt)); 55 fmt.dtfd_format = rec->dtrd_format; 56 fmt.dtfd_string = NULL; 57 fmt.dtfd_length = 0; 58 59 if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) 60 return (dt_set_errno(dtp, errno)); 61 62 if ((fmt.dtfd_string = dt_alloc(dtp, fmt.dtfd_length)) == NULL) 63 return (dt_set_errno(dtp, EDT_NOMEM)); 64 65 if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) { 66 free(fmt.dtfd_string); 67 return (dt_set_errno(dtp, errno)); 68 } 69 70 while (rec->dtrd_format > (maxformat = *max)) { 71 int new_max = maxformat ? (maxformat << 1) : 1; 72 size_t nsize = new_max * sizeof (void *); 73 size_t osize = maxformat * sizeof (void *); 74 void **new_data = dt_zalloc(dtp, nsize); 75 76 if (new_data == NULL) { 77 dt_free(dtp, fmt.dtfd_string); 78 return (dt_set_errno(dtp, EDT_NOMEM)); 79 } 80 81 bcopy(*data, new_data, osize); 82 free(*data); 83 84 *data = new_data; 85 *max = new_max; 86 } 87 88 switch (rec->dtrd_action) { 89 case DTRACEACT_DIFEXPR: 90 result = fmt.dtfd_string; 91 break; 92 case DTRACEACT_PRINTA: 93 result = dtrace_printa_create(dtp, fmt.dtfd_string); 94 dt_free(dtp, fmt.dtfd_string); 95 break; 96 default: 97 result = dtrace_printf_create(dtp, fmt.dtfd_string); 98 dt_free(dtp, fmt.dtfd_string); 99 break; 100 } 101 102 if (result == NULL) 103 return (-1); 104 105 (*data)[rec->dtrd_format - 1] = result; 106 107 return (0); 108 } 109 110 static int 111 dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id) 112 { 113 dtrace_id_t max; 114 int rval, i; 115 dtrace_eprobedesc_t *enabled, *nenabled; 116 dtrace_probedesc_t *probe; 117 118 while (id >= (max = dtp->dt_maxprobe) || dtp->dt_pdesc == NULL) { 119 dtrace_id_t new_max = max ? (max << 1) : 1; 120 size_t nsize = new_max * sizeof (void *); 121 dtrace_probedesc_t **new_pdesc; 122 dtrace_eprobedesc_t **new_edesc; 123 124 if ((new_pdesc = malloc(nsize)) == NULL || 125 (new_edesc = malloc(nsize)) == NULL) { 126 free(new_pdesc); 127 return (dt_set_errno(dtp, EDT_NOMEM)); 128 } 129 130 bzero(new_pdesc, nsize); 131 bzero(new_edesc, nsize); 132 133 if (dtp->dt_pdesc != NULL) { 134 size_t osize = max * sizeof (void *); 135 136 bcopy(dtp->dt_pdesc, new_pdesc, osize); 137 free(dtp->dt_pdesc); 138 139 bcopy(dtp->dt_edesc, new_edesc, osize); 140 free(dtp->dt_edesc); 141 } 142 143 dtp->dt_pdesc = new_pdesc; 144 dtp->dt_edesc = new_edesc; 145 dtp->dt_maxprobe = new_max; 146 } 147 148 if (dtp->dt_pdesc[id] != NULL) 149 return (0); 150 151 if ((enabled = malloc(sizeof (dtrace_eprobedesc_t))) == NULL) 152 return (dt_set_errno(dtp, EDT_NOMEM)); 153 154 bzero(enabled, sizeof (dtrace_eprobedesc_t)); 155 enabled->dtepd_epid = id; 156 enabled->dtepd_nrecs = 1; 157 158 if (dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled) == -1) { 159 rval = dt_set_errno(dtp, errno); 160 free(enabled); 161 return (rval); 162 } 163 164 if (DTRACE_SIZEOF_EPROBEDESC(enabled) != sizeof (*enabled)) { 165 /* 166 * There must be more than one action. Allocate the 167 * appropriate amount of space and try again. 168 */ 169 if ((nenabled = 170 malloc(DTRACE_SIZEOF_EPROBEDESC(enabled))) != NULL) 171 bcopy(enabled, nenabled, sizeof (*enabled)); 172 173 free(enabled); 174 175 if ((enabled = nenabled) == NULL) 176 return (dt_set_errno(dtp, EDT_NOMEM)); 177 178 rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled); 179 180 if (rval == -1) { 181 rval = dt_set_errno(dtp, errno); 182 free(enabled); 183 return (rval); 184 } 185 } 186 187 if ((probe = malloc(sizeof (dtrace_probedesc_t))) == NULL) { 188 free(enabled); 189 return (dt_set_errno(dtp, EDT_NOMEM)); 190 } 191 192 probe->dtpd_id = enabled->dtepd_probeid; 193 194 if (dt_ioctl(dtp, DTRACEIOC_PROBES, probe) == -1) { 195 rval = dt_set_errno(dtp, errno); 196 goto err; 197 } 198 199 for (i = 0; i < enabled->dtepd_nrecs; i++) { 200 dtrace_recdesc_t *rec = &enabled->dtepd_rec[i]; 201 202 if (DTRACEACT_ISPRINTFLIKE(rec->dtrd_action)) { 203 if (dt_strdata_add(dtp, rec, &dtp->dt_formats, 204 &dtp->dt_maxformat) != 0) { 205 rval = -1; 206 goto err; 207 } 208 } else if (rec->dtrd_action == DTRACEACT_DIFEXPR) { 209 if (dt_strdata_add(dtp, rec, 210 (void ***)&dtp->dt_strdata, 211 &dtp->dt_maxstrdata) != 0) { 212 rval = -1; 213 goto err; 214 } 215 } 216 217 } 218 219 dtp->dt_pdesc[id] = probe; 220 dtp->dt_edesc[id] = enabled; 221 222 return (0); 223 224 err: 225 /* 226 * If we failed, free our allocated probes. Note that if we failed 227 * while allocating formats, we aren't going to free formats that 228 * we have already allocated. This is okay; these formats are 229 * hanging off of dt_formats and will therefore not be leaked. 230 */ 231 free(enabled); 232 free(probe); 233 return (rval); 234 } 235 236 int 237 dt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid, 238 dtrace_eprobedesc_t **epdp, dtrace_probedesc_t **pdp) 239 { 240 int rval; 241 242 if (epid >= dtp->dt_maxprobe || dtp->dt_pdesc[epid] == NULL) { 243 if ((rval = dt_epid_add(dtp, epid)) != 0) 244 return (rval); 245 } 246 247 assert(epid < dtp->dt_maxprobe); 248 assert(dtp->dt_edesc[epid] != NULL); 249 assert(dtp->dt_pdesc[epid] != NULL); 250 *epdp = dtp->dt_edesc[epid]; 251 *pdp = dtp->dt_pdesc[epid]; 252 253 return (0); 254 } 255 256 void 257 dt_epid_destroy(dtrace_hdl_t *dtp) 258 { 259 size_t i; 260 261 assert((dtp->dt_pdesc != NULL && dtp->dt_edesc != NULL && 262 dtp->dt_maxprobe > 0) || (dtp->dt_pdesc == NULL && 263 dtp->dt_edesc == NULL && dtp->dt_maxprobe == 0)); 264 265 if (dtp->dt_pdesc == NULL) 266 return; 267 268 for (i = 0; i < dtp->dt_maxprobe; i++) { 269 if (dtp->dt_edesc[i] == NULL) { 270 assert(dtp->dt_pdesc[i] == NULL); 271 continue; 272 } 273 274 assert(dtp->dt_pdesc[i] != NULL); 275 free(dtp->dt_edesc[i]); 276 free(dtp->dt_pdesc[i]); 277 } 278 279 free(dtp->dt_pdesc); 280 dtp->dt_pdesc = NULL; 281 282 free(dtp->dt_edesc); 283 dtp->dt_edesc = NULL; 284 dtp->dt_maxprobe = 0; 285 } 286 287 void * 288 dt_format_lookup(dtrace_hdl_t *dtp, int format) 289 { 290 if (format == 0 || format > dtp->dt_maxformat) 291 return (NULL); 292 293 if (dtp->dt_formats == NULL) 294 return (NULL); 295 296 return (dtp->dt_formats[format - 1]); 297 } 298 299 void 300 dt_format_destroy(dtrace_hdl_t *dtp) 301 { 302 int i; 303 304 for (i = 0; i < dtp->dt_maxformat; i++) { 305 if (dtp->dt_formats[i] != NULL) 306 dt_printf_destroy(dtp->dt_formats[i]); 307 } 308 309 free(dtp->dt_formats); 310 dtp->dt_formats = NULL; 311 } 312 313 static int 314 dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id) 315 { 316 dtrace_id_t max; 317 dtrace_epid_t epid; 318 int rval; 319 320 while (id >= (max = dtp->dt_maxagg) || dtp->dt_aggdesc == NULL) { 321 dtrace_id_t new_max = max ? (max << 1) : 1; 322 size_t nsize = new_max * sizeof (void *); 323 dtrace_aggdesc_t **new_aggdesc; 324 325 if ((new_aggdesc = malloc(nsize)) == NULL) 326 return (dt_set_errno(dtp, EDT_NOMEM)); 327 328 bzero(new_aggdesc, nsize); 329 330 if (dtp->dt_aggdesc != NULL) { 331 bcopy(dtp->dt_aggdesc, new_aggdesc, 332 max * sizeof (void *)); 333 free(dtp->dt_aggdesc); 334 } 335 336 dtp->dt_aggdesc = new_aggdesc; 337 dtp->dt_maxagg = new_max; 338 } 339 340 if (dtp->dt_aggdesc[id] == NULL) { 341 dtrace_aggdesc_t *agg, *nagg; 342 343 if ((agg = malloc(sizeof (dtrace_aggdesc_t))) == NULL) 344 return (dt_set_errno(dtp, EDT_NOMEM)); 345 346 bzero(agg, sizeof (dtrace_aggdesc_t)); 347 agg->dtagd_id = id; 348 agg->dtagd_nrecs = 1; 349 350 if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg) == -1) { 351 rval = dt_set_errno(dtp, errno); 352 free(agg); 353 return (rval); 354 } 355 356 if (DTRACE_SIZEOF_AGGDESC(agg) != sizeof (*agg)) { 357 /* 358 * There must be more than one action. Allocate the 359 * appropriate amount of space and try again. 360 */ 361 if ((nagg = malloc(DTRACE_SIZEOF_AGGDESC(agg))) != NULL) 362 bcopy(agg, nagg, sizeof (*agg)); 363 364 free(agg); 365 366 if ((agg = nagg) == NULL) 367 return (dt_set_errno(dtp, EDT_NOMEM)); 368 369 rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg); 370 371 if (rval == -1) { 372 rval = dt_set_errno(dtp, errno); 373 free(agg); 374 return (rval); 375 } 376 } 377 378 /* 379 * If we have a uarg, it's a pointer to the compiler-generated 380 * statement; we'll use this value to get the name and 381 * compiler-generated variable ID for the aggregation. If 382 * we're grabbing an anonymous enabling, this pointer value 383 * is obviously meaningless -- and in this case, we can't 384 * provide the compiler-generated aggregation information. 385 */ 386 if (dtp->dt_options[DTRACEOPT_GRABANON] == DTRACEOPT_UNSET && 387 agg->dtagd_rec[0].dtrd_uarg != NULL) { 388 dtrace_stmtdesc_t *sdp; 389 dt_ident_t *aid; 390 391 sdp = (dtrace_stmtdesc_t *)(uintptr_t) 392 agg->dtagd_rec[0].dtrd_uarg; 393 aid = sdp->dtsd_aggdata; 394 agg->dtagd_name = aid->di_name; 395 agg->dtagd_varid = aid->di_id; 396 } else { 397 agg->dtagd_varid = DTRACE_AGGVARIDNONE; 398 } 399 400 if ((epid = agg->dtagd_epid) >= dtp->dt_maxprobe || 401 dtp->dt_pdesc[epid] == NULL) { 402 if ((rval = dt_epid_add(dtp, epid)) != 0) { 403 free(agg); 404 return (rval); 405 } 406 } 407 408 dtp->dt_aggdesc[id] = agg; 409 } 410 411 return (0); 412 } 413 414 int 415 dt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid, 416 dtrace_aggdesc_t **adp) 417 { 418 int rval; 419 420 if (aggid >= dtp->dt_maxagg || dtp->dt_aggdesc[aggid] == NULL) { 421 if ((rval = dt_aggid_add(dtp, aggid)) != 0) 422 return (rval); 423 } 424 425 assert(aggid < dtp->dt_maxagg); 426 assert(dtp->dt_aggdesc[aggid] != NULL); 427 *adp = dtp->dt_aggdesc[aggid]; 428 429 return (0); 430 } 431 432 void 433 dt_aggid_destroy(dtrace_hdl_t *dtp) 434 { 435 size_t i; 436 437 assert((dtp->dt_aggdesc != NULL && dtp->dt_maxagg != 0) || 438 (dtp->dt_aggdesc == NULL && dtp->dt_maxagg == 0)); 439 440 if (dtp->dt_aggdesc == NULL) 441 return; 442 443 for (i = 0; i < dtp->dt_maxagg; i++) { 444 if (dtp->dt_aggdesc[i] != NULL) 445 free(dtp->dt_aggdesc[i]); 446 } 447 448 free(dtp->dt_aggdesc); 449 dtp->dt_aggdesc = NULL; 450 dtp->dt_maxagg = 0; 451 } 452 453 const char * 454 dt_strdata_lookup(dtrace_hdl_t *dtp, int idx) 455 { 456 if (idx == 0 || idx > dtp->dt_maxstrdata) 457 return (NULL); 458 459 if (dtp->dt_strdata == NULL) 460 return (NULL); 461 462 return (dtp->dt_strdata[idx - 1]); 463 } 464 465 void 466 dt_strdata_destroy(dtrace_hdl_t *dtp) 467 { 468 int i; 469 470 for (i = 0; i < dtp->dt_maxstrdata; i++) { 471 free(dtp->dt_strdata[i]); 472 } 473 474 free(dtp->dt_strdata); 475 dtp->dt_strdata = NULL; 476 } 477