[DTrace-devel] [PATCH 15/20] Add support for string constants in compiled D programs

Kris Van Hees kris.van.hees at oracle.com
Tue Jun 1 22:48:15 PDT 2021


Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 include/dtrace/dif_defines.h             |  2 +-
 libdtrace/dt_cg.c                        | 76 +++++++++++++-----------
 libdtrace/dt_dctx.h                      |  2 +
 libdtrace/dt_printf.c                    |  2 +
 test/unittest/codegen/tst.stack_layout.r | 22 +++----
 test/unittest/scalars/tst.self.d         |  1 -
 test/unittest/sizeof/tst.SizeofString2.d |  1 -
 7 files changed, 56 insertions(+), 50 deletions(-)

diff --git a/include/dtrace/dif_defines.h b/include/dtrace/dif_defines.h
index bca9c630..55087f4e 100644
--- a/include/dtrace/dif_defines.h
+++ b/include/dtrace/dif_defines.h
@@ -113,7 +113,7 @@
 #endif
 
 #define	DIF_INTOFF_MAX		0xffff	/* highest integer table offset */
-#define	DIF_STROFF_MAX		0xffff	/* highest string table offset */
+#define	DIF_STROFF_MAX		0x7fff	/* highest string table offset */
 #define	DIF_REGISTER_MAX	0xff	/* highest register number */
 #define	DIF_VARIABLE_MAX	0xffff	/* highest variable identifier */
 #define	DIF_SUBROUTINE_MAX	0xffff	/* highest subroutine code */
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index c51e515c..e7cc00bc 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -21,6 +21,7 @@
 #include <dt_printf.h>
 #include <dt_provider.h>
 #include <dt_probe.h>
+#include <dt_varint.h>
 #include <bpf_asm.h>
 
 static void dt_cg_node(dt_node_t *, dt_irlist_t *, dt_regset_t *);
@@ -160,19 +161,21 @@ dt_cg_tramp_prologue_act(dt_pcb_t *pcb, dt_activity_t act)
 #define DT_CG_STORE_MAP_PTR(name, offset) \
 	do { \
 		dt_ident_t *idp = dt_dlib_get_map(dtp, name); \
- \
+		\
+		assert(idp != NULL); \
 		emit(dlp, BPF_STORE_IMM(BPF_W, BPF_REG_FP, DCTX_FP(offset), 0)); \
- \
+		\
 		dt_cg_xsetx(dlp, idp, DT_LBL_NONE, BPF_REG_1, idp->di_id); \
 		emit(dlp, BPF_MOV_REG(BPF_REG_2, BPF_REG_FP)); \
 		emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, DCTX_FP(offset))); \
 		emit(dlp, BPF_CALL_HELPER(BPF_FUNC_map_lookup_elem)); \
- \
+		\
 		emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_0, 0, lbl_exit)); \
- \
+		\
 		emit(dlp, BPF_STORE(BPF_DW, BPF_REG_FP, DCTX_FP(offset), BPF_REG_0)); \
 	} while(0)
 
+	DT_CG_STORE_MAP_PTR("strtab", DCTX_STRTAB);
 	if (dt_idhash_datasize(dtp->dt_aggs) > 0)
 		DT_CG_STORE_MAP_PTR("aggs", DCTX_AGG);
 	if (dt_idhash_datasize(dtp->dt_globals) > 0)
@@ -733,27 +736,16 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
 		dt_regset_free(drp, dnp->dn_reg);
 
 		return 0;
-#if 0
-	} else if (dt_node_is_string(dnp->dn_args)) {
-		size_t sz = dt_node_type_size(dnp->dn_args);
+	} else if (dt_node_is_string(dnp)) {
+		off = dt_rec_add(pcb->pcb_hdl, dt_cg_fill_gap, kind,
+				 size, 1, pfp, arg);
 
-		/*
-		 * Strings are stored as a 64-bit size followed by a character
-		 * array.  Given that all entries in the output buffer are
-		 * aligned at 64-bit boundaries, this guarantees that the
-		 * character array is also aligned at a 64-bit boundary.
-		 * We will pad the string to a multiple of 8 bytes as well.
-		 *
-		 * We store the size as two 32-bit values, lower 4 bytes first,
-		 * then the higher 4 bytes.
-		 */
-		sz = P2ROUNDUP(sz, sizeof(uint64_t));
-		emit(dlp, BPF_STORE_IMM(BPF_W, BPF_REG_9, off, sz & ((1UL << 32)-1)));
-		emit(dlp, BPF_STORE_IMM(BPF_W, BPF_REG_9, off + 4, sz >> 32));
-		dt_regset_free(drp, dnp->dn_args->dn_reg);
+		emit(dlp, BPF_MOV_REG(BPF_REG_0, BPF_REG_9));
+		emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, off));
+		dt_cg_memcpy(dlp, drp, BPF_REG_0, dnp->dn_reg, size);
+		dt_regset_free(drp, dnp->dn_reg);
 
-		return sz + sizeof(uint64_t);
-#endif
+		return 0;
 	}
 
 	return -1;
