[DTrace-devel] [PATCH] Change the dtrace_eprobedesc_t structure to match the new design

Kris Van Hees kris.van.hees at oracle.com
Thu Mar 26 09:07:27 PDT 2020


In DTrace v1, the dtrace_eprobedesc_t structure was used to obtain
metadata information about the probe data stream from the kernel.
Each EPID was also associated with a speciifc dtrace_probedesc_t,
identifying the probe for which the EPID represents an enabling.
Each EPID identified a unique dtrace_eprobedesc_t while the
dtrace_probedesc_t could be shared between multiple EPIDs.

    EPID -[1-to-1]-> dtrace_eprobedesc_t
    EPID -[n-to-1]-> dtrace_probedesc_t

In the DTrace v2 design, where everything resides in userspace, we
can create that metadata directly.  We can also make use of the fact
that when a single program is attached to multiple probes, we do not
need more than one copy of the metadata.  We also make use of the fact
that the EPID identifies a unique (probe, program) tuple.

    EPID -[n-to-1]-> dtrace_datadesc_t
    EPID -[n-to-1]-> dtrace_probedesc_t

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 include/dtrace/metadesc.h |  39 +++---
 libdtrace/dt_aggregate.c  |  10 +-
 libdtrace/dt_bpf.c        |  14 +--
 libdtrace/dt_cc.c         |   5 +
 libdtrace/dt_cg.c         |   3 +
 libdtrace/dt_consume.c    |  51 ++++----
 libdtrace/dt_handle.c     |  26 ++--
 libdtrace/dt_impl.h       |  13 +-
 libdtrace/dt_map.c        | 245 +++++++++++++++++++++++++-------------
 libdtrace/dt_pcb.h        |   2 +
 libdtrace/dt_program.c    |  18 ++-
 libdtrace/dtrace.h        |   8 +-
 12 files changed, 265 insertions(+), 169 deletions(-)

diff --git a/include/dtrace/metadesc.h b/include/dtrace/metadesc.h
index 7d800e97..10c6c2a5 100644
--- a/include/dtrace/metadesc.h
+++ b/include/dtrace/metadesc.h
@@ -21,16 +21,16 @@
  * DTrace separates the trace data stream from the metadata stream.  The only
  * metadata tokens placed in the data stream are enabled probe identifiers
  * (EPIDs) or (in the case of aggregations) aggregation identifiers.  In order
