[DTrace-devel] [PATCH] ensure global and TLS variables map to keys starting at 0

Eugene Loh eugene.loh at oracle.com
Fri Mar 20 00:02:16 PDT 2020


Global and TLS variables are assigned an id from DIF_VAR_OTHER_UBASE
onward in order to distinguish them from built-in global variables.
Up until now the code generator was applying a base offset to the
variable ids for debugging purposes.

This patch adds support for distinguishing built-in variables from
user defined global variables.  All variables in a specific class
or scope should be mapped to keys that are assigned from 0 onward.

Built-in variables are loaded using dt_get_bvar.
Global variables are loaded using dt_get_gvar, and stored using
dt_set_gvar.
TLS variables are loaded using dt_get_tvar, and stored using
dt_set_tvar.

This patch also adjusts the disassembler to ensure that it is able to
retrieve the correct variable name (and scope).

The support for TLS variables is still left unimplemented at this
point and it is therefore encoded as if they are regular global
variables.  A correct implementation is forthcoming.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_bpf_builtins.h |   1 +
 libdtrace/dt_cg.c           | 119 +++++++++++++++++-------------------
 libdtrace/dt_dis.c          |  22 +++++--
 libdtrace/dt_dlibs.c        |   1 +
 4 files changed, 76 insertions(+), 67 deletions(-)

diff --git a/libdtrace/dt_bpf_builtins.h b/libdtrace/dt_bpf_builtins.h
index 30b24624..edf0333e 100644
--- a/libdtrace/dt_bpf_builtins.h
+++ b/libdtrace/dt_bpf_builtins.h
@@ -14,6 +14,7 @@ extern "C" {
 #endif
 
 #define DT_BPF_MAP_BUILTINS(FN) \
+	FN(get_bvar), \
 	FN(get_gvar), \
 	FN(get_string), \
 	FN(get_tvar), \
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index e0e58abc..4945dead 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -774,6 +774,58 @@ dt_cg_load(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type)
 #endif
 }
 
+static void
+dt_cg_load_var(dt_node_t *dst, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	struct bpf_insn	instr;
+	dt_ident_t	*idp = dt_ident_resolve(dst->dn_ident);
+
+	idp->di_flags |= DT_IDFLG_DIFR;
+	if (idp->di_flags & DT_IDFLG_LOCAL) {		/* local var */
+		instr = BPF_LOAD(BPF_DW, dst->dn_reg, BPF_REG_FP,
+				 DT_STK_LVAR(idp->di_id));
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+	} else if (idp->di_flags & DT_IDFLG_TLS) {	/* TLS var */
+		dt_regset_xalloc(drp, BPF_REG_1);
+		instr = BPF_MOV_IMM(BPF_REG_1,
+				    idp->di_id - DIF_VAR_OTHER_UBASE);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_tvar");
+		assert(idp != NULL);
+		dt_regset_xalloc(drp, BPF_REG_0);
+		instr = BPF_CALL_FUNC(idp->di_id);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		dlp->dl_last->di_extern = idp;
+		instr = BPF_MOV_REG(dst->dn_reg, BPF_REG_0);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		dt_regset_free(drp, BPF_REG_0);
+		dt_regset_free(drp, BPF_REG_1);
+	} else {					/* global var */
+		dt_regset_xalloc(drp, BPF_REG_1);
+		if (idp->di_id < DIF_VAR_OTHER_UBASE) {	/* built-in var */
+			instr = BPF_MOV_IMM(BPF_REG_1, idp->di_id);
+			dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE,
+					 instr));
+			idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_bvar");
+		} else {
+			instr = BPF_MOV_IMM(BPF_REG_1,
+					    idp->di_id - DIF_VAR_OTHER_UBASE);
+			dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE,
+					 instr));
+			idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_gvar");
+		}
+		assert(idp != NULL);
+		dt_regset_xalloc(drp, BPF_REG_0);
+		instr = BPF_CALL_FUNC(idp->di_id);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		dlp->dl_last->di_extern = idp;
+		instr = BPF_MOV_REG(dst->dn_reg, BPF_REG_0);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		dt_regset_free(drp, BPF_REG_0);
+		dt_regset_free(drp, BPF_REG_1);
+	}
+}
+
 static void
 dt_cg_ptrsize(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
     uint_t op, int dreg)
