xref: /freebsd/cddl/contrib/opensolaris/lib/libdtrace/common/dt_map.c (revision 98e0ffaefb0f241cda3a72395d3be04192ae0d47)
16ff6d951SJohn Birrell /*
26ff6d951SJohn Birrell  * CDDL HEADER START
36ff6d951SJohn Birrell  *
46ff6d951SJohn Birrell  * The contents of this file are subject to the terms of the
56ff6d951SJohn Birrell  * Common Development and Distribution License (the "License").
66ff6d951SJohn Birrell  * You may not use this file except in compliance with the License.
76ff6d951SJohn Birrell  *
86ff6d951SJohn Birrell  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96ff6d951SJohn Birrell  * or http://www.opensolaris.org/os/licensing.
106ff6d951SJohn Birrell  * See the License for the specific language governing permissions
116ff6d951SJohn Birrell  * and limitations under the License.
126ff6d951SJohn Birrell  *
136ff6d951SJohn Birrell  * When distributing Covered Code, include this CDDL HEADER in each
146ff6d951SJohn Birrell  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156ff6d951SJohn Birrell  * If applicable, add the following below this CDDL HEADER, with the
166ff6d951SJohn Birrell  * fields enclosed by brackets "[]" replaced with your own identifying
176ff6d951SJohn Birrell  * information: Portions Copyright [yyyy] [name of copyright owner]
186ff6d951SJohn Birrell  *
196ff6d951SJohn Birrell  * CDDL HEADER END
206ff6d951SJohn Birrell  */
216ff6d951SJohn Birrell /*
226ff6d951SJohn Birrell  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
236ff6d951SJohn Birrell  * Use is subject to license terms.
246ff6d951SJohn Birrell  */
256ff6d951SJohn Birrell 
2654727873SPedro F. Giffuni /*
2754727873SPedro F. Giffuni  * Copyright (c) 2011 by Delphix. All rights reserved.
2854727873SPedro F. Giffuni  */
296ff6d951SJohn Birrell 
306ff6d951SJohn Birrell #include <stdlib.h>
316ff6d951SJohn Birrell #include <strings.h>
326ff6d951SJohn Birrell #include <errno.h>
336ff6d951SJohn Birrell #include <unistd.h>
346ff6d951SJohn Birrell #include <assert.h>
356ff6d951SJohn Birrell 
366ff6d951SJohn Birrell #include <dt_impl.h>
376ff6d951SJohn Birrell #include <dt_printf.h>
386ff6d951SJohn Birrell 
396ff6d951SJohn Birrell static int
dt_strdata_add(dtrace_hdl_t * dtp,dtrace_recdesc_t * rec,void *** data,int * max)4054727873SPedro F. Giffuni dt_strdata_add(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, void ***data, int *max)
4154727873SPedro F. Giffuni {
4247890cb5SMark Johnston 	int maxformat, rval;
4354727873SPedro F. Giffuni 	dtrace_fmtdesc_t fmt;
4454727873SPedro F. Giffuni 	void *result;
4554727873SPedro F. Giffuni 
4654727873SPedro F. Giffuni 	if (rec->dtrd_format == 0)
4754727873SPedro F. Giffuni 		return (0);
4854727873SPedro F. Giffuni 
4954727873SPedro F. Giffuni 	if (rec->dtrd_format <= *max &&
5054727873SPedro F. Giffuni 	    (*data)[rec->dtrd_format - 1] != NULL) {
5154727873SPedro F. Giffuni 		return (0);
5254727873SPedro F. Giffuni 	}
5354727873SPedro F. Giffuni 
5454727873SPedro F. Giffuni 	bzero(&fmt, sizeof (fmt));
5554727873SPedro F. Giffuni 	fmt.dtfd_format = rec->dtrd_format;
5654727873SPedro F. Giffuni 	fmt.dtfd_string = NULL;
5754727873SPedro F. Giffuni 	fmt.dtfd_length = 0;
5854727873SPedro F. Giffuni 
5954727873SPedro F. Giffuni 	if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1)
6054727873SPedro F. Giffuni 		return (dt_set_errno(dtp, errno));
6154727873SPedro F. Giffuni 
6254727873SPedro F. Giffuni 	if ((fmt.dtfd_string = dt_alloc(dtp, fmt.dtfd_length)) == NULL)
6354727873SPedro F. Giffuni 		return (dt_set_errno(dtp, EDT_NOMEM));
6454727873SPedro F. Giffuni 
6554727873SPedro F. Giffuni 	if (dt_ioctl(dtp, DTRACEIOC_FORMAT, &fmt) == -1) {
6647890cb5SMark Johnston 		rval = dt_set_errno(dtp, errno);
6754727873SPedro F. Giffuni 		free(fmt.dtfd_string);
6847890cb5SMark Johnston 		return (rval);
6954727873SPedro F. Giffuni 	}
7054727873SPedro F. Giffuni 
7154727873SPedro F. Giffuni 	while (rec->dtrd_format > (maxformat = *max)) {
7254727873SPedro F. Giffuni 		int new_max = maxformat ? (maxformat << 1) : 1;
7354727873SPedro F. Giffuni 		size_t nsize = new_max * sizeof (void *);
7454727873SPedro F. Giffuni 		size_t osize = maxformat * sizeof (void *);
7554727873SPedro F. Giffuni 		void **new_data = dt_zalloc(dtp, nsize);
7654727873SPedro F. Giffuni 
7754727873SPedro F. Giffuni 		if (new_data == NULL) {
7854727873SPedro F. Giffuni 			dt_free(dtp, fmt.dtfd_string);
7954727873SPedro F. Giffuni 			return (dt_set_errno(dtp, EDT_NOMEM));
8054727873SPedro F. Giffuni 		}
8154727873SPedro F. Giffuni 
8254727873SPedro F. Giffuni 		bcopy(*data, new_data, osize);
8354727873SPedro F. Giffuni 		free(*data);
8454727873SPedro F. Giffuni 
8554727873SPedro F. Giffuni 		*data = new_data;
8654727873SPedro F. Giffuni 		*max = new_max;
8754727873SPedro F. Giffuni 	}
8854727873SPedro F. Giffuni 
8954727873SPedro F. Giffuni 	switch (rec->dtrd_action) {
9054727873SPedro F. Giffuni 	case DTRACEACT_DIFEXPR:
9154727873SPedro F. Giffuni 		result = fmt.dtfd_string;
9254727873SPedro F. Giffuni 		break;
9354727873SPedro F. Giffuni 	case DTRACEACT_PRINTA:
9454727873SPedro F. Giffuni 		result = dtrace_printa_create(dtp, fmt.dtfd_string);
9554727873SPedro F. Giffuni 		dt_free(dtp, fmt.dtfd_string);
9654727873SPedro F. Giffuni 		break;
9754727873SPedro F. Giffuni 	default:
9854727873SPedro F. Giffuni 		result = dtrace_printf_create(dtp, fmt.dtfd_string);
9954727873SPedro F. Giffuni 		dt_free(dtp, fmt.dtfd_string);
10054727873SPedro F. Giffuni 		break;
10154727873SPedro F. Giffuni 	}
10254727873SPedro F. Giffuni 
10354727873SPedro F. Giffuni 	if (result == NULL)
10454727873SPedro F. Giffuni 		return (-1);
10554727873SPedro F. Giffuni 
10654727873SPedro F. Giffuni 	(*data)[rec->dtrd_format - 1] = result;
10754727873SPedro F. Giffuni 
10854727873SPedro F. Giffuni 	return (0);
10954727873SPedro F. Giffuni }
11054727873SPedro F. Giffuni 
11154727873SPedro F. Giffuni static int
dt_epid_add(dtrace_hdl_t * dtp,dtrace_epid_t id)1126ff6d951SJohn Birrell dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
1136ff6d951SJohn Birrell {
1146ff6d951SJohn Birrell 	dtrace_id_t max;
11554727873SPedro F. Giffuni 	int rval, i;
1166ff6d951SJohn Birrell 	dtrace_eprobedesc_t *enabled, *nenabled;
1176ff6d951SJohn Birrell 	dtrace_probedesc_t *probe;
1186ff6d951SJohn Birrell 
1196ff6d951SJohn Birrell 	while (id >= (max = dtp->dt_maxprobe) || dtp->dt_pdesc == NULL) {
1206ff6d951SJohn Birrell 		dtrace_id_t new_max = max ? (max << 1) : 1;
1216ff6d951SJohn Birrell 		size_t nsize = new_max * sizeof (void *);
1226ff6d951SJohn Birrell 		dtrace_probedesc_t **new_pdesc;
1236ff6d951SJohn Birrell 		dtrace_eprobedesc_t **new_edesc;
1246ff6d951SJohn Birrell 
1256ff6d951SJohn Birrell 		if ((new_pdesc = malloc(nsize)) == NULL ||
1266ff6d951SJohn Birrell 		    (new_edesc = malloc(nsize)) == NULL) {
1276ff6d951SJohn Birrell 			free(new_pdesc);
1286ff6d951SJohn Birrell 			return (dt_set_errno(dtp, EDT_NOMEM));
1296ff6d951SJohn Birrell 		}
1306ff6d951SJohn Birrell 
1316ff6d951SJohn Birrell 		bzero(new_pdesc, nsize);
1326ff6d951SJohn Birrell 		bzero(new_edesc, nsize);
1336ff6d951SJohn Birrell 
1346ff6d951SJohn Birrell 		if (dtp->dt_pdesc != NULL) {
1356ff6d951SJohn Birrell 			size_t osize = max * sizeof (void *);
1366ff6d951SJohn Birrell 
1376ff6d951SJohn Birrell 			bcopy(dtp->dt_pdesc, new_pdesc, osize);
1386ff6d951SJohn Birrell 			free(dtp->dt_pdesc);
1396ff6d951SJohn Birrell 
1406ff6d951SJohn Birrell 			bcopy(dtp->dt_edesc, new_edesc, osize);
1416ff6d951SJohn Birrell 			free(dtp->dt_edesc);
1426ff6d951SJohn Birrell 		}
1436ff6d951SJohn Birrell 
1446ff6d951SJohn Birrell 		dtp->dt_pdesc = new_pdesc;
1456ff6d951SJohn Birrell 		dtp->dt_edesc = new_edesc;
1466ff6d951SJohn Birrell 		dtp->dt_maxprobe = new_max;
1476ff6d951SJohn Birrell 	}
1486ff6d951SJohn Birrell 
1496ff6d951SJohn Birrell 	if (dtp->dt_pdesc[id] != NULL)
1506ff6d951SJohn Birrell 		return (0);
1516ff6d951SJohn Birrell 
1526ff6d951SJohn Birrell 	if ((enabled = malloc(sizeof (dtrace_eprobedesc_t))) == NULL)
1536ff6d951SJohn Birrell 		return (dt_set_errno(dtp, EDT_NOMEM));
1546ff6d951SJohn Birrell 
1556ff6d951SJohn Birrell 	bzero(enabled, sizeof (dtrace_eprobedesc_t));
1566ff6d951SJohn Birrell 	enabled->dtepd_epid = id;
1576ff6d951SJohn Birrell 	enabled->dtepd_nrecs = 1;
1586ff6d951SJohn Birrell 
159*bc96366cSSteven Hartland #ifdef illumos
1606ff6d951SJohn Birrell 	if (dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled) == -1) {
161cd14ec81SJohn Birrell #else
162cd14ec81SJohn Birrell 	if (dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled) == -1) {
163cd14ec81SJohn Birrell #endif
1646ff6d951SJohn Birrell 		rval = dt_set_errno(dtp, errno);
1656ff6d951SJohn Birrell 		free(enabled);
1666ff6d951SJohn Birrell 		return (rval);
1676ff6d951SJohn Birrell 	}
1686ff6d951SJohn Birrell 
1696ff6d951SJohn Birrell 	if (DTRACE_SIZEOF_EPROBEDESC(enabled) != sizeof (*enabled)) {
1706ff6d951SJohn Birrell 		/*
1716ff6d951SJohn Birrell 		 * There must be more than one action.  Allocate the
1726ff6d951SJohn Birrell 		 * appropriate amount of space and try again.
1736ff6d951SJohn Birrell 		 */
1746ff6d951SJohn Birrell 		if ((nenabled =
1756ff6d951SJohn Birrell 		    malloc(DTRACE_SIZEOF_EPROBEDESC(enabled))) != NULL)
1766ff6d951SJohn Birrell 			bcopy(enabled, nenabled, sizeof (*enabled));
1776ff6d951SJohn Birrell 
1786ff6d951SJohn Birrell 		free(enabled);
1796ff6d951SJohn Birrell 
1806ff6d951SJohn Birrell 		if ((enabled = nenabled) == NULL)
1816ff6d951SJohn Birrell 			return (dt_set_errno(dtp, EDT_NOMEM));
1826ff6d951SJohn Birrell 
183*bc96366cSSteven Hartland #ifdef illumos
1846ff6d951SJohn Birrell 		rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled);
185cd14ec81SJohn Birrell #else
186cd14ec81SJohn Birrell 		rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, &enabled);
187cd14ec81SJohn Birrell #endif
1886ff6d951SJohn Birrell 
1896ff6d951SJohn Birrell 		if (rval == -1) {
1906ff6d951SJohn Birrell 			rval = dt_set_errno(dtp, errno);
1916ff6d951SJohn Birrell 			free(enabled);
1926ff6d951SJohn Birrell 			return (rval);
1936ff6d951SJohn Birrell 		}
1946ff6d951SJohn Birrell 	}
1956ff6d951SJohn Birrell 
1966ff6d951SJohn Birrell 	if ((probe = malloc(sizeof (dtrace_probedesc_t))) == NULL) {
1976ff6d951SJohn Birrell 		free(enabled);
1986ff6d951SJohn Birrell 		return (dt_set_errno(dtp, EDT_NOMEM));
1996ff6d951SJohn Birrell 	}
2006ff6d951SJohn Birrell 
2016ff6d951SJohn Birrell 	probe->dtpd_id = enabled->dtepd_probeid;
2026ff6d951SJohn Birrell 
2036ff6d951SJohn Birrell 	if (dt_ioctl(dtp, DTRACEIOC_PROBES, probe) == -1) {
2046ff6d951SJohn Birrell 		rval = dt_set_errno(dtp, errno);
2056ff6d951SJohn Birrell 		goto err;
2066ff6d951SJohn Birrell 	}
2076ff6d951SJohn Birrell 
2086ff6d951SJohn Birrell 	for (i = 0; i < enabled->dtepd_nrecs; i++) {
2096ff6d951SJohn Birrell 		dtrace_recdesc_t *rec = &enabled->dtepd_rec[i];
2106ff6d951SJohn Birrell 
21154727873SPedro F. Giffuni 		if (DTRACEACT_ISPRINTFLIKE(rec->dtrd_action)) {
21254727873SPedro F. Giffuni 			if (dt_strdata_add(dtp, rec, &dtp->dt_formats,
21354727873SPedro F. Giffuni 			    &dtp->dt_maxformat) != 0) {
21454727873SPedro F. Giffuni 				rval = -1;
2156ff6d951SJohn Birrell 				goto err;
2166ff6d951SJohn Birrell 			}
21754727873SPedro F. Giffuni 		} else if (rec->dtrd_action == DTRACEACT_DIFEXPR) {
21854727873SPedro F. Giffuni 			if (dt_strdata_add(dtp, rec,
21954727873SPedro F. Giffuni 			    (void ***)&dtp->dt_strdata,
22054727873SPedro F. Giffuni 			    &dtp->dt_maxstrdata) != 0) {
22154727873SPedro F. Giffuni 				rval = -1;
2226ff6d951SJohn Birrell 				goto err;
2236ff6d951SJohn Birrell 			}
2246ff6d951SJohn Birrell 		}
2256ff6d951SJohn Birrell 
2266ff6d951SJohn Birrell 	}
2276ff6d951SJohn Birrell 
2286ff6d951SJohn Birrell 	dtp->dt_pdesc[id] = probe;
2296ff6d951SJohn Birrell 	dtp->dt_edesc[id] = enabled;
2306ff6d951SJohn Birrell 
2316ff6d951SJohn Birrell 	return (0);
2326ff6d951SJohn Birrell 
2336ff6d951SJohn Birrell err:
2346ff6d951SJohn Birrell 	/*
2356ff6d951SJohn Birrell 	 * If we failed, free our allocated probes.  Note that if we failed
2366ff6d951SJohn Birrell 	 * while allocating formats, we aren't going to free formats that
2376ff6d951SJohn Birrell 	 * we have already allocated.  This is okay; these formats are
2386ff6d951SJohn Birrell 	 * hanging off of dt_formats and will therefore not be leaked.
2396ff6d951SJohn Birrell 	 */
2406ff6d951SJohn Birrell 	free(enabled);
2416ff6d951SJohn Birrell 	free(probe);
2426ff6d951SJohn Birrell 	return (rval);
2436ff6d951SJohn Birrell }
2446ff6d951SJohn Birrell 
2456ff6d951SJohn Birrell int
2466ff6d951SJohn Birrell dt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid,
2476ff6d951SJohn Birrell     dtrace_eprobedesc_t **epdp, dtrace_probedesc_t **pdp)
2486ff6d951SJohn Birrell {
2496ff6d951SJohn Birrell 	int rval;
2506ff6d951SJohn Birrell 
2516ff6d951SJohn Birrell 	if (epid >= dtp->dt_maxprobe || dtp->dt_pdesc[epid] == NULL) {
2526ff6d951SJohn Birrell 		if ((rval = dt_epid_add(dtp, epid)) != 0)
2536ff6d951SJohn Birrell 			return (rval);
2546ff6d951SJohn Birrell 	}
2556ff6d951SJohn Birrell 
2566ff6d951SJohn Birrell 	assert(epid < dtp->dt_maxprobe);
2576ff6d951SJohn Birrell 	assert(dtp->dt_edesc[epid] != NULL);
2586ff6d951SJohn Birrell 	assert(dtp->dt_pdesc[epid] != NULL);
2596ff6d951SJohn Birrell 	*epdp = dtp->dt_edesc[epid];
2606ff6d951SJohn Birrell 	*pdp = dtp->dt_pdesc[epid];
2616ff6d951SJohn Birrell 
2626ff6d951SJohn Birrell 	return (0);
2636ff6d951SJohn Birrell }
2646ff6d951SJohn Birrell 
2656ff6d951SJohn Birrell void
2666ff6d951SJohn Birrell dt_epid_destroy(dtrace_hdl_t *dtp)
2676ff6d951SJohn Birrell {
2686ff6d951SJohn Birrell 	size_t i;
2696ff6d951SJohn Birrell 
2706ff6d951SJohn Birrell 	assert((dtp->dt_pdesc != NULL && dtp->dt_edesc != NULL &&
2716ff6d951SJohn Birrell 	    dtp->dt_maxprobe > 0) || (dtp->dt_pdesc == NULL &&
2726ff6d951SJohn Birrell 	    dtp->dt_edesc == NULL && dtp->dt_maxprobe == 0));
2736ff6d951SJohn Birrell 
2746ff6d951SJohn Birrell 	if (dtp->dt_pdesc == NULL)
2756ff6d951SJohn Birrell 		return;
2766ff6d951SJohn Birrell 
2776ff6d951SJohn Birrell 	for (i = 0; i < dtp->dt_maxprobe; i++) {
2786ff6d951SJohn Birrell 		if (dtp->dt_edesc[i] == NULL) {
2796ff6d951SJohn Birrell 			assert(dtp->dt_pdesc[i] == NULL);
2806ff6d951SJohn Birrell 			continue;
2816ff6d951SJohn Birrell 		}
2826ff6d951SJohn Birrell 
2836ff6d951SJohn Birrell 		assert(dtp->dt_pdesc[i] != NULL);
2846ff6d951SJohn Birrell 		free(dtp->dt_edesc[i]);
2856ff6d951SJohn Birrell 		free(dtp->dt_pdesc[i]);
2866ff6d951SJohn Birrell 	}
2876ff6d951SJohn Birrell 
2886ff6d951SJohn Birrell 	free(dtp->dt_pdesc);
2896ff6d951SJohn Birrell 	dtp->dt_pdesc = NULL;
2906ff6d951SJohn Birrell 
2916ff6d951SJohn Birrell 	free(dtp->dt_edesc);
2926ff6d951SJohn Birrell 	dtp->dt_edesc = NULL;
2936ff6d951SJohn Birrell 	dtp->dt_maxprobe = 0;
2946ff6d951SJohn Birrell }
2956ff6d951SJohn Birrell 
2966ff6d951SJohn Birrell void *
2976ff6d951SJohn Birrell dt_format_lookup(dtrace_hdl_t *dtp, int format)
2986ff6d951SJohn Birrell {
2996ff6d951SJohn Birrell 	if (format == 0 || format > dtp->dt_maxformat)
3006ff6d951SJohn Birrell 		return (NULL);
3016ff6d951SJohn Birrell 
3026ff6d951SJohn Birrell 	if (dtp->dt_formats == NULL)
3036ff6d951SJohn Birrell 		return (NULL);
3046ff6d951SJohn Birrell 
3056ff6d951SJohn Birrell 	return (dtp->dt_formats[format - 1]);
3066ff6d951SJohn Birrell }
3076ff6d951SJohn Birrell 
3086ff6d951SJohn Birrell void
3096ff6d951SJohn Birrell dt_format_destroy(dtrace_hdl_t *dtp)
3106ff6d951SJohn Birrell {
3116ff6d951SJohn Birrell 	int i;
3126ff6d951SJohn Birrell 
3136ff6d951SJohn Birrell 	for (i = 0; i < dtp->dt_maxformat; i++) {
3146ff6d951SJohn Birrell 		if (dtp->dt_formats[i] != NULL)
3156ff6d951SJohn Birrell 			dt_printf_destroy(dtp->dt_formats[i]);
3166ff6d951SJohn Birrell 	}
3176ff6d951SJohn Birrell 
3186ff6d951SJohn Birrell 	free(dtp->dt_formats);
3196ff6d951SJohn Birrell 	dtp->dt_formats = NULL;
3206ff6d951SJohn Birrell }
3216ff6d951SJohn Birrell 
3226ff6d951SJohn Birrell static int
3236ff6d951SJohn Birrell dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id)
3246ff6d951SJohn Birrell {
3256ff6d951SJohn Birrell 	dtrace_id_t max;
3266ff6d951SJohn Birrell 	dtrace_epid_t epid;
3276ff6d951SJohn Birrell 	int rval;
3286ff6d951SJohn Birrell 
3296ff6d951SJohn Birrell 	while (id >= (max = dtp->dt_maxagg) || dtp->dt_aggdesc == NULL) {
3306ff6d951SJohn Birrell 		dtrace_id_t new_max = max ? (max << 1) : 1;
3316ff6d951SJohn Birrell 		size_t nsize = new_max * sizeof (void *);
3326ff6d951SJohn Birrell 		dtrace_aggdesc_t **new_aggdesc;
3336ff6d951SJohn Birrell 
3346ff6d951SJohn Birrell 		if ((new_aggdesc = malloc(nsize)) == NULL)
3356ff6d951SJohn Birrell 			return (dt_set_errno(dtp, EDT_NOMEM));
3366ff6d951SJohn Birrell 
3376ff6d951SJohn Birrell 		bzero(new_aggdesc, nsize);
3386ff6d951SJohn Birrell 
3396ff6d951SJohn Birrell 		if (dtp->dt_aggdesc != NULL) {
3406ff6d951SJohn Birrell 			bcopy(dtp->dt_aggdesc, new_aggdesc,
3416ff6d951SJohn Birrell 			    max * sizeof (void *));
3426ff6d951SJohn Birrell 			free(dtp->dt_aggdesc);
3436ff6d951SJohn Birrell 		}
3446ff6d951SJohn Birrell 
3456ff6d951SJohn Birrell 		dtp->dt_aggdesc = new_aggdesc;
3466ff6d951SJohn Birrell 		dtp->dt_maxagg = new_max;
3476ff6d951SJohn Birrell 	}
3486ff6d951SJohn Birrell 
3496ff6d951SJohn Birrell 	if (dtp->dt_aggdesc[id] == NULL) {
3506ff6d951SJohn Birrell 		dtrace_aggdesc_t *agg, *nagg;
3516ff6d951SJohn Birrell 
3526ff6d951SJohn Birrell 		if ((agg = malloc(sizeof (dtrace_aggdesc_t))) == NULL)
3536ff6d951SJohn Birrell 			return (dt_set_errno(dtp, EDT_NOMEM));
3546ff6d951SJohn Birrell 
3556ff6d951SJohn Birrell 		bzero(agg, sizeof (dtrace_aggdesc_t));
3566ff6d951SJohn Birrell 		agg->dtagd_id = id;
3576ff6d951SJohn Birrell 		agg->dtagd_nrecs = 1;
3586ff6d951SJohn Birrell 
359*bc96366cSSteven Hartland #ifdef illumos
3606ff6d951SJohn Birrell 		if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg) == -1) {
361cd14ec81SJohn Birrell #else
362cd14ec81SJohn Birrell 		if (dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg) == -1) {
363cd14ec81SJohn Birrell #endif
3646ff6d951SJohn Birrell 			rval = dt_set_errno(dtp, errno);
3656ff6d951SJohn Birrell 			free(agg);
3666ff6d951SJohn Birrell 			return (rval);
3676ff6d951SJohn Birrell 		}
3686ff6d951SJohn Birrell 
3696ff6d951SJohn Birrell 		if (DTRACE_SIZEOF_AGGDESC(agg) != sizeof (*agg)) {
3706ff6d951SJohn Birrell 			/*
3716ff6d951SJohn Birrell 			 * There must be more than one action.  Allocate the
3726ff6d951SJohn Birrell 			 * appropriate amount of space and try again.
3736ff6d951SJohn Birrell 			 */
3746ff6d951SJohn Birrell 			if ((nagg = malloc(DTRACE_SIZEOF_AGGDESC(agg))) != NULL)
3756ff6d951SJohn Birrell 				bcopy(agg, nagg, sizeof (*agg));
3766ff6d951SJohn Birrell 
3776ff6d951SJohn Birrell 			free(agg);
3786ff6d951SJohn Birrell 
3796ff6d951SJohn Birrell 			if ((agg = nagg) == NULL)
3806ff6d951SJohn Birrell 				return (dt_set_errno(dtp, EDT_NOMEM));
3816ff6d951SJohn Birrell 
382*bc96366cSSteven Hartland #ifdef illumos
3836ff6d951SJohn Birrell 			rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, agg);
384cd14ec81SJohn Birrell #else
385cd14ec81SJohn Birrell 			rval = dt_ioctl(dtp, DTRACEIOC_AGGDESC, &agg);
386cd14ec81SJohn Birrell #endif
3876ff6d951SJohn Birrell 
3886ff6d951SJohn Birrell 			if (rval == -1) {
3896ff6d951SJohn Birrell 				rval = dt_set_errno(dtp, errno);
3906ff6d951SJohn Birrell 				free(agg);
3916ff6d951SJohn Birrell 				return (rval);
3926ff6d951SJohn Birrell 			}
3936ff6d951SJohn Birrell 		}
3946ff6d951SJohn Birrell 
3956ff6d951SJohn Birrell 		/*
3966ff6d951SJohn Birrell 		 * If we have a uarg, it's a pointer to the compiler-generated
3976ff6d951SJohn Birrell 		 * statement; we'll use this value to get the name and
3986ff6d951SJohn Birrell 		 * compiler-generated variable ID for the aggregation.  If
3996ff6d951SJohn Birrell 		 * we're grabbing an anonymous enabling, this pointer value
4006ff6d951SJohn Birrell 		 * is obviously meaningless -- and in this case, we can't
4016ff6d951SJohn Birrell 		 * provide the compiler-generated aggregation information.
4026ff6d951SJohn Birrell 		 */
4036ff6d951SJohn Birrell 		if (dtp->dt_options[DTRACEOPT_GRABANON] == DTRACEOPT_UNSET &&
404cd14ec81SJohn Birrell 		    agg->dtagd_rec[0].dtrd_uarg != 0) {
4056ff6d951SJohn Birrell 			dtrace_stmtdesc_t *sdp;
4066ff6d951SJohn Birrell 			dt_ident_t *aid;
4076ff6d951SJohn Birrell 
4086ff6d951SJohn Birrell 			sdp = (dtrace_stmtdesc_t *)(uintptr_t)
4096ff6d951SJohn Birrell 			    agg->dtagd_rec[0].dtrd_uarg;
4106ff6d951SJohn Birrell 			aid = sdp->dtsd_aggdata;
4116ff6d951SJohn Birrell 			agg->dtagd_name = aid->di_name;
4126ff6d951SJohn Birrell 			agg->dtagd_varid = aid->di_id;
4136ff6d951SJohn Birrell 		} else {
4146ff6d951SJohn Birrell 			agg->dtagd_varid = DTRACE_AGGVARIDNONE;
4156ff6d951SJohn Birrell 		}
4166ff6d951SJohn Birrell 
4176ff6d951SJohn Birrell 		if ((epid = agg->dtagd_epid) >= dtp->dt_maxprobe ||
4186ff6d951SJohn Birrell 		    dtp->dt_pdesc[epid] == NULL) {
4196ff6d951SJohn Birrell 			if ((rval = dt_epid_add(dtp, epid)) != 0) {
4206ff6d951SJohn Birrell 				free(agg);
4216ff6d951SJohn Birrell 				return (rval);
4226ff6d951SJohn Birrell 			}
4236ff6d951SJohn Birrell 		}
4246ff6d951SJohn Birrell 
4256ff6d951SJohn Birrell 		dtp->dt_aggdesc[id] = agg;
4266ff6d951SJohn Birrell 	}
4276ff6d951SJohn Birrell 
4286ff6d951SJohn Birrell 	return (0);
4296ff6d951SJohn Birrell }
4306ff6d951SJohn Birrell 
4316ff6d951SJohn Birrell int
4326ff6d951SJohn Birrell dt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid,
4336ff6d951SJohn Birrell     dtrace_aggdesc_t **adp)
4346ff6d951SJohn Birrell {
4356ff6d951SJohn Birrell 	int rval;
4366ff6d951SJohn Birrell 
4376ff6d951SJohn Birrell 	if (aggid >= dtp->dt_maxagg || dtp->dt_aggdesc[aggid] == NULL) {
4386ff6d951SJohn Birrell 		if ((rval = dt_aggid_add(dtp, aggid)) != 0)
4396ff6d951SJohn Birrell 			return (rval);
4406ff6d951SJohn Birrell 	}
4416ff6d951SJohn Birrell 
4426ff6d951SJohn Birrell 	assert(aggid < dtp->dt_maxagg);
4436ff6d951SJohn Birrell 	assert(dtp->dt_aggdesc[aggid] != NULL);
4446ff6d951SJohn Birrell 	*adp = dtp->dt_aggdesc[aggid];
4456ff6d951SJohn Birrell 
4466ff6d951SJohn Birrell 	return (0);
4476ff6d951SJohn Birrell }
4486ff6d951SJohn Birrell 
4496ff6d951SJohn Birrell void
4506ff6d951SJohn Birrell dt_aggid_destroy(dtrace_hdl_t *dtp)
4516ff6d951SJohn Birrell {
4526ff6d951SJohn Birrell 	size_t i;
4536ff6d951SJohn Birrell 
4546ff6d951SJohn Birrell 	assert((dtp->dt_aggdesc != NULL && dtp->dt_maxagg != 0) ||
4556ff6d951SJohn Birrell 	    (dtp->dt_aggdesc == NULL && dtp->dt_maxagg == 0));
4566ff6d951SJohn Birrell 
4576ff6d951SJohn Birrell 	if (dtp->dt_aggdesc == NULL)
4586ff6d951SJohn Birrell 		return;
4596ff6d951SJohn Birrell 
4606ff6d951SJohn Birrell 	for (i = 0; i < dtp->dt_maxagg; i++) {
4616ff6d951SJohn Birrell 		if (dtp->dt_aggdesc[i] != NULL)
4626ff6d951SJohn Birrell 			free(dtp->dt_aggdesc[i]);
4636ff6d951SJohn Birrell 	}
4646ff6d951SJohn Birrell 
4656ff6d951SJohn Birrell 	free(dtp->dt_aggdesc);
4666ff6d951SJohn Birrell 	dtp->dt_aggdesc = NULL;
4676ff6d951SJohn Birrell 	dtp->dt_maxagg = 0;
4686ff6d951SJohn Birrell }
46954727873SPedro F. Giffuni 
47054727873SPedro F. Giffuni const char *
47154727873SPedro F. Giffuni dt_strdata_lookup(dtrace_hdl_t *dtp, int idx)
47254727873SPedro F. Giffuni {
47354727873SPedro F. Giffuni 	if (idx == 0 || idx > dtp->dt_maxstrdata)
47454727873SPedro F. Giffuni 		return (NULL);
47554727873SPedro F. Giffuni 
47654727873SPedro F. Giffuni 	if (dtp->dt_strdata == NULL)
47754727873SPedro F. Giffuni 		return (NULL);
47854727873SPedro F. Giffuni 
47954727873SPedro F. Giffuni 	return (dtp->dt_strdata[idx - 1]);
48054727873SPedro F. Giffuni }
48154727873SPedro F. Giffuni 
48254727873SPedro F. Giffuni void
48354727873SPedro F. Giffuni dt_strdata_destroy(dtrace_hdl_t *dtp)
48454727873SPedro F. Giffuni {
48554727873SPedro F. Giffuni 	int i;
48654727873SPedro F. Giffuni 
48754727873SPedro F. Giffuni 	for (i = 0; i < dtp->dt_maxstrdata; i++) {
48854727873SPedro F. Giffuni 		free(dtp->dt_strdata[i]);
48954727873SPedro F. Giffuni 	}
49054727873SPedro F. Giffuni 
49154727873SPedro F. Giffuni 	free(dtp->dt_strdata);
49254727873SPedro F. Giffuni 	dtp->dt_strdata = NULL;
49354727873SPedro F. Giffuni }
494