[DTrace-devel] [PATCH] Convert dvars to use the default block of zeros

Kris Van Hees kris.van.hees at oracle.com
Thu Aug 4 13:55:45 UTC 2022


The code sequence for retrieving dynamic variables (TLS variables and
associative arrays) is modified, so the disassembler annotation code is
updated to relfect this.  As a useful side effect, relocation symbols
are now reported for mov and arithmetic intructions as well.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 bpf/get_dvar.c                       | 21 ++++++++----------
 libdtrace/dt_bpf.c                   | 20 +++++------------
 libdtrace/dt_cg.c                    | 32 ++++++++++++++++------------
 libdtrace/dt_dis.c                   | 24 ++++++++++++++-------
 test/unittest/disasm/tst.ann-tvar.r  |  4 +++-
 test/unittest/disasm/tst.ann-tvar.sh |  4 +++-
 6 files changed, 54 insertions(+), 51 deletions(-)

diff --git a/bpf/get_dvar.c b/bpf/get_dvar.c
index 7e9c0fc7..d11182df 100644
--- a/bpf/get_dvar.c
+++ b/bpf/get_dvar.c
@@ -46,9 +46,9 @@ noinline uint64_t dt_tlskey(uint32_t id)
 	return key;
 }
 
-noinline void *dt_get_dvar(uint64_t key, uint64_t store, uint64_t nval)
+noinline void *dt_get_dvar(uint64_t key, uint64_t store, uint64_t nval,
+			   const char *dflt)
 {
-	uint64_t	dflt_key = 0;
 	void		*val;
 
 	/*
@@ -79,11 +79,7 @@ noinline void *dt_get_dvar(uint64_t key, uint64_t store, uint64_t nval)
 	 * Not found and we are storing a non-zero value: create the variable
 	 * with the default value.
 	 */
-	val = bpf_map_lookup_elem(&dvars, &dflt_key);
-	if (val == 0)
-		return 0;
-
-	if (bpf_map_update_elem(&dvars, &key, val, BPF_ANY) < 0)
+	if (bpf_map_update_elem(&dvars, &key, dflt, BPF_ANY) < 0)
 		return 0;
 
 	val = bpf_map_lookup_elem(&dvars, &key);
@@ -93,13 +89,14 @@ noinline void *dt_get_dvar(uint64_t key, uint64_t store, uint64_t nval)
 	return 0;
 }
 
-noinline void *dt_get_tvar(uint32_t id, uint64_t store, uint64_t nval)
+noinline void *dt_get_tvar(uint32_t id, uint64_t store, uint64_t nval,
+			   const char *dflt)
 {
-	return dt_get_dvar(dt_tlskey(id), store, nval);
+	return dt_get_dvar(dt_tlskey(id), store, nval, dflt);
 }
 
-noinline void *dt_get_assoc(uint32_t id, const char *tuple,
-			    uint64_t store, uint64_t nval)
+noinline void *dt_get_assoc(uint32_t id, const char *tuple, uint64_t store,
+			    uint64_t nval, const char *dflt)
 {
 	uint64_t	*valp;
 	uint64_t	val;
@@ -151,5 +148,5 @@ noinline void *dt_get_assoc(uint32_t id, const char *tuple,
 			bpf_map_delete_elem(&tuples, tuple);
 	}
 
-	return dt_get_dvar(val, store, nval);
+	return dt_get_dvar(val, store, nval, dflt);
 }
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index 17562b9d..d5b8e21b 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -431,7 +431,8 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
 	 */
 	dtp->dt_strlen = dt_strtab_size(dtp->dt_ccstab);
 	dtp->dt_zerooffset = P2ROUNDUP(dtp->dt_strlen, 8);
-	sz = dtp->dt_zerooffset + MAX(strsize + 1, dtp->dt_zerosize);
+	dtp->dt_zerosize = MAX(dtp->dt_maxdvarsize, strsize + 1);
+	sz = dtp->dt_zerooffset + dtp->dt_zerosize;
 	strtab = dt_zalloc(dtp, sz);
 	if (strtab == NULL)
 		return dt_set_errno(dtp, EDT_NOMEM);
@@ -481,22 +482,11 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
 		dvarc = dtp->dt_options[DTRACEOPT_DYNVARSIZE] /
 			dtp->dt_maxdvarsize;
 
-	if (dvarc > 0) {
-		int	fd;
-		char	dflt[dtp->dt_maxdvarsize];
-
-		/* Allocate one extra element for the default value. */
-		fd = create_gmap(dtp, "dvars", BPF_MAP_TYPE_HASH,
-				 sizeof(uint64_t), dtp->dt_maxdvarsize,
-				 dvarc + 1);
-		if (fd == -1)
+	if (dvarc > 0 &&
+	    create_gmap(dtp, "dvars", BPF_MAP_TYPE_HASH,
+			sizeof(uint64_t), dtp->dt_maxdvarsize, dvarc) == -1)
 			return -1;	/* dt_errno is set for us */
 
-		/* Initialize the default value (key = 0). */
-		memset(dflt, 0, dtp->dt_maxdvarsize);
-		dt_bpf_map_update(fd, &key, &dflt);
-	}
-
 	if (dtp->dt_maxtuplesize > 0 &&
 	    create_gmap(dtp, "tuples", BPF_MAP_TYPE_HASH,
 			dtp->dt_maxtuplesize, sizeof(uint64_t), dvarc) == -1)
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index cb79c5b4..c5db5fa3 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -2081,6 +2081,20 @@ dt_cg_membinfo(ctf_file_t *fp, ctf_id_t type, const char *s, ctf_membinfo_t *mp)
 	return fp;
 }
 