@@ -1054,7 +1106,8 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
 		instr = BPF_MOV_REG(BPF_REG_2, src->dn_reg);
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
 		dt_regset_xalloc(drp, BPF_REG_1);
-		instr = BPF_MOV_IMM(BPF_REG_1, 0x2000 + idp->di_id);
+		instr = BPF_MOV_IMM(BPF_REG_1,
+				    idp->di_id - DIF_VAR_OTHER_UBASE);
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
 		idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_set_tvar");
 		assert(idp != NULL);
@@ -1070,7 +1123,8 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
 		instr = BPF_MOV_REG(BPF_REG_2, src->dn_reg);
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
 		dt_regset_xalloc(drp, BPF_REG_1);
-		instr = BPF_MOV_IMM(BPF_REG_1, 0x3000 + idp->di_id);
+		instr = BPF_MOV_IMM(BPF_REG_1,
+				    idp->di_id - DIF_VAR_OTHER_UBASE);
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
 		idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_set_gvar");
 		assert(idp != NULL);
@@ -2433,8 +2487,6 @@ if ((idp = dnp->dn_ident)->di_kind != DT_IDENT_FUNC)
 			break;
 
 		case DT_NODE_VAR: {
-			ssize_t	base;
-
 			if (dnp->dn_ident->di_kind == DT_IDENT_XLSOU ||
 			    dnp->dn_ident->di_kind == DT_IDENT_XLPTR) {
 				/*
@@ -2457,65 +2509,8 @@ if ((idp = dnp->dn_ident)->di_kind != DT_IDENT_FUNC)
 			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
 				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
 
-			if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL) {
-				base = 0x1000;
-				instr = BPF_LOAD(
-					    BPF_DW, dnp->dn_reg, BPF_REG_FP,
-					    DT_STK_LVAR(dnp->dn_ident->di_id));
-				dt_irlist_append(dlp,
-						 dt_cg_node_alloc(DT_LBL_NONE,
-								  instr));
-			} else if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
-				base = 0x2000;
-			else
-				base = 0x3000;
-
-			dnp->dn_ident->di_flags |= DT_IDFLG_DIFR;
+			dt_cg_load_var(dnp, dlp, drp);
 
-/* FIXME */
-			if (base == 0x3000) {
-				dt_regset_xalloc(drp, BPF_REG_1);
-				instr = BPF_ALU64_IMM(BPF_MOV, BPF_REG_1,
-						      dnp->dn_ident->di_id);
-				dt_irlist_append(dlp,
-						 dt_cg_node_alloc(DT_LBL_NONE,
-								  instr));
-				idp = dt_dlib_get_func(yypcb->pcb_hdl,
-						       "dt_get_gvar");
-				assert(idp != NULL);
-				dt_regset_xalloc(drp, BPF_REG_0);
-				instr = BPF_CALL_FUNC(idp->di_id);
-				dt_irlist_append(dlp,
-						 dt_cg_node_alloc(DT_LBL_NONE,
-								  instr));
-				dlp->dl_last->di_extern = idp;
-				instr = BPF_ALU64_REG(BPF_MOV, dnp->dn_reg,
-						      BPF_REG_0);
-				dt_irlist_append(dlp,
-						 dt_cg_node_alloc(DT_LBL_NONE,
-								  instr));
-				dt_regset_free(drp, BPF_REG_0);
-				dt_regset_free(drp, BPF_REG_1);
-			} else if (base == 0x2000) {
-				instr = BPF_ALU64_IMM(BPF_MOV, dnp->dn_reg,
-						      dnp->dn_ident->di_id);
-				dt_irlist_append(dlp,
-						 dt_cg_node_alloc(DT_LBL_NONE,
-								  instr));
-				idp = dt_dlib_get_func(yypcb->pcb_hdl,
-						       "dt_get_tvar");
-				assert(idp != NULL);
-				instr = BPF_CALL_FUNC(idp->di_id);
-				dt_irlist_append(dlp,
-						 dt_cg_node_alloc(DT_LBL_NONE,
-								  instr));
-				dlp->dl_last->di_extern = idp;
-				instr = BPF_ALU64_REG(BPF_MOV, dnp->dn_reg,
-						      BPF_REG_0);
-				dt_irlist_append(dlp,
-						 dt_cg_node_alloc(DT_LBL_NONE,
-								  instr));
-			}
 			break;
 		}
 
diff --git a/libdtrace/dt_dis.c b/libdtrace/dt_dis.c
index 58726a91..9b272958 100644
--- a/libdtrace/dt_dis.c
+++ b/libdtrace/dt_dis.c
@@ -224,27 +224,39 @@ dt_dis_bpf_args(const dtrace_difo_t *dp, const char *fn,
 {
 	char		*s;
 
-	if (strcmp(fn, "dt_get_gvar") == 0 ||
-	    strcmp(fn, "dt_set_gvar") == 0) {
+	if (strcmp(fn, "dt_get_bvar") == 0) {
 		/*
 		 * We know that the previous instruction exists and assigns
 		 * the variable id to %r1 (because we wrote the code generator
-		 * to emit these instructions in this exact order.
+		 * to emit these instructions in this exact order.)
 		 */
 		in--;
 		snprintf(buf, len, "%s",
 			 dt_dis_varname(dp, in->imm, DIFV_SCOPE_GLOBAL));
 		return buf;
+	} else if (strcmp(fn, "dt_get_gvar") == 0 ||
+		   strcmp(fn, "dt_set_gvar") == 0) {
+		/*
+		 * We know that the previous instruction exists and assigns
+		 * the variable id to %r1 (because we wrote the code generator
+		 * to emit these instructions in this exact order.)
+		 */
+		in--;
+		snprintf(buf, len, "%s",
+			 dt_dis_varname(dp, in->imm + DIF_VAR_OTHER_UBASE,
+					DIFV_SCOPE_GLOBAL));
+		return buf;
 	} else if (strcmp(fn, "dt_get_tvar") == 0 ||
 		   strcmp(fn, "dt_set_tvar") == 0 ) {
 		/*
 		 * We know that the previous instruction exists and assigns
 		 * the variable id to %r1 (because we wrote the code generator
-		 * to emit these instructions in this exact order.
+		 * to emit these instructions in this exact order.)
 		 */
 		in--;
 		snprintf(buf, len, "self->%s",
-			 dt_dis_varname(dp, in->imm, DIFV_SCOPE_THREAD));
+			 dt_dis_varname(dp, in->imm + DIF_VAR_OTHER_UBASE,
+					DIFV_SCOPE_THREAD));
 		return buf;
 	} else if (strcmp(fn, "dt_get_string") == 0) {
 		/*
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index 4f1aeaa2..1fd0f0a8 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -51,6 +51,7 @@ static const dt_ident_t	dt_bpf_symbols[] = {
 	DT_BPF_SYMBOL(dt_predicate, DT_IDENT_FUNC),
 	DT_BPF_SYMBOL(dt_program, DT_IDENT_FUNC),
 	/* BPF library (external) functions */
+	DT_BPF_SYMBOL(dt_get_bvar, DT_IDENT_SYMBOL),
 	DT_BPF_SYMBOL(dt_get_gvar, DT_IDENT_SYMBOL),
 	DT_BPF_SYMBOL(dt_get_string, DT_IDENT_SYMBOL),
 	DT_BPF_SYMBOL(dt_get_tvar, DT_IDENT_SYMBOL),
-- 
2.25.0




More information about the DTrace-devel mailing list