dt_map.c revision 178562
1178479Sjb/* 2178479Sjb * CDDL HEADER START 3178479Sjb * 4178479Sjb * The contents of this file are subject to the terms of the 5178479Sjb * Common Development and Distribution License (the "License"). 6178479Sjb * You may not use this file except in compliance with the License. 7178479Sjb * 8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9178479Sjb * or http://www.opensolaris.org/os/licensing. 10178479Sjb * See the License for the specific language governing permissions 11178479Sjb * and limitations under the License. 12178479Sjb * 13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each 14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15178479Sjb * If applicable, add the following below this CDDL HEADER, with the 16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18178479Sjb * 19178479Sjb * CDDL HEADER END 20178479Sjb */ 21178479Sjb/* 22178479Sjb * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23178479Sjb * Use is subject to license terms. 24178479Sjb */ 25178479Sjb 26178479Sjb#pragma ident "%Z%%M% %I% %E% SMI" 27178479Sjb 28178479Sjb#include <stdlib.h> 29178479Sjb#include <strings.h> 30178479Sjb#include <errno.h> 31178479Sjb#include <unistd.h> 32178479Sjb#include <assert.h> 33178479Sjb 34178479Sjb#include <dt_impl.h> 35178479Sjb#include <dt_printf.h> 36178479Sjb 37178479Sjbstatic int 38178479Sjbdt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id) 39178479Sjb{ 40178479Sjb dtrace_id_t max; 41178479Sjb int rval, i, maxformat; 42178479Sjb dtrace_eprobedesc_t *enabled, *nenabled; 43178479Sjb dtrace_probedesc_t *probe; 44178479Sjb 45178479Sjb while (id >= (max = dtp->dt_maxprobe) || dtp->dt_pdesc == NULL) { 46178479Sjb dtrace_id_t new_max = max ? (max << 1) : 1; 47178479Sjb size_t nsize = new_max * sizeof (void *); 48178479Sjb dtrace_probedesc_t **new_pdesc; 49178479Sjb dtrace_eprobedesc_t **new_edesc; 50178479Sjb 51178479Sjb if ((new_pdesc = malloc(nsize)) == NULL || 52178479Sjb (new_edesc = malloc(nsize)) == NULL) { 53178479Sjb free(new_pdesc); 54178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 55178479Sjb } 56178479Sjb 57178479Sjb bzero(new_pdesc, nsize); 58178479Sjb bzero(new_edesc, nsize); 59178479Sjb 60178479Sjb if (dtp->dt_pdesc != NULL) { 61178479Sjb size_t osize = max * sizeof (void *); 62178479Sjb 63178479Sjb bcopy(dtp->dt_pdesc, new_pdesc, osize); 64178479Sjb free(dtp->dt_pdesc); 65178479Sjb 66178479Sjb bcopy(dtp->dt_edesc, new_edesc, osize); 67178479Sjb free(dtp->dt_edesc); 68178479Sjb } 69178479Sjb 70178479Sjb dtp->dt_pdesc = new_pdesc; 71178479Sjb dtp->dt_edesc = new_edesc; 72178479Sjb dtp->dt_maxprobe = new_max; 73178479Sjb } 74178479Sjb 75178479Sjb if (dtp->dt_pdesc[id] != NULL) 76178479Sjb return (0); 77178479Sjb 78178479Sjb if ((enabled = malloc(sizeof (dtrace_eprobedesc_t))) == NULL) 79178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 80178479Sjb 81178479Sjb bzero(enabled, sizeof (dtrace_eprobedesc_t)); 82178479Sjb enabled->dtepd_epid = id; 83178479Sjb enabled->dtepd_nrecs = 1; 84178479Sjb 85178562Sjb#if defined(sun) 86178479Sjb if (dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled) == -1) { 87178562Sjb#else 88178562Sjb if (dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled) == -1) { 89178562Sjb#endif 90178479Sjb rval = dt_set_errno(dtp, errno); 91178479Sjb free(enabled); 92178479Sjb return (rval); 93178479Sjb } 94178479Sjb 95178479Sjb if (DTRACE_SIZEOF_EPROBEDESC(enabled) != sizeof (*enabled)) { 96178479Sjb /* 97178479Sjb * There must be more than one action. Allocate the 98178479Sjb * appropriate amount of space and try again. 99178479Sjb */ 100178479Sjb if ((nenabled = 101178479Sjb malloc(DTRACE_SIZEOF_EPROBEDESC(enabled))) != NULL) 102178479Sjb bcopy(enabled, nenabled, sizeof (*enabled)); 103178479Sjb 104178479Sjb free(enabled); 105178479Sjb 106178479Sjb if ((enabled = nenabled) == NULL) 107178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 108178479Sjb 109178562Sjb#if defined(sun) 110178479Sjb rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled); 111178562Sjb#else 112178562Sjb rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled); 113178562Sjb#endif 114178479Sjb 115178479Sjb if (rval == -1) { 116178479Sjb rval = dt_set_errno(dtp, errno); 117178479Sjb free(enabled); 118178479Sjb return (rval); 119178479Sjb } 120178479Sjb } 121178479Sjb 122178479Sjb if ((probe = malloc(sizeof (dtrace_probedesc_t))) == NULL) { 123178479Sjb free(enabled); 124178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 125178479Sjb } 126178479Sjb 127178479Sjb probe->dtpd_id = enabled->dtepd_probeid; 128178479Sjb 129178479Sjb if (dt_ioctl(dtp, DTRACEIOC_PROBES, probe) == -1) { 130178479Sjb rval = dt_set_errno(dtp, errno); 131178479Sjb goto err; 132178479Sjb } 133178479Sjb 134178479Sjb for (i = 0; i < enabled->dtepd_nrecs; i++) { 135178479Sjb dtrace_fmtdesc_t fmt; 136178479Sjb dtrace_recdesc_t *rec = &enabled->dtepd_rec[i]; 137178479Sjb 138178479Sjb if (!DTRACEACT_ISPRINTFLIKE(rec->dtrd_action)) 139178479Sjb continue; 140178479Sjb 141178479Sjb if (rec->dtrd_format == 0) 142178479Sjb continue; 143178479Sjb 144178479Sjb if (rec->dtrd_format <= dtp->dt_maxformat && 145178479Sjb dtp->dt_formats[rec->dtrd_format - 1] != NULL) 146178479Sjb continue; 147178479Sjb 148178479Sjb bzero(&fmt, sizeof (fmt)); 149178479Sjb fmt.dtfd_format = rec->dtrd_format; 150178479Sjb fmt.dtfd_string = NULL; 151178479Sjb fmt.dtfd_length = 0; 152178479Sjb 153178479Sjb if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) { 154178479Sjb rval = dt_set_errno(dtp, errno); 155178479Sjb goto err; 156178479Sjb } 157178479Sjb 158178479Sjb if ((fmt.dtfd_string = malloc(fmt.dtfd_length)) == NULL) { 159178479Sjb rval = dt_set_errno(dtp, EDT_NOMEM); 160178479Sjb goto err; 161178479Sjb } 162178479Sjb 163178479Sjb if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) { 164178479Sjb rval = dt_set_errno(dtp, errno); 165178479Sjb free(fmt.dtfd_string); 166178479Sjb goto err; 167178479Sjb } 168178479Sjb 169178479Sjb while (rec->dtrd_format > (maxformat = dtp->dt_maxformat)) { 170178479Sjb int new_max = maxformat ? (maxformat << 1) : 1; 171178479Sjb size_t nsize = new_max * sizeof (void *); 172178479Sjb size_t osize = maxformat * sizeof (void *); 173178479Sjb void **new_formats = malloc(nsize); 174178479Sjb 175178479Sjb if (new_formats == NULL) { 176178479Sjb rval = dt_set_errno(dtp, EDT_NOMEM); 177178479Sjb free(fmt.dtfd_string); 178178479Sjb goto err; 179178479Sjb } 180178479Sjb 181178479Sjb bzero(new_formats, nsize); 182178479Sjb bcopy(dtp->dt_formats, new_formats, osize); 183178479Sjb free(dtp->dt_formats); 184178479Sjb 185178479Sjb dtp->dt_formats = new_formats; 186178479Sjb dtp->dt_maxformat = new_max; 187178479Sjb } 188178479Sjb 189178479Sjb dtp->dt_formats[rec->dtrd_format - 1] = 190178479Sjb rec->dtrd_action == DTRACEACT_PRINTA ? 191178479Sjb dtrace_printa_create(dtp, fmt.dtfd_string) : 192178479Sjb dtrace_printf_create(dtp, fmt.dtfd_string); 193178479Sjb 194178479Sjb free(fmt.dtfd_string); 195178479Sjb 196178479Sjb if (dtp->dt_formats[rec->dtrd_format - 1] == NULL) { 197178479Sjb rval = -1; /* dt_errno is set for us */ 198178479Sjb goto err; 199178479Sjb } 200178479Sjb } 201178479Sjb 202178479Sjb dtp->dt_pdesc[id] = probe; 203178479Sjb dtp->dt_edesc[id] = enabled; 204178479Sjb 205178479Sjb return (0); 206178479Sjb 207178479Sjberr: 208178479Sjb /* 209178479Sjb * If we failed, free our allocated probes. Note that if we failed 210178479Sjb * while allocating formats, we aren't going to free formats that 211178479Sjb * we have already allocated. This is okay; these formats are 212178479Sjb * hanging off of dt_formats and will therefore not be leaked. 213178479Sjb */ 214178479Sjb free(enabled); 215178479Sjb free(probe); 216178479Sjb return (rval); 217178479Sjb} 218178479Sjb 219178479Sjbint 220178479Sjbdt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid, 221178479Sjb dtrace_eprobedesc_t **epdp, dtrace_probedesc_t **pdp) 222178479Sjb{ 223178479Sjb int rval; 224178479Sjb 225178479Sjb if (epid >= dtp->dt_maxprobe || dtp->dt_pdesc[epid] == NULL) { 226178479Sjb if ((rval = dt_epid_add(dtp, epid)) != 0) 227178479Sjb return (rval); 228178479Sjb } 229178479Sjb 230178479Sjb assert(epid < dtp->dt_maxprobe); 231178479Sjb assert(dtp->dt_edesc[epid] != NULL); 232178479Sjb assert(dtp->dt_pdesc[epid] != NULL); 233178479Sjb *epdp = dtp->dt_edesc[epid]; 234178479Sjb *pdp = dtp->dt_pdesc[epid]; 235178479Sjb 236178479Sjb return (0); 237178479Sjb} 238178479Sjb 239178479Sjbvoid 240178479Sjbdt_epid_destroy(dtrace_hdl_t *dtp) 241178479Sjb{ 242178479Sjb size_t i; 243178479Sjb 244178479Sjb assert((dtp->dt_pdesc != NULL && dtp->dt_edesc != NULL && 245178479Sjb dtp->dt_maxprobe > 0) || (dtp->dt_pdesc == NULL && 246178479Sjb dtp->dt_edesc == NULL && dtp->dt_maxprobe == 0)); 247178479Sjb 248178479Sjb if (dtp->dt_pdesc == NULL) 249178479Sjb return; 250178479Sjb 251178479Sjb for (i = 0; i < dtp->dt_maxprobe; i++) { 252178479Sjb if (dtp->dt_edesc[i] == NULL) { 253178479Sjb assert(dtp->dt_pdesc[i] == NULL); 254178479Sjb continue; 255178479Sjb } 256178479Sjb 257178479Sjb assert(dtp->dt_pdesc[i] != NULL); 258178479Sjb free(dtp->dt_edesc[i]); 259178479Sjb free(dtp->dt_pdesc[i]); 260178479Sjb } 261178479Sjb 262178479Sjb free(dtp->dt_pdesc); 263178479Sjb dtp->dt_pdesc = NULL; 264178479Sjb 265178479Sjb free(dtp->dt_edesc); 266178479Sjb dtp->dt_edesc = NULL; 267178479Sjb dtp->dt_maxprobe = 0; 268178479Sjb} 269178479Sjb 270178479Sjbvoid * 271178479Sjbdt_format_lookup(dtrace_hdl_t *dtp, int format) 272178479Sjb{ 273178479Sjb if (format == 0 || format > dtp->dt_maxformat) 274178479Sjb return (NULL); 275178479Sjb 276178479Sjb if (dtp->dt_formats == NULL) 277178479Sjb return (NULL); 278178479Sjb 279178479Sjb return (dtp->dt_formats[format - 1]); 280178479Sjb} 281178479Sjb 282178479Sjbvoid 283178479Sjbdt_format_destroy(dtrace_hdl_t *dtp) 284178479Sjb{ 285178479Sjb int i; 286178479Sjb 287178479Sjb for (i = 0; i < dtp->dt_maxformat; i++) { 288178479Sjb if (dtp->dt_formats[i] != NULL) 289178479Sjb dt_printf_destroy(dtp->dt_formats[i]); 290178479Sjb } 291178479Sjb 292178479Sjb free(dtp->dt_formats); 293178479Sjb dtp->dt_formats = NULL; 294178479Sjb} 295178479Sjb 296178479Sjbstatic int 297178479Sjbdt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id) 298178479Sjb{ 299178479Sjb dtrace_id_t max; 300178479Sjb dtrace_epid_t epid; 301178479Sjb int rval; 302178479Sjb 303178479Sjb while (id >= (max = dtp->dt_maxagg) || dtp->dt_aggdesc == NULL) { 304178479Sjb dtrace_id_t new_max = max ? (max << 1) : 1; 305178479Sjb size_t nsize = new_max * sizeof (void *); 306178479Sjb dtrace_aggdesc_t **new_aggdesc; 307178479Sjb 308178479Sjb if ((new_aggdesc = malloc(nsize)) == NULL) 309178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 310178479Sjb 311178479Sjb bzero(new_aggdesc, nsize); 312178479Sjb 313178479Sjb if (dtp->dt_aggdesc != NULL) { 314178479Sjb bcopy(dtp->dt_aggdesc, new_aggdesc, 315178479Sjb max * sizeof (void *)); 316178479Sjb free(dtp->dt_aggdesc); 317178479Sjb } 318178479Sjb 319178479Sjb dtp->dt_aggdesc = new_aggdesc; 320178479Sjb dtp->dt_maxagg = new_max; 321178479Sjb } 322178479Sjb 323178479Sjb if (dtp->dt_aggdesc[id] == NULL) { 324178479Sjb dtrace_aggdesc_t *agg, *nagg; 325178479Sjb 326178479Sjb if ((agg = malloc(sizeof (dtrace_aggdesc_t))) == NULL) 327178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 328178479Sjb 329178479Sjb bzero(agg, sizeof (dtrace_aggdesc_t)); 330178479Sjb agg->dtagd_id = id; 331178479Sjb agg->dtagd_nrecs = 1; 332178479Sjb 333178562Sjb#if defined(sun) 334178479Sjb if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg) == -1) { 335178562Sjb#else 336178562Sjb if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg) == -1) { 337178562Sjb#endif 338178479Sjb rval = dt_set_errno(dtp, errno); 339178479Sjb free(agg); 340178479Sjb return (rval); 341178479Sjb } 342178479Sjb 343178479Sjb if (DTRACE_SIZEOF_AGGDESC(agg) != sizeof (*agg)) { 344178479Sjb /* 345178479Sjb * There must be more than one action. Allocate the 346178479Sjb * appropriate amount of space and try again. 347178479Sjb */ 348178479Sjb if ((nagg = malloc(DTRACE_SIZEOF_AGGDESC(agg))) != NULL) 349178479Sjb bcopy(agg, nagg, sizeof (*agg)); 350178479Sjb 351178479Sjb free(agg); 352178479Sjb 353178479Sjb if ((agg = nagg) == NULL) 354178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 355178479Sjb 356178562Sjb#if defined(sun) 357178479Sjb rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg); 358178562Sjb#else 359178562Sjb rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg); 360178562Sjb#endif 361178479Sjb 362178479Sjb if (rval == -1) { 363178479Sjb rval = dt_set_errno(dtp, errno); 364178479Sjb free(agg); 365178479Sjb return (rval); 366178479Sjb } 367178479Sjb } 368178479Sjb 369178479Sjb /* 370178479Sjb * If we have a uarg, it's a pointer to the compiler-generated 371178479Sjb * statement; we'll use this value to get the name and 372178479Sjb * compiler-generated variable ID for the aggregation. If 373178479Sjb * we're grabbing an anonymous enabling, this pointer value 374178479Sjb * is obviously meaningless -- and in this case, we can't 375178479Sjb * provide the compiler-generated aggregation information. 376178479Sjb */ 377178479Sjb if (dtp->dt_options[DTRACEOPT_GRABANON] == DTRACEOPT_UNSET && 378178562Sjb agg->dtagd_rec[0].dtrd_uarg != 0) { 379178479Sjb dtrace_stmtdesc_t *sdp; 380178479Sjb dt_ident_t *aid; 381178479Sjb 382178479Sjb sdp = (dtrace_stmtdesc_t *)(uintptr_t) 383178479Sjb agg->dtagd_rec[0].dtrd_uarg; 384178479Sjb aid = sdp->dtsd_aggdata; 385178479Sjb agg->dtagd_name = aid->di_name; 386178479Sjb agg->dtagd_varid = aid->di_id; 387178479Sjb } else { 388178479Sjb agg->dtagd_varid = DTRACE_AGGVARIDNONE; 389178479Sjb } 390178479Sjb 391178479Sjb if ((epid = agg->dtagd_epid) >= dtp->dt_maxprobe || 392178479Sjb dtp->dt_pdesc[epid] == NULL) { 393178479Sjb if ((rval = dt_epid_add(dtp, epid)) != 0) { 394178479Sjb free(agg); 395178479Sjb return (rval); 396178479Sjb } 397178479Sjb } 398178479Sjb 399178479Sjb dtp->dt_aggdesc[id] = agg; 400178479Sjb } 401178479Sjb 402178479Sjb return (0); 403178479Sjb} 404178479Sjb 405178479Sjbint 406178479Sjbdt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid, 407178479Sjb dtrace_aggdesc_t **adp) 408178479Sjb{ 409178479Sjb int rval; 410178479Sjb 411178479Sjb if (aggid >= dtp->dt_maxagg || dtp->dt_aggdesc[aggid] == NULL) { 412178479Sjb if ((rval = dt_aggid_add(dtp, aggid)) != 0) 413178479Sjb return (rval); 414178479Sjb } 415178479Sjb 416178479Sjb assert(aggid < dtp->dt_maxagg); 417178479Sjb assert(dtp->dt_aggdesc[aggid] != NULL); 418178479Sjb *adp = dtp->dt_aggdesc[aggid]; 419178479Sjb 420178479Sjb return (0); 421178479Sjb} 422178479Sjb 423178479Sjbvoid 424178479Sjbdt_aggid_destroy(dtrace_hdl_t *dtp) 425178479Sjb{ 426178479Sjb size_t i; 427178479Sjb 428178479Sjb assert((dtp->dt_aggdesc != NULL && dtp->dt_maxagg != 0) || 429178479Sjb (dtp->dt_aggdesc == NULL && dtp->dt_maxagg == 0)); 430178479Sjb 431178479Sjb if (dtp->dt_aggdesc == NULL) 432178479Sjb return; 433178479Sjb 434178479Sjb for (i = 0; i < dtp->dt_maxagg; i++) { 435178479Sjb if (dtp->dt_aggdesc[i] != NULL) 436178479Sjb free(dtp->dt_aggdesc[i]); 437178479Sjb } 438178479Sjb 439178479Sjb free(dtp->dt_aggdesc); 440178479Sjb dtp->dt_aggdesc = NULL; 441178479Sjb dtp->dt_maxagg = 0; 442178479Sjb} 443