@@ -1935,8 +1927,27 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
 
 		/* store by value or by reference */
 		if (src->dn_flags & DT_NF_REF) {
+			size_t	size;
+
 			emit(dlp, BPF_ALU64_IMM(BPF_ADD, reg, idp->di_offset));
-			dt_cg_memcpy(dlp, drp, reg, src->dn_reg, idp->di_size);
+
+			/*
+			 * Determine the amount of data to be copied.  It is
+			 * usually the size of the identifier, except for
+			 * string constants where it is the size of the string
+			 * constant (adjusted for the variable-width length
+			 * prefix).  An assignment of a string constant is a
+			 * store of type 'string' with a RHS of type
+			 * DT_TOK_STRING.
+			 */
+			if (dt_node_is_string(src) &&
+			    src->dn_right->dn_op == DT_TOK_STRING) {
+				size = dt_node_type_size(src->dn_right);
+				size += dt_vint_size(size) + 1;
+			} else
+				size = idp->di_size;
+
+			dt_cg_memcpy(dlp, drp, reg, src->dn_reg, size);
 		} else {
 			size_t	size = idp->di_size;
 
@@ -3244,19 +3255,12 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 			longjmp(yypcb->pcb_jmpbuf, EDT_STR2BIG);
 
 		/*
-		 * The string table will be loaded as value for the 0 element
-		 * in the strtab BPF array map.  We use a function call to get
-		 * the actual string:
-		 *	get_string(stroff);
+		 * Calculate the address of the string data in the 'strtab' BPF
+		 * map.
 		 */
-		if (dt_regset_xalloc_args(drp) == -1)
-			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-		idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_string");
-		assert(idp != NULL);
-		emit(dlp,  BPF_MOV_IMM(BPF_REG_1, stroff));
-		emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
-		emit(dlp,  BPF_MOV_REG(dnp->dn_reg, BPF_REG_0));
-		dt_regset_free_args(drp);
+		emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_FP, DT_STK_DCTX));
+		emit(dlp, BPF_LOAD(BPF_DW, dnp->dn_reg, dnp->dn_reg, DCTX_STRTAB));
+		emit(dlp, BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, stroff));
 		break;
 
 	case DT_TOK_IDENT:
diff --git a/libdtrace/dt_dctx.h b/libdtrace/dt_dctx.h
index 0873602c..3ba474b0 100644
--- a/libdtrace/dt_dctx.h
+++ b/libdtrace/dt_dctx.h
@@ -38,6 +38,7 @@ typedef struct dt_dctx {
 	dt_activity_t	*act;		/* pointer to activity state */
 	dt_mstate_t	*mst;		/* DTrace machine state */
 	char		*buf;		/* Output buffer scratch memory */
+	char		*strtab;	/* String constant table */
 	char		*agg;		/* Aggregation data */
 	char		*gvars;		/* Global variables */
 	char		*lvars;		/* Local variables */
@@ -47,6 +48,7 @@ typedef struct dt_dctx {
 #define DCTX_ACT	offsetof(dt_dctx_t, act)
 #define DCTX_MST	offsetof(dt_dctx_t, mst)
 #define DCTX_BUF	offsetof(dt_dctx_t, buf)
+#define DCTX_STRTAB	offsetof(dt_dctx_t, strtab)
 #define DCTX_AGG	offsetof(dt_dctx_t, agg)
 #define DCTX_GVARS	offsetof(dt_dctx_t, gvars)
 #define DCTX_LVARS	offsetof(dt_dctx_t, lvars)
diff --git a/libdtrace/dt_printf.c b/libdtrace/dt_printf.c
index 6d6187ee..cd2a8fce 100644
--- a/libdtrace/dt_printf.c
+++ b/libdtrace/dt_printf.c
@@ -16,6 +16,7 @@
 
 #include <dt_printf.h>
 #include <dt_string.h>
+#include <dt_varint.h>
 #include <dt_impl.h>
 
 /*ARGSUSED*/
@@ -489,6 +490,7 @@ pfprint_cstr(dtrace_hdl_t *dtp, FILE *fp, const char *format,
 
 	memcpy(s, addr, size);
 	s[size] = '\0';
+	s = (char *)dt_vint_skip(s);
 	return dt_printf(dtp, fp, format, s);
 }
 
diff --git a/test/unittest/codegen/tst.stack_layout.r b/test/unittest/codegen/tst.stack_layout.r
index 48be58d2..cc23a6a1 100644
--- a/test/unittest/codegen/tst.stack_layout.r
+++ b/test/unittest/codegen/tst.stack_layout.r
@@ -1,12 +1,12 @@
 Base:          0
-dctx:        -56
-%r0:         -64
-%r1:         -72
-%r2:         -80
-%r3:         -88
-%r4:         -96
-%r5:        -104
-%r6:        -112
-%r7:        -120
-%r8:        -128
-scratch:    -129 .. -512
+dctx:        -64
+%r0:         -72
+%r1:         -80
+%r2:         -88
+%r3:         -96
+%r4:        -104
+%r5:        -112
+%r6:        -120
+%r7:        -128
+%r8:        -136
+scratch:    -137 .. -512
diff --git a/test/unittest/scalars/tst.self.d b/test/unittest/scalars/tst.self.d
index 2611e993..515ee786 100644
--- a/test/unittest/scalars/tst.self.d
+++ b/test/unittest/scalars/tst.self.d
@@ -4,7 +4,6 @@
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/sizeof/tst.SizeofString2.d b/test/unittest/sizeof/tst.SizeofString2.d
index 62378a46..8abb9f91 100644
--- a/test/unittest/sizeof/tst.SizeofString2.d
+++ b/test/unittest/sizeof/tst.SizeofString2.d
@@ -4,7 +4,6 @@
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION: sizeof returns the size in bytes of any D expression or data
-- 
2.31.1




More information about the DTrace-devel mailing list