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 2004 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 if (agg->dtagd_rec[0].dtrd_uarg) { 355 dtrace_stmtdesc_t *sdp; 356 dt_ident_t *aid; 357 358 sdp = (dtrace_stmtdesc_t *)agg->dtagd_rec[0].dtrd_uarg; 359 aid = sdp->dtsd_aggdata; 360 agg->dtagd_name = aid->di_name; 361 } 362 363 if ((epid = agg->dtagd_epid) >= dtp->dt_maxprobe || 364 dtp->dt_pdesc[epid] == NULL) { 365 if ((rval = dt_epid_add(dtp, epid)) != 0) { 366 free(agg); 367 return (rval); 368 } 369 } 370 371 dtp->dt_aggdesc[id] = agg; 372 } 373 374 return (0); 375 } 376 377 int 378 dt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid, 379 dtrace_aggdesc_t **adp) 380 { 381 int rval; 382 383 if (aggid >= dtp->dt_maxagg || dtp->dt_aggdesc[aggid] == NULL) { 384 if ((rval = dt_aggid_add(dtp, aggid)) != 0) 385 return (rval); 386 } 387 388 assert(aggid < dtp->dt_maxagg); 389 assert(dtp->dt_aggdesc[aggid] != NULL); 390 *adp = dtp->dt_aggdesc[aggid]; 391 392 return (0); 393 } 394 395 void 396 dt_aggid_destroy(dtrace_hdl_t *dtp) 397 { 398 size_t i; 399 400 assert((dtp->dt_aggdesc != NULL && dtp->dt_maxagg != 0) || 401 (dtp->dt_aggdesc == NULL && dtp->dt_maxagg == 0)); 402 403 if (dtp->dt_aggdesc == NULL) 404 return; 405 406 for (i = 0; i < dtp->dt_maxagg; i++) { 407 if (dtp->dt_aggdesc[i] != NULL) 408 free(dtp->dt_aggdesc[i]); 409 } 410 411 free(dtp->dt_aggdesc); 412 dtp->dt_aggdesc = NULL; 413 dtp->dt_maxagg = 0; 414 } 415