- * to determine the structure of the data, DTrace consumers pass the token to
- * the kernel, and receive in return a corresponding description of the enabled
- * probe (via the dtrace_eprobedesc structure) or the aggregation (via the
- * dtrace_aggdesc structure).  Both of these structures are expressed in terms
- * of record descriptions (via the dtrace_recdesc structure) that describe the
- * exact structure of the data.  Some record descriptions may also contain a
- * format identifier; this additional bit of metadata can be retrieved from the
- * kernel, for which a format description is returned via the dtrace_fmtdesc
- * structure.  Note that all four of these structures must be bitness-neutral
- * to allow for a 32-bit DTrace consumer on a 64-bit kernel.
+ * to determine the structure of the data, DTrace uses the token to perform a
+ * lookup to retrieve the corresponding description of the enabled probe (via
+ * the dtrace_datadesc structure) or the aggregation (via the dtrace_aggdesc
+ * structure).
+ *
+ * Both of these structures are expressed in terms of record descriptions (via
+ * the dtrace_recdesc structure) that describe the exact structure of the data.
+ * Some record descriptions may also contain a format identifier; this
+ * additional bit of metadata refers to a format description described via a
+ * dtrace_fmtdesc structure.
  */
 typedef struct dtrace_recdesc {
 	dtrace_actkind_t dtrd_action;		/* kind of action */
@@ -42,14 +42,13 @@ typedef struct dtrace_recdesc {
 	uint64_t dtrd_uarg;			/* user argument */
 } dtrace_recdesc_t;
 
-typedef struct dtrace_eprobedesc {
-	dtrace_epid_t dtepd_epid;		/* enabled probe ID */
-	dtrace_id_t dtepd_probeid;		/* probe ID */
-	uint64_t dtepd_uarg;			/* library argument */
-	uint32_t dtepd_size;			/* total size */
-	int dtepd_nrecs;			/* number of records */
-	dtrace_recdesc_t dtepd_rec[1];		/* recods themselves */
-} dtrace_eprobedesc_t;
+typedef struct dtrace_datadesc {
+	uint64_t dtdd_uarg;			/* library argument */
+	uint32_t dtdd_size;			/* total size */
+	int dtdd_nrecs;				/* number of records */
+	dtrace_recdesc_t *dtdd_recs;		/* records themselves */
+	int dtdd_refcnt;			/* reference count */
+} dtrace_datadesc_t;
 
 typedef struct dtrace_aggdesc {
 	DTRACE_PTR(char, dtagd_name);		/* not filled in by kernel */
@@ -70,8 +69,8 @@ typedef struct dtrace_fmtdesc {
 } dtrace_fmtdesc_t;
 
 #define DTRACE_SIZEOF_EPROBEDESC(desc)				\
-	(sizeof (dtrace_eprobedesc_t) + ((desc)->dtepd_nrecs ?  \
-	(((desc)->dtepd_nrecs - 1) * sizeof (dtrace_recdesc_t)) : 0))
+	(sizeof (dtrace_eprobedesc_t) + ((desc)->dtdd_nrecs ?  \
+	(((desc)->dtdd_nrecs - 1) * sizeof (dtrace_recdesc_t)) : 0))
 
 #define	DTRACE_SIZEOF_AGGDESC(desc)			       \
 	(sizeof (dtrace_aggdesc_t) + ((desc)->dtagd_nrecs ?     \
diff --git a/libdtrace/dt_aggregate.c b/libdtrace/dt_aggregate.c
index b545cb32..908dc6d2 100644
--- a/libdtrace/dt_aggregate.c
+++ b/libdtrace/dt_aggregate.c
@@ -644,8 +644,8 @@ hashnext:
 		aggdata->dtada_size = size;
 		aggdata->dtada_desc = agg;
 		aggdata->dtada_handle = dtp;
-		(void) dt_epid_lookup(dtp, agg->dtagd_epid,
-		    &aggdata->dtada_edesc, &aggdata->dtada_pdesc);
+		dt_epid_lookup(dtp, agg->dtagd_epid, &aggdata->dtada_ddesc,
+			       &aggdata->dtada_pdesc);
 		aggdata->dtada_normal = 1;
 
 		h->dtahe_hashval = hashval;
@@ -1631,9 +1631,9 @@ dtrace_aggregate_walk_joined(dtrace_hdl_t *dtp, dtrace_aggvarid_t *aggvars,
 				aggdata->dtada_size = agg->dtagd_size;
 				aggdata->dtada_desc = agg;
 				aggdata->dtada_handle = dtp;
-				(void) dt_epid_lookup(dtp, agg->dtagd_epid,
-				    &aggdata->dtada_edesc,
-				    &aggdata->dtada_pdesc);
+				dt_epid_lookup(dtp, agg->dtagd_epid,
+					       &aggdata->dtada_ddesc,
+					       &aggdata->dtada_pdesc);
 				aggdata->dtada_normal = 1;
 				zaggdata[i].dtahe_hashval = 0;
 				zaggdata[i].dtahe_size = agg->dtagd_size;
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index cacfa07a..2c90411b 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -249,15 +249,16 @@ dt_bpf_reloc_prog(dtrace_hdl_t *dtp, const dt_probe_t *prp,
  */
 int
 dt_bpf_load_prog(dtrace_hdl_t *dtp, const dt_probe_t *prp,
-		 const dtrace_difo_t *dp)
+		 dtrace_stmtdesc_t *sdp)
 {
 	struct bpf_load_program_attr	attr;
 	dtrace_epid_t			epid;
+	const dtrace_difo_t		*dp = sdp->dtsd_action->dtad_difo;
 	int				logsz = BPF_LOG_BUF_SIZE;
 	char				*log;
 	int				rc;
 
-	epid = dt_epid_add(dtp, prp->desc->id, 0);
+	epid = dt_epid_add(dtp, sdp->dtsd_ddesc, prp->desc->id);
 
 	/*
 	 * Check whether there are any probe-specific relocations to be
@@ -360,14 +361,7 @@ dt_bpf_stmt(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp,
 	if (!prp)
 		return dt_set_errno(dtp, ESRCH);
 
-	/*
-	 * In the new implementation, every statement has a single action,
-	 * which is the entire program.  At a future code reworking, we should
-	 * combine the action into the statement and do away with the action
-	 * list.
-	 */
-	assert(ap == sdp->dtsd_action_last);
-	fd = dt_bpf_load_prog(dtp, prp, ap->dtad_difo);
+	fd = dt_bpf_load_prog(dtp, prp, sdp);
 	if (fd < 0)
 		return fd;
 
diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
index cc299b93..ab987fc7 100644
--- a/libdtrace/dt_cc.c
+++ b/libdtrace/dt_cc.c
@@ -259,6 +259,11 @@ dt_stmt_append(dtrace_stmtdesc_t *sdp, const dt_node_t *dnp)
 			datarec = 1;
 	}
 
+	/*
+	 * Finalize the probe data description for the statement.
+	 */
+	dt_datadesc_finalize(yypcb->pcb_hdl, sdp->dtsd_ddesc);
+
 	if (dtrace_stmt_add(yypcb->pcb_hdl, yypcb->pcb_prog, sdp) != 0)
 		longjmp(yypcb->pcb_jmpbuf, dtrace_errno(yypcb->pcb_hdl));
 
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 4945dead..17074661 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -490,6 +490,9 @@ dt_cg_act_trace(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
 		dt_regset_free(pcb->pcb_regs, dnp->dn_args->dn_reg);
 
+		dt_rec_add(pcb->pcb_hdl, DT_ACT_TRACE, sizeof(uint64_t), off,
+			   sizeof(uint64_t), NULL, 0); 
+
 		return sizeof(uint64_t);
 	} else if (dt_node_is_string(dnp->dn_args)) {
 		size_t sz = dt_node_type_size(dnp->dn_args);
diff --git a/libdtrace/dt_consume.c b/libdtrace/dt_consume.c
index 62e8e9cb..57a7b0b9 100644
--- a/libdtrace/dt_consume.c
+++ b/libdtrace/dt_consume.c
@@ -366,7 +366,7 @@ dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last,
     dtrace_bufdesc_t *buf, size_t offs)
 {
 	dtrace_probedesc_t *pd = data->dtpda_pdesc, *npd;
-	dtrace_eprobedesc_t *epd = data->dtpda_edesc, *nepd;
+	dtrace_datadesc_t *dd = data->dtpda_ddesc, *ndd;
 	dtrace_flowkind_t flow = DTRACEFLOW_NONE;
 	const char *p = pd->prv;
 	const char *n = pd->prb;
@@ -376,7 +376,7 @@ dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last,
 	static const char *r_str[2] = { " <- ", " <= " };
 	static const char *ent = "entry", *ret = "return";
 	static int entlen = 0, retlen = 0;
-	dtrace_epid_t next, id = epd->dtepd_epid;
+	dtrace_epid_t next, id = data->dtpda_epid;
 	int rval;
 
 	if (entlen == 0) {
@@ -421,7 +421,7 @@ dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last,
 	 * _next_ EPID.
 	 */
 	if (flow == DTRACEFLOW_RETURN) {
-		offs += epd->dtepd_size;
+		offs += dd->dtdd_size;
 
 		do {
 			if (offs >= buf->dtbd_size) {
@@ -442,7 +442,7 @@ dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last,
 				offs += sizeof (id);
 		} while (next == DTRACE_EPIDNONE);
 
-		if ((rval = dt_epid_lookup(dtp, next, &nepd, &npd)) != 0)
+		if ((rval = dt_epid_lookup(dtp, next, &ndd, &npd)) != 0)
 			return (rval);
 
 		if (next != id && npd->id == pd->id)
@@ -1867,7 +1867,7 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf,
 
 again:
 	for (offs = start; offs < end; ) {
-		dtrace_eprobedesc_t *epd;
+		dtrace_datadesc_t *dd;
 
 		/*
 		 * We're guaranteed to have an ID.
@@ -1883,14 +1883,14 @@ again:
 			continue;
 		}
 
-		if ((rval = dt_epid_lookup(dtp, id, &data.dtpda_edesc,
-		    &data.dtpda_pdesc)) != 0)
+		if ((rval = dt_epid_lookup(dtp, id, &data.dtpda_ddesc,
+					   &data.dtpda_pdesc)) != 0)
 			return (rval);
 
-		epd = data.dtpda_edesc;
+		dd = data.dtpda_ddesc;
 		data.dtpda_data = buf->dtbd_data + offs;
 
-		if (data.dtpda_edesc->dtepd_uarg != DT_ECB_DEFAULT) {
+		if (data.dtpda_ddesc->dtdd_uarg != DT_ECB_DEFAULT) {
 			rval = dt_handle(dtp, &data);
 
 			if (rval == DTRACE_CONSUME_NEXT)
@@ -1919,8 +1919,8 @@ again:
 		if (rval != DTRACE_CONSUME_THIS)
 			return (dt_set_errno(dtp, EDT_BADRVAL));
 
-		for (i = 0; i < epd->dtepd_nrecs; i++) {
-			dtrace_recdesc_t *rec = &epd->dtepd_rec[i];
+		for (i = 0; i < dd->dtdd_nrecs; i++) {
+			dtrace_recdesc_t *rec = &dd->dtdd_recs[i];
 			dtrace_actkind_t act = rec->dtrd_action;
 
 			data.dtpda_data = buf->dtbd_data + offs +
@@ -1956,7 +1956,7 @@ again:
 					continue;
 
 				case DT_ACT_NORMALIZE:
-					if (i == epd->dtepd_nrecs - 1)
+					if (i == dd->dtdd_nrecs - 1)
 						return (dt_set_errno(dtp,
 						    EDT_BADNORMAL));
 
@@ -1974,12 +1974,12 @@ again:
 					caddr_t val;
 					int rv;
 
-					if (i == epd->dtepd_nrecs - 1) {
+					if (i == dd->dtdd_nrecs - 1) {
 						return (dt_set_errno(dtp,
 						    EDT_BADSETOPT));
 					}
 
-					valrec = &epd->dtepd_rec[++i];
+					valrec = &dd->dtdd_recs[++i];
 					valsize = valrec->dtrd_size;
 
 					if (valrec->dtrd_action != act ||
@@ -2009,7 +2009,7 @@ again:
 				}
 
 				case DT_ACT_TRUNC:
-					if (i == epd->dtepd_nrecs - 1)
+					if (i == dd->dtdd_nrecs - 1)
 						return (dt_set_errno(dtp,
 						    EDT_BADTRUNC));
 
@@ -2109,7 +2109,7 @@ again:
 				}
 
 				n = (*func)(dtp, fp, fmtdata, &data,
-				    rec, epd->dtepd_nrecs - i,
+				    rec, dd->dtdd_nrecs - i,
 				    (uchar_t *)buf->dtbd_data + offs,
 				    buf->dtbd_size - offs);
 
@@ -2126,7 +2126,7 @@ nofmt:
 				dtrace_print_aggdata_t pd;
 				dtrace_aggvarid_t *aggvars;
 				int j, naggvars = 0;
-				size_t size = ((epd->dtepd_nrecs - i) *
+				size_t size = ((dd->dtdd_nrecs - i) *
 				    sizeof (dtrace_aggvarid_t));
 
 				if ((aggvars = dt_alloc(dtp, size)) == NULL)
@@ -2138,11 +2138,11 @@ nofmt:
 				 * forward through the records until we find
 				 * a record from a different statement.
 				 */
-				for (j = i; j < epd->dtepd_nrecs; j++) {
+				for (j = i; j < dd->dtdd_nrecs; j++) {
 					dtrace_recdesc_t *nrec;
 					caddr_t naddr;
 
-					nrec = &epd->dtepd_rec[j];
+					nrec = &dd->dtdd_recs[j];
 
 					if (nrec->dtrd_uarg != rec->dtrd_uarg)
 						break;
@@ -2191,7 +2191,7 @@ nofmt:
 
 			if (act == DTRACEACT_TRACEMEM) {
 				n = dt_print_tracemem(dtp, fp, rec,
-				    epd->dtepd_nrecs - i,
+				    dd->dtdd_nrecs - i,
 				    buf->dtbd_data + offs);
 
 				if (n < 0)
@@ -2253,7 +2253,7 @@ nextrec:
 		 */
 		rval = (*rfunc)(&data, NULL, arg);
 nextepid:
-		offs += epd->dtepd_size;
+		offs += dd->dtdd_size;
 		last = id;
 	}
 
@@ -2293,7 +2293,7 @@ dt_consume_one(dtrace_hdl_t *dtp, FILE *fp, int cpu, char *buf,
 	if (hdr->type == PERF_RECORD_SAMPLE) {
 		char			*ptr = data;
 		uint32_t		size, epid, tag;
-		int			i, nrecs;
+		int			i;
 		dtrace_probedata_t	pdat;
 
 		/*
@@ -2331,7 +2331,7 @@ dt_consume_one(dtrace_hdl_t *dtp, FILE *fp, int cpu, char *buf,
 		memset(&pdat, 0, sizeof(pdat));
 		pdat.dtpda_handle = dtp;
 		pdat.dtpda_cpu = cpu;
-		rval = dt_epid_lookup(dtp, epid, &pdat.dtpda_edesc,
+		rval = dt_epid_lookup(dtp, epid, &pdat.dtpda_ddesc,
 						 &pdat.dtpda_pdesc);
 		if (rval != 0)
 			return (rval);
@@ -2362,12 +2362,11 @@ dt_consume_one(dtrace_hdl_t *dtp, FILE *fp, int cpu, char *buf,
 		/*
 		 * FIXME: This code is temporary.
 		 */
-		nrecs = size / sizeof(uint64_t);
-		for (i = 0; i < nrecs; i++) {
+		for (i = 0; i < pdat.dtpda_ddesc->dtdd_nrecs; i++) {
 			int	n;
 
 			n = dt_printf(dtp, fp, quiet ? "%lld" : " %16lld",
-				      *(uint64_t *)data);
+				      *(int64_t *)data);
 			data += sizeof(uint64_t);
 			size -= sizeof(uint64_t);
 
diff --git a/libdtrace/dt_handle.c b/libdtrace/dt_handle.c
index ead5e198..d567a265 100644
--- a/libdtrace/dt_handle.c
+++ b/libdtrace/dt_handle.c
@@ -126,12 +126,12 @@ dtrace_handle_setopt(dtrace_hdl_t *dtp, dtrace_handle_setopt_f *hdlr,
 }
 
 #define	DT_REC(type, ndx) *((type *)((uintptr_t)data->dtpda_data + \
-    epd->dtepd_rec[(ndx)].dtrd_offset))
+    dd->dtdd_recs[(ndx)].dtrd_offset))
 
 static int
 dt_handle_err(dtrace_hdl_t *dtp, dtrace_probedata_t *data)
 {
-	dtrace_eprobedesc_t *epd = data->dtpda_edesc, *errepd;
+	dtrace_datadesc_t *dd = data->dtpda_ddesc, *errdd;
 	dtrace_probedesc_t *pd = data->dtpda_pdesc, *errpd;
 	dtrace_errdata_t err;
 	dtrace_epid_t epid;
@@ -144,9 +144,9 @@ dt_handle_err(dtrace_hdl_t *dtp, dtrace_probedata_t *data)
 	char *str;
 	int len;
 
-	assert(epd->dtepd_uarg == DT_ECB_ERROR);
+	assert(dd->dtdd_uarg == DT_ECB_ERROR);
 
-	if (epd->dtepd_nrecs != 5 || strcmp(pd->prv, "dtrace") != 0 ||
+	if (dd->dtdd_nrecs != 5 || strcmp(pd->prv, "dtrace") != 0 ||
 	    strcmp(pd->prb, "ERROR") != 0)
 		return (dt_set_errno(dtp, EDT_BADERROR));
 
@@ -156,10 +156,10 @@ dt_handle_err(dtrace_hdl_t *dtp, dtrace_probedata_t *data)
 	 */
 	epid = (uint32_t)DT_REC(uint64_t, 0);
 
-	if (dt_epid_lookup(dtp, epid, &errepd, &errpd) != 0)
+	if (dt_epid_lookup(dtp, epid, &errdd, &errpd) != 0)
 		return (dt_set_errno(dtp, EDT_BADERROR));
 
-	err.dteda_edesc = errepd;
+	err.dteda_ddesc = errdd;
 	err.dteda_pdesc = errpd;
 	err.dteda_cpu = data->dtpda_cpu;
 	err.dteda_action = (int)DT_REC(uint64_t, 1);
@@ -225,7 +225,7 @@ dt_handle_liberr(dtrace_hdl_t *dtp, const dtrace_probedata_t *data,
 	char *str;
 	int len;
 
-	err.dteda_edesc = data->dtpda_edesc;
+	err.dteda_ddesc = data->dtpda_ddesc;
 	err.dteda_pdesc = errpd;
 	err.dteda_cpu = data->dtpda_cpu;
 	err.dteda_action = -1;
@@ -238,10 +238,10 @@ dt_handle_liberr(dtrace_hdl_t *dtp, const dtrace_probedata_t *data,
 
 	str = alloca(len);
 
-	snprintf(str, len, "error on enabled probe ID %u (ID %u: %s:%s:%s:%s): "
-			   "%s\n",
-		 data->dtpda_edesc->dtepd_epid, errpd->id, errpd->prv,
-		 errpd->mod, errpd->fun, errpd->prb, faultstr);
+	snprintf(str, len,
+		 "error on enabled probe ID %u (ID %u: %s:%s:%s:%s): %s\n",
+		 data->dtpda_epid, errpd->id, errpd->prv, errpd->mod,
+		 errpd->fun, errpd->prb, faultstr);
 
 	err.dteda_msg = str;
 
@@ -443,10 +443,10 @@ dt_handle_setopt(dtrace_hdl_t *dtp, dtrace_setoptdata_t *data)
 int
 dt_handle(dtrace_hdl_t *dtp, dtrace_probedata_t *data)
 {
-	dtrace_eprobedesc_t *epd = data->dtpda_edesc;
+	dtrace_datadesc_t *dd = data->dtpda_ddesc;
 	int rval;
 
-	switch (epd->dtepd_uarg) {
+	switch (dd->dtdd_uarg) {
 	case DT_ECB_ERROR:
 		rval = dt_handle_err(dtp, data);
 		break;
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index c20d30c9..8bb5c003 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -290,7 +290,7 @@ struct dtrace_hdl {
 	ctf_id_t dt_type_usymaddr; /* cached CTF ident. for _usymaddr type */
 	dtrace_epid_t dt_nextepid; /* next enabled probe ID to assign */
 	size_t dt_maxprobe;	/* max enabled probe ID */
-	dtrace_eprobedesc_t **dt_edesc; /* enabled probe descriptions */
+	dtrace_datadesc_t **dt_ddesc; /* probe data descriptions */
 	dtrace_probedesc_t **dt_pdesc; /* probe descriptions for enabled prbs */
 	size_t dt_maxagg;	/* max aggregation ID */
 	dtrace_aggdesc_t **dt_aggdesc; /* aggregation descriptions */
@@ -709,10 +709,15 @@ extern int dt_aggregate_go(dtrace_hdl_t *);
 extern int dt_aggregate_init(dtrace_hdl_t *);
 extern void dt_aggregate_destroy(dtrace_hdl_t *);
 
-extern dtrace_epid_t dt_epid_add(dtrace_hdl_t *, dtrace_id_t, int);
-extern int dt_epid_lookup(dtrace_hdl_t *, dtrace_epid_t,
-    dtrace_eprobedesc_t **, dtrace_probedesc_t **);
+extern dtrace_datadesc_t *dt_datadesc_create(dtrace_hdl_t *);
+extern int dt_datadesc_finalize(dtrace_hdl_t *, dtrace_datadesc_t *);
+extern dtrace_epid_t dt_epid_add(dtrace_hdl_t *, dtrace_datadesc_t *,
+				 dtrace_id_t);
+extern int dt_epid_lookup(dtrace_hdl_t *, dtrace_epid_t, dtrace_datadesc_t **,
+			  dtrace_probedesc_t **);
 extern void dt_epid_destroy(dtrace_hdl_t *);
+extern int dt_rec_add(dtrace_hdl_t *, dtrace_actkind_t, uint32_t, uint32_t,
+		      uint16_t, const char *, uint64_t);
 extern int dt_aggid_lookup(dtrace_hdl_t *, dtrace_aggid_t, dtrace_aggdesc_t **);
 extern void dt_aggid_destroy(dtrace_hdl_t *);
 
diff --git a/libdtrace/dt_map.c b/libdtrace/dt_map.c
index 48ffa15d..048789f7 100644
--- a/libdtrace/dt_map.c
+++ b/libdtrace/dt_map.c
@@ -11,32 +11,94 @@
 #include <assert.h>
 
 #include <dt_impl.h>
+#include <dt_pcb.h>
 #include <dt_probe.h>
 #include <dt_printf.h>
 
+static void
+dt_datadesc_hold(dtrace_datadesc_t *ddp)
+{
+	ddp->dtdd_refcnt++;
+}
+
+static void
+dt_datadesc_release(dtrace_hdl_t *dtp, dtrace_datadesc_t *ddp)
+{
+	if (--ddp->dtdd_refcnt > 0)
+		return;
+
+	dt_free(dtp, ddp->dtdd_recs);
+	dt_free(dtp, ddp);
+}
+
+dtrace_datadesc_t *
+dt_datadesc_create(dtrace_hdl_t *dtp)
+{
+	dtrace_datadesc_t	*ddp;
+
+	ddp = dt_zalloc(dtp, sizeof(dtrace_datadesc_t));
+	if (ddp == NULL) {
+		dt_set_errno(dtp, EDT_NOMEM);
+		return NULL;
+	}
+
+	dt_datadesc_hold(ddp);
+
+	return ddp;
+}
+
+int
+dt_datadesc_finalize(dtrace_hdl_t *dtp, dtrace_datadesc_t *ddp)
+{
+	dt_pcb_t	*pcb = dtp->dt_pcb;
+
+	/*
+	 * If the number of allocated data records is greater than the actual
+	 * number needed, we create a copy with the right number of records and
+	 * free the oversized one.
+	 */
+	if (pcb->pcb_nrecs < pcb->pcb_maxrecs) {
+		dtrace_recdesc_t	*nrecs;
+
+		nrecs = dt_calloc(dtp, pcb->pcb_nrecs,
+				  sizeof(dtrace_recdesc_t));
+		if (nrecs == NULL)
+			return dt_set_errno(dtp, EDT_NOMEM);
+
+		memcpy(nrecs, ddp->dtdd_recs, pcb->pcb_nrecs);
+		dt_free(dtp, ddp->dtdd_recs);
+		ddp->dtdd_recs = nrecs;
+		pcb->pcb_maxrecs = pcb->pcb_nrecs;
+	}
+
+	ddp->dtdd_nrecs = pcb->pcb_nrecs;
+
+	return 0;
+}
+
 #if 0
 static int
 dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
 {
 	dtrace_id_t max;
 	int rval, i, maxformat;
-	dtrace_eprobedesc_t *enabled, *nenabled;
+	dtrace_datadesc_t *dd, *ndd;
 	dtrace_probedesc_t *probe;
 
 	while (id >= (max = dtp->dt_maxprobe) || dtp->dt_pdesc == NULL) {
 		dtrace_id_t new_max = max ? (max << 1) : 1;
 		size_t nsize = new_max * sizeof (void *);
 		dtrace_probedesc_t **new_pdesc;
-		dtrace_eprobedesc_t **new_edesc;
+		dtrace_datadesc_t **new_ddesc;
 
 		if ((new_pdesc = malloc(nsize)) == NULL ||
-		    (new_edesc = malloc(nsize)) == NULL) {
+		    (new_ddesc = malloc(nsize)) == NULL) {
 			free(new_pdesc);
 			return (dt_set_errno(dtp, EDT_NOMEM));
 		}
 
 		memset(new_pdesc, 0, nsize);
-		memset(new_edesc, 0, nsize);
+		memset(new_ddesc, 0, nsize);
 
 		if (dtp->dt_pdesc != NULL) {
 			size_t osize = max * sizeof (void *);
@@ -44,69 +106,68 @@ dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
 			memcpy(new_pdesc, dtp->dt_pdesc, osize);
 			free(dtp->dt_pdesc);
 
-			memcpy(new_edesc, dtp->dt_edesc, osize);
-			free(dtp->dt_edesc);
+			memcpy(new_ddesc, dtp->dt_ddesc, osize);
+			free(dtp->dt_ddesc);
 		}
 
 		dtp->dt_pdesc = new_pdesc;
-		dtp->dt_edesc = new_edesc;
+		dtp->dt_ddesc = new_ddesc;
 		dtp->dt_maxprobe = new_max;
 	}
 
 	if (dtp->dt_pdesc[id] != NULL)
 		return (0);
 
-	if ((enabled = malloc(sizeof (dtrace_eprobedesc_t))) == NULL)
+	if ((dd = malloc(sizeof (dtrace_datadesc_t))) == NULL)
 		return (dt_set_errno(dtp, EDT_NOMEM));
 
-	memset(enabled, 0, sizeof (dtrace_eprobedesc_t));
-	enabled->dtepd_epid = id;
-	enabled->dtepd_nrecs = 1;
+	memset(dd, 0, sizeof (dtrace_datadesc_t));
+	dd->dtdd_epid = id;
+	dd->dtdd_nrecs = 1;
 
-	if (dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled) == -1) {
+	if (dt_ioctl(dtp, DTRACEIOC_EPROBE, dd) == -1) {
 		rval = dt_set_errno(dtp, errno);
-		free(enabled);
+		free(dd);
 		return (rval);
 	}
 
-	if (DTRACE_SIZEOF_EPROBEDESC(enabled) != sizeof (*enabled)) {
+	if (DTRACE_SIZEOF_EPROBEDESC(dd) != sizeof (*dd)) {
 		/*
 		 * There must be more than one action.  Allocate the
 		 * appropriate amount of space and try again.
 		 */
-		if ((nenabled =
-		    malloc(DTRACE_SIZEOF_EPROBEDESC(enabled))) != NULL)
-			memcpy(nenabled, enabled, sizeof (*enabled));
+		if ((ndd = malloc(DTRACE_SIZEOF_EPROBEDESC(dd))) != NULL)
+			memcpy(ndd, dd, sizeof (*dd));
 
-		free(enabled);
+		free(dd);
 
-		if ((enabled = nenabled) == NULL)
+		if ((dd = ndd) == NULL)
 			return (dt_set_errno(dtp, EDT_NOMEM));
 
-		rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, enabled);
+		rval = dt_ioctl(dtp, DTRACEIOC_EPROBE, dd);
 
 		if (rval == -1) {
 			rval = dt_set_errno(dtp, errno);
-			free(enabled);
+			free(dd);
 			return (rval);
 		}
 	}
 
 	if ((probe = malloc(sizeof (dtrace_probedesc_t))) == NULL) {
-		free(enabled);
+		free(dd);
 		return (dt_set_errno(dtp, EDT_NOMEM));
 	}
 
-	probe->id = enabled->dtepd_probeid;
+	probe->id = dd->dtdd_probeid;
 
 	if (dt_ioctl(dtp, DTRACEIOC_PROBES, probe) == -1) {
 		rval = dt_set_errno(dtp, errno);
 		goto err;
 	}
 
-	for (i = 0; i < enabled->dtepd_nrecs; i++) {
+	for (i = 0; i < dd->dtdd_nrecs; i++) {
 		dtrace_fmtdesc_t fmt;
-		dtrace_recdesc_t *rec = &enabled->dtepd_rec[i];
+		dtrace_recdesc_t *rec = &dd->dtdd_rec[i];
 
 		if (!DTRACEACT_ISPRINTFLIKE(rec->dtrd_action))
 			continue;
@@ -173,7 +234,7 @@ dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
 	}
 
 	dtp->dt_pdesc[id] = probe;
-	dtp->dt_edesc[id] = enabled;
+	dtp->dt_ddesc[id] = dd;
 
 	return (0);
 
@@ -184,70 +245,56 @@ err:
 	 * we have already allocated.  This is okay; these formats are
 	 * hanging off of dt_formats and will therefore not be leaked.
 	 */
-	free(enabled);
+	free(dd);
 	free(probe);
 	return (rval);
 }
 #else
+/*
+ * Associate a probe data description and probe description with an enabled
+ * probe ID.  This means that the given ID refers to the program matching the
+ * probe data description being attached to the probe that matches the probe
+ * description.
+ */
 dtrace_epid_t
-dt_epid_add(dtrace_hdl_t *dtp, dtrace_id_t prid, int nrecs)
+dt_epid_add(dtrace_hdl_t *dtp, dtrace_datadesc_t *ddp, dtrace_id_t prid)
 {
-	dtrace_id_t		max;
+	dtrace_id_t		max = dtp->dt_maxprobe;
 	dtrace_epid_t		epid;
-	dtrace_eprobedesc_t	*eprobe;
 
 	epid = dtp->dt_nextepid++;
-	max = dtp->dt_maxprobe;
-	if (epid >= max || dtp->dt_edesc == NULL) {
+	if (epid >= max || dtp->dt_ddesc == NULL) {
 		dtrace_id_t		nmax = max ? (max << 1) : 2;
-		dtrace_eprobedesc_t	**nedesc;
+		dtrace_datadesc_t	**nddesc;
 		dtrace_probedesc_t	**npdesc;
 
-		nedesc = dt_calloc(dtp, nmax, sizeof(void *));
+		nddesc = dt_calloc(dtp, nmax, sizeof(void *));
 		npdesc = dt_calloc(dtp, nmax, sizeof(void *));
-		if (nedesc == NULL || npdesc == NULL) {
-			dt_free(dtp, nedesc);
+		if (nddesc == NULL || npdesc == NULL) {
+			dt_free(dtp, nddesc);
 			dt_free(dtp, npdesc);
 			return dt_set_errno(dtp, EDT_NOMEM);
 		}
 
-		if (dtp->dt_edesc != NULL) {
+		if (dtp->dt_ddesc != NULL) {
 			size_t	osize = max * sizeof(void *);
 
-			memcpy(nedesc, dtp->dt_edesc, osize);
-			dt_free(dtp, dtp->dt_edesc);
+			memcpy(nddesc, dtp->dt_ddesc, osize);
+			dt_free(dtp, dtp->dt_ddesc);
 			memcpy(npdesc, dtp->dt_pdesc, osize);
 			dt_free(dtp, dtp->dt_pdesc);
 		}
 
-		dtp->dt_edesc = nedesc;
+		dtp->dt_ddesc = nddesc;
 		dtp->dt_pdesc = npdesc;
 		dtp->dt_maxprobe = nmax;
 	}
 
-	if (dtp->dt_edesc[epid] != NULL)
+	if (dtp->dt_ddesc[epid] != NULL)
 		return epid;
 
-	/*
-	 * This is a bit odd, but we want to make sure that nrecs is not a
-	 * negative value while also taking into consideration that there is
-	 * always rooms for one record in dtrace_eprobedesc_t, so for our
-	 * allocation purposes we account for that default record slot.
-	 */
-	assert(nrecs >= 0);
-	if (nrecs == 0)
-		nrecs = 1;
-
-	eprobe = dt_zalloc(dtp, sizeof(dtrace_eprobedesc_t) +
-				(nrecs - 1) * sizeof(dtrace_recdesc_t));
-	if (eprobe == NULL)
-		return dt_set_errno(dtp, EDT_NOMEM);
-
-	eprobe->dtepd_epid = epid;
-	eprobe->dtepd_probeid = prid;
-	eprobe->dtepd_nrecs = nrecs;
-
-	dtp->dt_edesc[epid] = eprobe;
+	dt_datadesc_hold(ddp);
+	dtp->dt_ddesc[epid] = ddp;
 	dtp->dt_pdesc[epid] = (dtrace_probedesc_t *)dtp->dt_probes[prid]->desc;
 
 	return epid;
@@ -255,22 +302,14 @@ dt_epid_add(dtrace_hdl_t *dtp, dtrace_id_t prid, int nrecs)
 #endif
 
 int
-dt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid,
-    dtrace_eprobedesc_t **epdp, dtrace_probedesc_t **pdp)
+dt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid, dtrace_datadesc_t **ddp,
+	       dtrace_probedesc_t **pdp)
 {
-	int rval;
-
-#if 0
-	if (epid >= dtp->dt_maxprobe || dtp->dt_pdesc[epid] == NULL) {
-		if ((rval = dt_epid_add(dtp, epid)) != 0)
-			return (rval);
-	}
-#endif
-
 	assert(epid < dtp->dt_maxprobe);
-	assert(dtp->dt_edesc[epid] != NULL);
+	assert(dtp->dt_ddesc[epid] != NULL);
 	assert(dtp->dt_pdesc[epid] != NULL);
-	*epdp = dtp->dt_edesc[epid];
+
+	*ddp = dtp->dt_ddesc[epid];
 	*pdp = dtp->dt_pdesc[epid];
 
 	return (0);
@@ -281,33 +320,73 @@ dt_epid_destroy(dtrace_hdl_t *dtp)
 {
 	size_t i;
 
-	assert((dtp->dt_pdesc != NULL && dtp->dt_edesc != NULL &&
+	assert((dtp->dt_pdesc != NULL && dtp->dt_ddesc != NULL &&
 	    dtp->dt_maxprobe > 0) || (dtp->dt_pdesc == NULL &&
-	    dtp->dt_edesc == NULL && dtp->dt_maxprobe == 0));
+	    dtp->dt_ddesc == NULL && dtp->dt_maxprobe == 0));
 
 	if (dtp->dt_pdesc == NULL)
 		return;
 
 	for (i = 0; i < dtp->dt_maxprobe; i++) {
-		if (dtp->dt_edesc[i] == NULL) {
+		if (dtp->dt_ddesc[i] == NULL) {
 			assert(dtp->dt_pdesc[i] == NULL);
 			continue;
 		}
 
+		dt_datadesc_release(dtp, dtp->dt_ddesc[i]);
 		assert(dtp->dt_pdesc[i] != NULL);
-		free(dtp->dt_edesc[i]);
-		free(dtp->dt_pdesc[i]);
 	}
 
 	free(dtp->dt_pdesc);
 	dtp->dt_pdesc = NULL;
 
-	free(dtp->dt_edesc);
-	dtp->dt_edesc = NULL;
+	free(dtp->dt_ddesc);
+	dtp->dt_ddesc = NULL;
 	dtp->dt_nextepid = 0;
 	dtp->dt_maxprobe = 0;
 }
 
+int
+dt_rec_add(dtrace_hdl_t *dtp, dtrace_actkind_t kind, uint32_t size,
+	   uint32_t offset, uint16_t alignment, const char *fmt, uint64_t arg)
+{
+	dt_pcb_t		*pcb = dtp->dt_pcb;
+	dtrace_datadesc_t	*ddp = pcb->pcb_stmt->dtsd_ddesc;
+	dtrace_recdesc_t	*rec;
+	int			cnt, max;
+
+	cnt = pcb->pcb_nrecs + 1;
+	max = pcb->pcb_maxrecs;
+	if (cnt >= max) {
+		int			nmax = max ? (max << 1) : cnt;
+		dtrace_recdesc_t	*nrecs;
+
+		nrecs = dt_calloc(dtp, cnt, sizeof(dtrace_recdesc_t));
+		if (nrecs == NULL)
+			return dt_set_errno(dtp, EDT_NOMEM);
+
+		if (ddp->dtdd_recs != NULL) {
+			size_t	osize = max * sizeof(dtrace_recdesc_t);
+
+			memcpy(nrecs, ddp->dtdd_recs, osize);
+			dt_free(dtp, ddp->dtdd_recs);
+		}
+
+		ddp->dtdd_recs = nrecs;
+		pcb->pcb_maxrecs = nmax;
+	}
+
+	rec = &ddp->dtdd_recs[pcb->pcb_nrecs++];
+	rec->dtrd_action = kind;
+	rec->dtrd_size = size;
+	rec->dtrd_offset = offset;
+	rec->dtrd_alignment = alignment;
+	rec->dtrd_format = 0;	/* FIXME */
+	rec->dtrd_arg = arg;
+
+	return 0;
+}
+
 void *
 dt_format_lookup(dtrace_hdl_t *dtp, int format)
 {
@@ -338,7 +417,6 @@ static int
 dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id)
 {
 	dtrace_id_t max;
-	dtrace_epid_t epid;
 	int rval;
 
 	while (id >= (max = dtp->dt_maxagg) || dtp->dt_aggdesc == NULL) {
@@ -438,8 +516,7 @@ dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id)
 }
 
 int
-dt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid,
-    dtrace_aggdesc_t **adp)
+dt_aggid_lookup(dtrace_hdl_t *dtp, dtrace_aggid_t aggid, dtrace_aggdesc_t **adp)
 {
 	int rval;
 
diff --git a/libdtrace/dt_pcb.h b/libdtrace/dt_pcb.h
index 8a73e7da..da35d03e 100644
--- a/libdtrace/dt_pcb.h
+++ b/libdtrace/dt_pcb.h
@@ -50,6 +50,8 @@ typedef struct dt_pcb {
 	const dtrace_probedesc_t *pcb_pdesc; /* probedesc for current context */
 	struct dt_probe *pcb_probe; /* probe associated with current context */
 	dtrace_probeinfo_t pcb_pinfo; /* info associated with current context */
+	int pcb_nrecs;		/* number of data record descriptions */
+	int pcb_maxrecs;	/* alloc'd number of data record descriptions */
 	dtrace_attribute_t pcb_amin; /* stability minimum for compilation */
 	dt_node_t *pcb_dret;	/* node containing return type for assembler */
 	dtrace_difo_t *pcb_difo; /* intermediate DIF object made by assembler */
diff --git a/libdtrace/dt_program.c b/libdtrace/dt_program.c
index 5555b176..b154668d 100644
--- a/libdtrace/dt_program.c
+++ b/libdtrace/dt_program.c
@@ -220,17 +220,26 @@ dt_ecbdesc_create(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
 dtrace_stmtdesc_t *
 dtrace_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp)
 {
-	dtrace_stmtdesc_t *sdp;
+	dtrace_stmtdesc_t	*sdp;
+	dtrace_datadesc_t	*ddp;
 
-	if ((sdp = dt_zalloc(dtp, sizeof (dtrace_stmtdesc_t))) == NULL)
-		return (NULL);
+	sdp = dt_zalloc(dtp, sizeof(dtrace_stmtdesc_t));
+	if (sdp == NULL)
+		return NULL;
+
+	ddp = dt_datadesc_create(dtp);
+	if (ddp == NULL) {
+		dt_free(dtp, sdp);
+		return NULL;
+	}
 
 	dt_ecbdesc_hold(edp);
 	sdp->dtsd_ecbdesc = edp;
+	sdp->dtsd_ddesc = ddp;
 	sdp->dtsd_descattr = _dtrace_defattr;
 	sdp->dtsd_stmtattr = _dtrace_defattr;
 
-	return (sdp);
+	return sdp;
 }
 
 dtrace_actdesc_t *
@@ -346,6 +355,7 @@ dtrace_stmt_destroy(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
 		dt_printf_destroy(sdp->dtsd_fmtdata);
 
 	dt_ecbdesc_release(dtp, sdp->dtsd_ecbdesc);
+	dt_free(dtp, sdp->dtsd_ddesc);
 	dt_free(dtp, sdp);
 }
 
diff --git a/libdtrace/dtrace.h b/libdtrace/dtrace.h
index 13844324..0b502f34 100644
--- a/libdtrace/dtrace.h
+++ b/libdtrace/dtrace.h
@@ -135,6 +135,7 @@ typedef struct dtrace_stmtdesc {
 	dtrace_ecbdesc_t *dtsd_ecbdesc;		/* ECB description */
 	dtrace_actdesc_t *dtsd_action;		/* action list */
 	dtrace_actdesc_t *dtsd_action_last;	/* last action in action list */
+	dtrace_datadesc_t *dtsd_ddesc;		/* probe data description */
 	void *dtsd_aggdata;			/* aggregation data */
 	void *dtsd_fmtdata;			/* type-specific output data */
 	void (*dtsd_callback)();		/* callback function for EPID */
@@ -173,7 +174,8 @@ typedef enum {
 
 typedef struct dtrace_probedata {
 	dtrace_hdl_t *dtpda_handle;		/* handle to DTrace library */
-	dtrace_eprobedesc_t *dtpda_edesc;	/* enabled probe description */
+	dtrace_epid_t dtpda_epid;		/* enabled probe ID */
+	dtrace_datadesc_t *dtpda_ddesc;		/* probe data description */
 	dtrace_probedesc_t *dtpda_pdesc;	/* probe description */
 	unsigned int dtpda_cpu;			/* CPU for data */
 	caddr_t dtpda_data;			/* pointer to raw data */
@@ -262,7 +264,7 @@ extern dtrace_workstatus_t dtrace_work(dtrace_hdl_t *dtp, FILE *fp,
 
 typedef struct dtrace_errdata {
 	dtrace_hdl_t *dteda_handle;		/* handle to DTrace library */
-	dtrace_eprobedesc_t *dteda_edesc;	/* enabled probe inducing err */
+	dtrace_datadesc_t *dteda_ddesc;		/* probe data inducing err */
 	dtrace_probedesc_t *dteda_pdesc;	/* probe inducing error */
 	unsigned int dteda_cpu;			/* CPU of error */
 	int dteda_action;			/* action inducing error */
@@ -355,7 +357,7 @@ extern int dtrace_handle_setopt(dtrace_hdl_t *dtp,
 struct dtrace_aggdata {
 	dtrace_hdl_t *dtada_handle;		/* handle to DTrace library */
 	dtrace_aggdesc_t *dtada_desc;		/* aggregation description */
-	dtrace_eprobedesc_t *dtada_edesc;	/* enabled probe description */
+	dtrace_datadesc_t *dtada_ddesc;		/* probe data description */
 	dtrace_probedesc_t *dtada_pdesc;	/* probe description */
 	caddr_t dtada_data;			/* pointer to raw data */
 	uint64_t dtada_normal;			/* the normal -- 1 for denorm */
-- 
2.25.0




More information about the DTrace-devel mailing list