[DTrace-devel] Convert the epid tracking code from discovery to explicit construction

Kris Van Hees kris.van.hees at oracle.com
Tue Mar 17 14:44:09 PDT 2020


In legacy DTrace (v1) the mapping from EPID to probe and related data
was constructed on the fly as tracing data was being processed.  When
an unknown EPID was seen, the DTrace kernel component was queried
(using ioctls) to obtain information about the enabling and probe.

Now that we manage all probes and enablings in userspace we already
know all the information about enablings and probes.  We can therefore
simply add them to the list of EPIDs for easy lookup when we start
processing tracing data.

The epid management code in dt_map.c changed (and got simplified) quite
a bit in function of the new design.  EPIDs are now allocated as a new
enabling is added to the list (from dt_bpf.c when we are about to load
a program for a specific probe).

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_bpf.c   | 39 +++++++++++++++++++++---
 libdtrace/dt_bpf.h   |  3 ++
 libdtrace/dt_dlibs.c | 11 +++++--
 libdtrace/dt_impl.h  |  2 ++
 libdtrace/dt_map.c   | 72 ++++++++++++++++++++++++++++++++++++++++++++
 libdtrace/dt_open.c  |  2 ++
 6 files changed, 121 insertions(+), 8 deletions(-)

diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index 5ea573ac..3bd1d016 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -14,6 +14,7 @@
 #include <dtrace.h>
 #include <dt_impl.h>
 #include <dt_probe.h>
+#include <dt_bpf.h>
 #include <port.h>
 
 #include <bpf.h>
@@ -159,7 +160,7 @@ int dt_bpf_map_update(int fd, const void *key, const void *val)
  */
 static void
 dt_bpf_reloc_prog(dtrace_hdl_t *dtp, const dt_probe_t *prp,
-		  const dtrace_difo_t *dp)
+		  const dtrace_difo_t *dp, dtrace_epid_t epid)
 {
 	int			len = dp->dtdo_brelen;
 	const dof_relodesc_t	*rp = dp->dtdo_breltab;
@@ -170,12 +171,37 @@ dt_bpf_reloc_prog(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 		struct bpf_insn	*text = dp->dtdo_buf;
 		int		ioff = rp->dofr_offset /
 					sizeof(struct bpf_insn);
+		uint32_t	val = 0;
+
+		switch (idp->di_kind) {
+		case DT_IDENT_FUNC:
+			continue;
+		case DT_IDENT_PTR:
+			if (rp->dofr_type == R_BPF_64_64)
+				text[ioff].src_reg = BPF_PSEUDO_MAP_FD;
+
+			val = idp->di_id;
+			break;
+		case DT_IDENT_SCALAR:
+			switch (idp->di_id) {
+			case DT_CONST_EPID:
+				val = epid;
+				break;
+			case DT_CONST_ARGC:
+				val = 0;	/* FIXME */
+				break;
+			}
+
+			break;
+		case DT_IDENT_SYMBOL:
+			continue;
+		}
 
 		if (rp->dofr_type == R_BPF_64_64) {
-			text[ioff].src_reg = BPF_PSEUDO_MAP_FD;
-			text[ioff].imm = idp->di_id;
+			text[ioff].imm = val;
 			text[ioff + 1].imm = 0;
-		}
+		} else if (rp->dofr_type == R_BPF_64_32)
+			text[ioff].imm = val;
 	}
 }
 
