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