+/*
+ * Store a pointer to the 'memory block of zeros' in reg.
+ */
+static void
+dt_cg_zerosptr(int reg, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dtrace_hdl_t	*dtp = yypcb->pcb_hdl;
+	dt_ident_t	*zero_off = dt_dlib_get_var(dtp, "ZERO_OFF");
+
+	emit(dlp,  BPF_LOAD(BPF_DW, reg, BPF_REG_FP, DT_STK_DCTX));
+	emit(dlp,  BPF_LOAD(BPF_DW, reg, reg, DCTX_STRTAB));
+	emite(dlp, BPF_ALU64_IMM(BPF_ADD, reg, -1), zero_off);
+}
+
 void
 dt_cg_xsetx(dt_irlist_t *dlp, dt_ident_t *idp, uint_t lbl, int reg, uint64_t x)
 {
@@ -2217,6 +2231,7 @@ dt_cg_load_var(dt_node_t *dst, dt_irlist_t *dlp, dt_regset_t *drp)
 		emit(dlp,  BPF_MOV_IMM(BPF_REG_1, varid));
 		emit(dlp,  BPF_MOV_IMM(BPF_REG_2, 0));
 		emit(dlp,  BPF_MOV_IMM(BPF_REG_3, 0));
+		dt_cg_zerosptr(BPF_REG_4, dlp, drp);
 		dt_regset_xalloc(drp, BPF_REG_0);
 		emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
 		dt_regset_free_args(drp);
@@ -2561,20 +2576,6 @@ dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
 	}
 }
 
-/*
- * Store a pointer to the 'memory block of zeros' in reg.
- */
-static void
-dt_cg_zerosptr(int reg, dt_irlist_t *dlp, dt_regset_t *drp)
-{
-	dtrace_hdl_t	*dtp = yypcb->pcb_hdl;
-	dt_ident_t	*zero_off = dt_dlib_get_var(dtp, "ZERO_OFF");
-
-	emit(dlp,  BPF_LOAD(BPF_DW, reg, BPF_REG_FP, DT_STK_DCTX));
-	emit(dlp,  BPF_LOAD(BPF_DW, reg, reg, DCTX_STRTAB));
-	emite(dlp, BPF_ALU64_IMM(BPF_ADD, reg, -1), zero_off);
-}
-
 /*
  * Generate code to push the specified argument list on to the tuple stack.
  * We use this routine for handling the index tuple for associative arrays.
@@ -2830,6 +2831,7 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
 		dt_regset_free(drp, dnp->dn_left->dn_args->dn_reg);
 		emit(dlp,  BPF_MOV_IMM(BPF_REG_3, 1));
 		emit(dlp,  BPF_MOV_REG(BPF_REG_4, dnp->dn_reg));
+		dt_cg_zerosptr(BPF_REG_5, dlp, drp);
 		dt_regset_xalloc(drp, BPF_REG_0);
 		emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
 		dt_regset_free_args(drp);
@@ -2929,6 +2931,7 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
 	emit(dlp,  BPF_MOV_IMM(BPF_REG_1, varid));
 	emit(dlp,  BPF_MOV_IMM(BPF_REG_2, 1));
 	emit(dlp,  BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
+	dt_cg_zerosptr(BPF_REG_4, dlp, drp);
 	dt_regset_xalloc(drp, BPF_REG_0);
 	emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
 	dt_regset_free_args(drp);
@@ -3632,6 +3635,7 @@ dt_cg_assoc_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	dt_regset_free(drp, dnp->dn_args->dn_reg);
 	emit(dlp,  BPF_MOV_IMM(BPF_REG_3, 0));
 	emit(dlp,  BPF_MOV_IMM(BPF_REG_4, 0));
+	dt_cg_zerosptr(BPF_REG_5, dlp, drp);
 	dt_regset_xalloc(drp, BPF_REG_0);
 	emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
 	dt_regset_free_args(drp);
diff --git a/libdtrace/dt_dis.c b/libdtrace/dt_dis.c
index 9e6d3be8..ecbe7524 100644
--- a/libdtrace/dt_dis.c
+++ b/libdtrace/dt_dis.c
@@ -106,16 +106,24 @@ dt_dis_varname_off(const dtrace_difo_t *dp, uint_t off, uint_t scope, uint_t add
  *          -1:    ld   dst  dst  DCTX_STRTAB  00000000
  *           0:    add  dst    0     0         var_offset
  * where instruction 0 is the current instruction.
+ *
+ * In all cases, if a relocation symbol name is provided, report that.
  */
 static void
 dt_dis_refname(const dtrace_difo_t *dp, const struct bpf_insn *in, uint_t addr,
-	       int n, FILE *fp)
+	       const char *rname, int n, FILE *fp)
 {
 	__u8		ldcode = BPF_LDX | BPF_MEM | BPF_DW;
 	__u8		addcode = BPF_ALU64 | BPF_ADD | BPF_K;
 	int		dst, scope = -1, var_offset = -1;
 	const char	*str;
 
+	/* if we have a relocation symbol name, use that */
+	if (rname != NULL) {
+		fprintf(fp, "%*s! %s", DT_DIS_PAD(n), "", rname);
+		goto out;
+	}
+
 	/* make sure in[-2] and in[-1] exist */
 	if (addr < 2)
 		goto out;
@@ -211,7 +219,7 @@ dt_dis_op2imm(const dtrace_difo_t *dp, const char *name, uint_t addr,
 	int		n;
 
 	n = fprintf(fp, "%-4s %s, %d", name, reg(in->dst_reg), in->imm);
-	dt_dis_refname(dp, in, addr, n, fp);
+	dt_dis_refname(dp, in, addr, rname, n, fp);
 
 	return 0;
 }
@@ -273,7 +281,7 @@ dt_dis_load(const dtrace_difo_t *dp, const char *name, uint_t addr,
 		fprintf(fp, "%*s! restore %s\n", DT_DIS_PAD(n), "",
 			reg(in->dst_reg));
 	} else
-		dt_dis_refname(dp, in, addr, n, fp);
+		dt_dis_refname(dp, in, addr, rname, n, fp);
 
 	return 0;
 }
