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