@@ -189,10 +215,13 @@ dt_bpf_load_prog(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 		 const dtrace_difo_t *dp)
 {
 	struct bpf_load_program_attr	attr;
+	dtrace_epid_t			epid;
 	int				logsz = BPF_LOG_BUF_SIZE;
 	char				*log;
 	int				rc;
 
+	epid = dt_epid_add(dtp, prp->desc->id, 0);
+
 	/*
 	 * Check whether there are any probe-specific relocations to be
 	 * performed.  If so, we need to modify the executable code.  This can
@@ -202,7 +231,7 @@ dt_bpf_load_prog(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 	 * earlier time so we can ignore those.
 	 */
 	if (dp->dtdo_brelen)
-		dt_bpf_reloc_prog(dtp, prp, dp);
+		dt_bpf_reloc_prog(dtp, prp, dp, epid);
 
 	memset(&attr, 0, sizeof(struct bpf_load_program_attr));
 
diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
index c258318f..edb159e8 100644
--- a/libdtrace/dt_bpf.h
+++ b/libdtrace/dt_bpf.h
@@ -14,6 +14,9 @@
 extern "C" {
 #endif
 
+#define DT_CONST_EPID	1
+#define DT_CONST_ARGC	2
+
 extern int dt_bpf_gmap_create(dtrace_hdl_t *, uint_t);
 extern int dt_bpf_map_update(int fd, const void *key, const void *val);
 extern int dt_bpf_prog(dtrace_hdl_t *, dtrace_prog_t *);
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index 2c644cd2..4f1aeaa2 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -14,6 +14,7 @@
 #include <dt_program.h>
 #include <dt_grammar.h>
 #include <dt_impl.h>
+#include <dt_bpf.h>
 
 #define DT_DLIB_D	0
 #define DT_DLIB_BPF	1
@@ -40,7 +41,10 @@ struct dt_bpf_func {
 static dtrace_attribute_t	dt_bpf_attr = DT_ATTR_STABCMN;
 
 #define DT_BPF_SYMBOL(name, type) \
-	{ __stringify(name), type, DT_IDFLG_BPF, DT_IDENT_UNDEF, \
+	{ __stringify(name), (type), DT_IDFLG_BPF, DT_IDENT_UNDEF, \
+		DT_ATTR_STABCMN, DT_VERS_2_0, }
+#define DT_BPF_SYMBOL_ID(name, type, id) \
+	{ __stringify(name), (type), DT_IDFLG_BPF, (id), \
 		DT_ATTR_STABCMN, DT_VERS_2_0, }
 static const dt_ident_t	dt_bpf_symbols[] = {
 	/* BPF built-in functions */
@@ -62,12 +66,13 @@ static const dt_ident_t	dt_bpf_symbols[] = {
 	DT_BPF_SYMBOL(probes, DT_IDENT_PTR),
 	DT_BPF_SYMBOL(mem, DT_IDENT_PTR),
 	/* BPF internal identifiers */
-	DT_BPF_SYMBOL(EPID, DT_IDENT_SCALAR),
-	DT_BPF_SYMBOL(ARGC, DT_IDENT_SCALAR),
+	DT_BPF_SYMBOL_ID(EPID, DT_IDENT_SCALAR, DT_CONST_EPID),
+	DT_BPF_SYMBOL_ID(ARGC, DT_IDENT_SCALAR, DT_CONST_ARGC),
 	/* End-of-list marker */
 	{ NULL, }
 };
 #undef DT_BPF_SYMBOL
+#undef DT_BPF_SYMBOL_ID
 
 /*
  * Perform initialization for the BPF function library handling.
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index b38c9ad8..019e91a4 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -287,6 +287,7 @@ struct dtrace_hdl {
 	ctf_id_t dt_type_stack;	/* cached CTF identifier for stack type */
 	ctf_id_t dt_type_symaddr; /* cached CTF identifier for _symaddr type */
 	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_probedesc_t **dt_pdesc; /* probe descriptions for enabled prbs */
@@ -708,6 +709,7 @@ 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 void dt_epid_destroy(dtrace_hdl_t *);
diff --git a/libdtrace/dt_map.c b/libdtrace/dt_map.c
index 29d6aabc..48ffa15d 100644
--- a/libdtrace/dt_map.c
+++ b/libdtrace/dt_map.c
@@ -11,8 +11,10 @@
 #include <assert.h>
 
 #include <dt_impl.h>
+#include <dt_probe.h>
 #include <dt_printf.h>
 
+#if 0
 static int
 dt_epid_add(dtrace_hdl_t *dtp, dtrace_epid_t id)
 {
@@ -186,6 +188,71 @@ err:
 	free(probe);
 	return (rval);
 }
+#else
+dtrace_epid_t
+dt_epid_add(dtrace_hdl_t *dtp, dtrace_id_t prid, int nrecs)
+{
+	dtrace_id_t		max;
+	dtrace_epid_t		epid;
+	dtrace_eprobedesc_t	*eprobe;
+
+	epid = dtp->dt_nextepid++;
+	max = dtp->dt_maxprobe;
+	if (epid >= max || dtp->dt_edesc == NULL) {
+		dtrace_id_t		nmax = max ? (max << 1) : 2;
+		dtrace_eprobedesc_t	**nedesc;
+		dtrace_probedesc_t	**npdesc;
+
+		nedesc = dt_calloc(dtp, nmax, sizeof(void *));
+		npdesc = dt_calloc(dtp, nmax, sizeof(void *));
+		if (nedesc == NULL || npdesc == NULL) {
+			dt_free(dtp, nedesc);
+			dt_free(dtp, npdesc);
+			return dt_set_errno(dtp, EDT_NOMEM);
+		}
+
+		if (dtp->dt_edesc != NULL) {
+			size_t	osize = max * sizeof(void *);
+
+			memcpy(nedesc, dtp->dt_edesc, osize);
+			dt_free(dtp, dtp->dt_edesc);
+			memcpy(npdesc, dtp->dt_pdesc, osize);
+			dt_free(dtp, dtp->dt_pdesc);
+		}
+
+		dtp->dt_edesc = nedesc;
+		dtp->dt_pdesc = npdesc;
+		dtp->dt_maxprobe = nmax;
+	}
+
+	if (dtp->dt_edesc[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;
+	dtp->dt_pdesc[epid] = (dtrace_probedesc_t *)dtp->dt_probes[prid]->desc;
+
+	return epid;
+}
+#endif
 
 int
 dt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid,
@@ -193,10 +260,12 @@ dt_epid_lookup(dtrace_hdl_t *dtp, dtrace_epid_t epid,
 {
 	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);
@@ -235,6 +304,7 @@ dt_epid_destroy(dtrace_hdl_t *dtp)
 
 	free(dtp->dt_edesc);
 	dtp->dt_edesc = NULL;
+	dtp->dt_nextepid = 0;
 	dtp->dt_maxprobe = 0;
 }
 
@@ -351,6 +421,7 @@ dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id)
 			agg->dtagd_varid = DTRACE_AGGVARIDNONE;
 		}
 
+#if 0
 		if ((epid = agg->dtagd_epid) >= dtp->dt_maxprobe ||
 		    dtp->dt_pdesc[epid] == NULL) {
 			if ((rval = dt_epid_add(dtp, epid)) != 0) {
@@ -358,6 +429,7 @@ dt_aggid_add(dtrace_hdl_t *dtp, dtrace_aggid_t id)
 				return (rval);
 			}
 		}
+#endif
 
 		dtp->dt_aggdesc[id] = agg;
 	}
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index 0fd83d2e..bf26d007 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -721,6 +721,8 @@ dt_vopen(int version, int flags, int *errp,
 	dtp->dt_provbuckets = _dtrace_strbuckets;
 	dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
 	dt_proc_hash_create(dtp);
+	dtp->dt_nextepid = 1;
+	dtp->dt_maxprobe = 0;
 	dtp->dt_vmax = DT_VERS_LATEST;
 	dtp->dt_cpp_path = strdup(_dtrace_defcpp);
 	dtp->dt_cpp_argv = malloc(sizeof (char *));
-- 
2.25.0




More information about the DTrace-devel mailing list