@@ -317,7 +325,7 @@ dt_dis_store(const dtrace_difo_t *dp, const char *name, uint_t addr,
 		fprintf(fp, "%*s! spill %s\n", DT_DIS_PAD(n), "",
 			reg(in->src_reg));
 	} else
-		dt_dis_refname(dp, in, addr, n, fp);
+		dt_dis_refname(dp, in, addr, rname, n, fp);
 
 	return 0;
 }
@@ -357,12 +365,12 @@ dt_dis_bpf_args(const dtrace_difo_t *dp, const char *fn,
 		return buf;
 	} else if (strcmp(fn, "dt_get_tvar") == 0) {
 		/*
-		 * We know that the previous three instructions exist and
+		 * We know that the previous six instructions exist and
 		 * move the variable id to a register in the first instruction
 		 * of that seqeuence (because we wrote the code generator to
 		 * emit the instructions in this exact order.)
 		 */
-		in -= 3;
+		in -= 6;
 		snprintf(buf, len, "self->%s",
 			 dt_dis_varname_id(dp, in->imm + DIF_VAR_OTHER_UBASE,
 					DIFV_SCOPE_THREAD, addr));
@@ -371,12 +379,12 @@ dt_dis_bpf_args(const dtrace_difo_t *dp, const char *fn,
 		uint_t		varid;
 
 		/*
-		 * We know that the previous four instructions exist and
+		 * We know that the previous seven instructions exist and
 		 * move the variable id to a register in the first instruction
 		 * of that seqeuence (because we wrote the code generator to
 		 * emit the instructions in this exact order.)
 		 */
-		in -= 4;
+		in -= 7;
 		varid = in->imm + DIF_VAR_OTHER_UBASE;
 
 		/*
diff --git a/test/unittest/disasm/tst.ann-tvar.r b/test/unittest/disasm/tst.ann-tvar.r
index 5194531b..39065fdc 100644
--- a/test/unittest/disasm/tst.ann-tvar.r
+++ b/test/unittest/disasm/tst.ann-tvar.r
@@ -1 +1,3 @@
-85 0 1 0000 ffffffff    call dt_get_tvar              ! self->var
+85 0 1 0000 ffffffff    call dt_get_tvar              ! self->one
+85 0 1 0000 ffffffff    call dt_get_tvar              ! self->two
+85 0 1 0000 ffffffff    call dt_get_tvar              ! self->three
diff --git a/test/unittest/disasm/tst.ann-tvar.sh b/test/unittest/disasm/tst.ann-tvar.sh
index 66501840..729e703c 100755
--- a/test/unittest/disasm/tst.ann-tvar.sh
+++ b/test/unittest/disasm/tst.ann-tvar.sh
@@ -11,7 +11,9 @@ dtrace=$1
 $dtrace $dt_flags -Sen '
 BEGIN
 {
-	self->var = 42;
+	self->one = 42;
+	self->two = 42;
+	self->three = 42;
 	exit(0);
 }
 ' 2>&1 | awk '/ call dt_get_tvar/ { sub(/^[^:]+: /, ""); print; }'
-- 
2.34.1




More information about the DTrace-devel mailing list