dt_map.c revision 178562
1178173Simp/* 2178173Simp * CDDL HEADER START 3178173Simp * 4178173Simp * The contents of this file are subject to the terms of the 5178173Simp * Common Development and Distribution License (the "License"). 6178173Simp * You may not use this file except in compliance with the License. 7178173Simp * 8178173Simp * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9178173Simp * or http://www.opensolaris.org/os/licensing. 10178173Simp * See the License for the specific language governing permissions 11178173Simp * and limitations under the License. 12178173Simp * 13178173Simp * When distributing Covered Code, include this CDDL HEADER in each 14178173Simp * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15178173Simp * If applicable, add the following below this CDDL HEADER, with the 16178173Simp * fields enclosed by brackets "[]" replaced with your own identifying 17178173Simp * information: Portions Copyright [yyyy] [name of copyright owner] 18178173Simp * 19178173Simp * CDDL HEADER END 20178173Simp */ 21178173Simp/* 22178173Simp * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23178173Simp * Use is subject to license terms. 24178173Simp */ 25178173Simp 26178173Simp#pragma ident "%Z%%M% %I% %E% SMI" 27178173Simp 28178173Simp#include <stdlib.h> 29178173Simp#include <strings.h> 30178173Simp#include <errno.h> 31178173Simp#include <unistd.h> 32178173Simp#include <assert.h> 33178173Simp 34178173Simp#include <dt_impl.h> 35178173Simp#include <dt_printf.h> 36178173Simp 37178173Simpstatic int 38178173Simpdt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id) 39178173Simp{ 40178173Simp dtrace_id_t max; 41178173Simp int rval, i, maxformat; 42178173Simp dtrace_eprobedesc_t *enabled, *nenabled; 43178173Simp dtrace_probedesc_t *probe; 44178173Simp 45178173Simp while (id >= (max = dtp->dt_maxprobe) || dtp->dt_pdesc == NULL) { 46178173Simp dtrace_id_t new_max = max ? (max << 1) : 1; 47182901Sgonzo size_t nsize = new_max * sizeof (void *); 48182901Sgonzo dtrace_probedesc_t **new_pdesc; 49178173Simp dtrace_eprobedesc_t **new_edesc; 50178173Simp 51178173Simp if ((new_pdesc = malloc(nsize)) == NULL || 52178173Simp (new_edesc = malloc(nsize)) == NULL) { 53178173Simp free(new_pdesc); 54178173Simp return (dt_set_errno(dtp, EDT_NOMEM)); 55178173Simp } 56178173Simp 57178173Simp bzero(new_pdesc, nsize); 58178173Simp bzero(new_edesc, nsize); 59178173Simp 60178173Simp if (dtp->dt_pdesc != NULL) { 61178173Simp size_t osize = max * sizeof (void *); 62178173Simp 63178173Simp bcopy(dtp->dt_pdesc, new_pdesc, osize); 64178173Simp free(dtp->dt_pdesc); 65178173Simp 66178173Simp bcopy(dtp->dt_edesc, new_edesc, osize); 67178173Simp free(dtp->dt_edesc); 68178173Simp } 69178173Simp 70178173Simp dtp->dt_pdesc = new_pdesc; 71178173Simp dtp->dt_edesc = new_edesc; 72178173Simp dtp->dt_maxprobe = new_max; 73178173Simp } 74178173Simp 75178173Simp if (dtp->dt_pdesc[id] != NULL) 76178173Simp return (0); 77178173Simp 78178173Simp if ((enabled = malloc(sizeof (dtrace_eprobedesc_t))) == NULL) 79178173Simp return (dt_set_errno(dtp, EDT_NOMEM)); 80178173Simp 81178173Simp bzero(enabled, sizeof (dtrace_eprobedesc_t)); 82178173Simp enabled->dtepd_epid = id; 83178173Simp enabled->dtepd_nrecs = 1; 84178173Simp 85178173Simp#if defined(sun) 86178173Simp if (dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled) == -1) { 87178173Simp#else 88178173Simp if (dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled) == -1) { 89178173Simp#endif 90178173Simp rval = dt_set_errno(dtp, errno); 91178173Simp free(enabled); 92178173Simp return (rval); 93178173Simp } 94178173Simp 95178173Simp if (DTRACE_SIZEOF_EPROBEDESC(enabled) != sizeof (*enabled)) { 96178173Simp /* 97178173Simp * There must be more than one action. Allocate the 98178173Simp * appropriate amount of space and try again. 99178173Simp */ 100178173Simp if ((nenabled = 101178173Simp malloc(DTRACE_SIZEOF_EPROBEDESC(enabled))) != NULL) 102178173Simp bcopy(enabled, nenabled, sizeof (*enabled)); 103178173Simp 104178173Simp free(enabled); 105178173Simp 106178173Simp if ((enabled = nenabled) == NULL) 107178173Simp return (dt_set_errno(dtp, EDT_NOMEM)); 108178173Simp 109178173Simp#if defined(sun) 110178173Simp rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled); 111178173Simp#else 112178173Simp rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled); 113178173Simp#endif 114178173Simp 115178173Simp if (rval == -1) { 116178173Simp rval = dt_set_errno(dtp, errno); 117178173Simp free(enabled); 118178173Simp return (rval); 119178173Simp } 120178173Simp } 121178173Simp 122178173Simp if ((probe = malloc(sizeof (dtrace_probedesc_t))) == NULL) { 123178173Simp free(enabled); 124178173Simp return (dt_set_errno(dtp, EDT_NOMEM)); 125178173Simp } 126178173Simp 127178173Simp probe->dtpd_id = enabled->dtepd_probeid; 128178173Simp 129178173Simp if (dt_ioctl(dtp, DTRACEIOC_PROBES, probe) == -1) { 130178173Simp rval = dt_set_errno(dtp, errno); 131178173Simp goto err; 132178173Simp } 133178173Simp 134178173Simp for (i = 0; i < enabled->dtepd_nrecs; i++) { 135178173Simp dtrace_fmtdesc_t fmt; 136178173Simp dtrace_recdesc_t *rec = &enabled->dtepd_rec[i]; 137178173Simp 138178173Simp if (!DTRACEACT_ISPRINTFLIKE(rec->dtrd_action)) 139178173Simp continue; 140178173Simp 141178173Simp if (rec->dtrd_format == 0) 142178173Simp continue; 143178173Simp 144178173Simp if (rec->dtrd_format <= dtp->dt_maxformat && 145178173Simp dtp->dt_formats[rec->dtrd_format - 1] != NULL) 146178173Simp continue; 147178173Simp 148178173Simp bzero(&fmt, sizeof (fmt)); 149178173Simp fmt.dtfd_format = rec->dtrd_format; 150178173Simp fmt.dtfd_string = NULL; 151178173Simp fmt.dtfd_length = 0; 152178173Simp 153178173Simp if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) { 154178173Simp rval = dt_set_errno(dtp, errno); 155178173Simp goto err; 156178173Simp } 157178173Simp 158178173Simp if ((fmt.dtfd_string = malloc(fmt.dtfd_length)) == NULL) { 159178173Simp rval = dt_set_errno(dtp, EDT_NOMEM); 160178173Simp goto err; 161178173Simp } 162178173Simp 163178173Simp if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) { 164178173Simp rval = dt_set_errno(dtp, errno); 165178173Simp free(fmt.dtfd_string); 166178173Simp goto err; 167178173Simp } 168178173Simp 169178173Simp while (rec->dtrd_format > (maxformat = dtp->dt_maxformat)) { 170178173Simp int new_max = maxformat ? (maxformat << 1) : 1; 171178173Simp size_t nsize = new_max * sizeof (void *); 172178173Simp size_t osize = maxformat * sizeof (void *); 173178173Simp void **new_formats = malloc(nsize); 174178173Simp 175178173Simp if (new_formats == NULL) { 176178173Simp rval = dt_set_errno(dtp, EDT_NOMEM); 177178173Simp free(fmt.dtfd_string); 178178173Simp goto err; 179178173Simp } 180178173Simp 181178173Simp bzero(new_formats, nsize); 182178173Simp bcopy(dtp->dt_formats, new_formats, osize); 183178173Simp free(dtp->dt_formats); 184178173Simp 185178173Simp dtp->dt_formats = new_formats; 186178173Simp dtp->dt_maxformat = new_max; 187178173Simp } 188178173Simp 189178173Simp dtp->dt_formats[rec->dtrd_format - 1] = 190178173Simp rec->dtrd_action == DTRACEACT_PRINTA ? 191178173Simp dtrace_printa_create(dtp, fmt.dtfd_string) : 192178173Simp dtrace_printf_create(dtp, fmt.dtfd_string); 193178173Simp 194178173Simp free(fmt.dtfd_string); 195178173Simp 196178173Simp if (dtp->dt_formats[rec->dtrd_format - 1] == NULL) { 197178173Simp rval = -1; /* dt_errno is set for us */ 198178173Simp goto err; 199178173Simp } 200178173Simp } 201178173Simp 202178173Simp dtp->dt_pdesc[id] = probe; 203178173Simp dtp->dt_edesc[id] = enabled; 204178173Simp 205178173Simp return (0); 206178173Simp 207178173Simperr: 208178173Simp /* 209178173Simp * If we failed, free our allocated probes. Note that if we failed 210178173Simp * while allocating formats, we aren't going to free formats that 211178173Simp * we have already allocated. This is okay; these formats are 212178173Simp * hanging off of dt_formats and will therefore not be leaked. 213178173Simp */ 214178173Simp free(enabled); 215178173Simp free(probe); 216178173Simp return (rval); 217178173Simp} 218178173Simp 219178173Simpint 220178173Simpdt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid, 221178173Simp dtrace_eprobedesc_t **epdp, dtrace_probedesc_t **pdp) 222178173Simp{ 223178173Simp int rval; 224178173Simp 225178173Simp if (epid >= dtp->dt_maxprobe || dtp->dt_pdesc[epid] == NULL) { 226178173Simp if ((rval = dt_epid_add(dtp, epid)) != 0) 227178173Simp return (rval); 228178173Simp } 229178173Simp 230178173Simp assert(epid < dtp->dt_maxprobe); 231178173Simp assert(dtp->dt_edesc[epid] != NULL); 232178173Simp assert(dtp->dt_pdesc[epid] != NULL); 233178173Simp *epdp = dtp->dt_edesc[epid]; 234178173Simp *pdp = dtp->dt_pdesc[epid]; 235178173Simp 236178173Simp return (0); 237178173Simp} 238178173Simp 239178173Simpvoid 240178173Simpdt_epid_destroy(dtrace_hdl_t *dtp) 241178173Simp{ 242178173Simp size_t i; 243178173Simp 244178173Simp assert((dtp->dt_pdesc != NULL && dtp->dt_edesc != NULL && 245178173Simp dtp->dt_maxprobe > 0) || (dtp->dt_pdesc == NULL && 246178173Simp dtp->dt_edesc == NULL && dtp->dt_maxprobe == 0)); 247178173Simp 248178173Simp if (dtp->dt_pdesc == NULL) 249178173Simp return; 250178173Simp 251178173Simp for (i = 0; i < dtp->dt_maxprobe; i++) { 252178173Simp if (dtp->dt_edesc[i] == NULL) { 253178173Simp assert(dtp->dt_pdesc[i] == NULL); 254178173Simp continue; 255178173Simp } 256178173Simp 257178173Simp assert(dtp->dt_pdesc[i] != NULL); 258178173Simp free(dtp->dt_edesc[i]); 259178173Simp free(dtp->dt_pdesc[i]); 260178173Simp } 261178173Simp 262178173Simp free(dtp->dt_pdesc); 263178173Simp dtp->dt_pdesc = NULL; 264178173Simp 265178173Simp free(dtp->dt_edesc); 266178173Simp dtp->dt_edesc = NULL; 267178173Simp dtp->dt_maxprobe = 0; 268178173Simp} 269178173Simp 270178173Simpvoid * 271178173Simpdt_format_lookup(dtrace_hdl_t *dtp, int format) 272178173Simp{ 273178173Simp if (format == 0 || format > dtp->dt_maxformat) 274178173Simp return (NULL); 275178173Simp 276183173Simp if (dtp->dt_formats == NULL) 277178173Simp return (NULL); 278178173Simp 279178173Simp return (dtp->dt_formats[format - 1]); 280178173Simp} 281178173Simp 282178173Simpvoid 283178173Simpdt_format_destroy(dtrace_hdl_t *dtp) 284178173Simp{ 285178173Simp int i; 286178173Simp 287178173Simp for (i = 0; i < dtp->dt_maxformat; i++) { 288178173Simp if (dtp->dt_formats[i] != NULL) 289178173Simp dt_printf_destroy(dtp->dt_formats[i]); 290178173Simp } 291178173Simp 292178173Simp free(dtp->dt_formats); 293178173Simp dtp->dt_formats = NULL; 294178173Simp} 295178173Simp 296178173Simpstatic int 297178173Simpdt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id) 298178173Simp{ 299178173Simp dtrace_id_t max; 300178173Simp dtrace_epid_t epid; 301178173Simp int rval; 302178173Simp 303178173Simp while (id >= (max = dtp->dt_maxagg) || dtp->dt_aggdesc == NULL) { 304178173Simp dtrace_id_t new_max = max ? (max << 1) : 1; 305178173Simp size_t nsize = new_max * sizeof (void *); 306178173Simp dtrace_aggdesc_t **new_aggdesc; 307178173Simp 308178173Simp if ((new_aggdesc = malloc(nsize)) == NULL) 309178173Simp return (dt_set_errno(dtp, EDT_NOMEM)); 310178173Simp 311178173Simp bzero(new_aggdesc, nsize); 312178173Simp 313178173Simp if (dtp->dt_aggdesc != NULL) { 314178173Simp bcopy(dtp->dt_aggdesc, new_aggdesc, 315178173Simp max * sizeof (void *)); 316178173Simp free(dtp->dt_aggdesc); 317178173Simp } 318178173Simp 319178173Simp dtp->dt_aggdesc = new_aggdesc; 320178173Simp dtp->dt_maxagg = new_max; 321178173Simp } 322178173Simp 323178173Simp if (dtp->dt_aggdesc[id] == NULL) { 324178173Simp dtrace_aggdesc_t *agg, *nagg; 325178173Simp 326178173Simp if ((agg = malloc(sizeof (dtrace_aggdesc_t))) == NULL) 327178173Simp return (dt_set_errno(dtp, EDT_NOMEM)); 328178173Simp 329178173Simp bzero(agg, sizeof (dtrace_aggdesc_t)); 330178173Simp agg->dtagd_id = id; 331178173Simp agg->dtagd_nrecs = 1; 332183173Simp 333178173Simp#if defined(sun) 334178173Simp if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg) == -1) { 335178173Simp#else 336178173Simp if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg) == -1) { 337178173Simp#endif 338178173Simp rval = dt_set_errno(dtp, errno); 339178173Simp free(agg); 340178173Simp return (rval); 341178173Simp } 342178173Simp 343178173Simp if (DTRACE_SIZEOF_AGGDESC(agg) != sizeof (*agg)) { 344178173Simp /* 345178173Simp * There must be more than one action. Allocate the 346178173Simp * appropriate amount of space and try again. 347178173Simp */ 348178173Simp if ((nagg = malloc(DTRACE_SIZEOF_AGGDESC(agg))) != NULL) 349178173Simp bcopy(agg, nagg, sizeof (*agg)); 350178173Simp 351178173Simp free(agg); 352178173Simp 353183173Simp if ((agg = nagg) == NULL) 354178173Simp return (dt_set_errno(dtp, EDT_NOMEM)); 355178173Simp 356178173Simp#if defined(sun) 357178173Simp rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg); 358178173Simp#else 359178173Simp rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg); 360178173Simp#endif 361178173Simp 362178173Simp if (rval == -1) { 363178173Simp rval = dt_set_errno(dtp, errno); 364178173Simp free(agg); 365178173Simp return (rval); 366178173Simp } 367178173Simp } 368178173Simp 369178173Simp /* 370178173Simp * If we have a uarg, it's a pointer to the compiler-generated 371178173Simp * statement; we'll use this value to get the name and 372178173Simp * compiler-generated variable ID for the aggregation. If 373178173Simp * we're grabbing an anonymous enabling, this pointer value 374178173Simp * is obviously meaningless -- and in this case, we can't 375178173Simp * provide the compiler-generated aggregation information. 376178173Simp */ 377178173Simp if (dtp->dt_options[DTRACEOPT_GRABANON] == DTRACEOPT_UNSET && 378178173Simp agg->dtagd_rec[0].dtrd_uarg != 0) { 379178173Simp dtrace_stmtdesc_t *sdp; 380178173Simp dt_ident_t *aid; 381178173Simp 382178173Simp sdp = (dtrace_stmtdesc_t *)(uintptr_t) 383178173Simp agg->dtagd_rec[0].dtrd_uarg; 384178173Simp aid = sdp->dtsd_aggdata; 385178173Simp agg->dtagd_name = aid->di_name; 386178173Simp agg->dtagd_varid = aid->di_id; 387178173Simp } else { 388178173Simp agg->dtagd_varid = DTRACE_AGGVARIDNONE; 389178173Simp } 390178173Simp 391178173Simp if ((epid = agg->dtagd_epid) >= dtp->dt_maxprobe || 392178173Simp dtp->dt_pdesc[epid] == NULL) { 393178173Simp if ((rval = dt_epid_add(dtp, epid)) != 0) { 394178173Simp free(agg); 395178173Simp return (rval); 396178173Simp } 397178173Simp } 398178173Simp 399178173Simp dtp->dt_aggdesc[id] = agg; 400178173Simp } 401178173Simp 402178173Simp return (0); 403178173Simp} 404178173Simp 405178173Simpint 406178173Simpdt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid, 407178173Simp dtrace_aggdesc_t **adp) 408178173Simp{ 409178173Simp int rval; 410178173Simp 411178173Simp if (aggid >= dtp->dt_maxagg || dtp->dt_aggdesc[aggid] == NULL) { 412178173Simp if ((rval = dt_aggid_add(dtp, aggid)) != 0) 413178173Simp return (rval); 414178173Simp } 415178173Simp 416178173Simp assert(aggid < dtp->dt_maxagg); 417178173Simp assert(dtp->dt_aggdesc[aggid] != NULL); 418178173Simp *adp = dtp->dt_aggdesc[aggid]; 419178173Simp 420178173Simp return (0); 421178173Simp} 422178173Simp 423178173Simpvoid 424178173Simpdt_aggid_destroy(dtrace_hdl_t *dtp) 425178173Simp{ 426178173Simp size_t i; 427178173Simp 428178173Simp assert((dtp->dt_aggdesc != NULL && dtp->dt_maxagg != 0) || 429178173Simp (dtp->dt_aggdesc == NULL && dtp->dt_maxagg == 0)); 430178173Simp 431178173Simp if (dtp->dt_aggdesc == NULL) 432178173Simp return; 433178173Simp 434178173Simp for (i = 0; i < dtp->dt_maxagg; i++) { 435178173Simp if (dtp->dt_aggdesc[i] != NULL) 436178173Simp free(dtp->dt_aggdesc[i]); 437178173Simp } 438178173Simp 439178173Simp free(dtp->dt_aggdesc); 440178173Simp dtp->dt_aggdesc = NULL; 441178173Simp dtp->dt_maxagg = 0; 442178173Simp} 443178173Simp