[DTrace-devel] [PATCH 4/4] Make sure assignment expressions work correctly with tstrings

Eugene Loh eugene.loh at oracle.com
Mon Nov 1 19:33:01 UTC 2021


Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
with minor comments.

On 10/30/21 1:41 AM, Kris Van Hees wrote:
> The node kinds that can hold a tstring has been expanded from just
> DT_NOT_DUNC to DT_NODE_OP1, DT_NODE_OP2, DT_NODE_OP3, DT_NODE_DEXPR.

s/DT_NOT_DUNC/DT_NODE_FUNC/

> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index ddc4c0d7..0196b114 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -2303,8 +2310,13 @@ dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
>   	}
>   }
>   
> +/*
> + * dnp = node of the assignment
> + *   dn_left = identifier node for the destination (idp = identifier)
> + *   dn_right = value to store
> + */
>   static void
> -dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
> +dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
>   		dt_ident_t *idp)
>   {
>   	uint_t	varid;
> @@ -2327,7 +2339,7 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
>   			emit(dlp, BPF_LOAD(BPF_DW, reg, reg, DCTX_GVARS));
>   
>   		/* store by value or by reference */
> -		if (src->dn_flags & DT_NF_REF) {
> +		if (dnp->dn_flags & DT_NF_REF) {
>   			size_t		srcsz;
>   
>   			emit(dlp, BPF_ALU64_IMM(BPF_ADD, reg, idp->di_offset));
> @@ -2337,23 +2349,22 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
>   			 * the lesser of the size of the identifier and the
>   			 * size of the data being copied in.
>   			 */
> -			srcsz = dt_node_type_size(src->dn_right);
> -			if (dt_node_is_string(src))
> +			srcsz = dt_node_type_size(dnp->dn_right);
> +			if (dt_node_is_string(dnp))
>   				srcsz += DT_STRLEN_BYTES;
>   			size = MIN(srcsz, idp->di_size);
>   
> -			dt_cg_memcpy(dlp, drp, reg, src->dn_reg, size);
> +			dt_cg_memcpy(dlp, drp, reg, dnp->dn_reg, size);
>   		} else {
>   			size = idp->di_size;
>   
>   			assert(size > 0 && size <= 8 &&
>   			       (size & (size - 1)) == 0);
>   
> -			emit(dlp, BPF_STORE(ldstw[size], reg, idp->di_offset, src->dn_reg));
> +			emit(dlp, BPF_STORE(ldstw[size], reg, idp->di_offset, dnp->dn_reg));
>   		}
>   
>   		dt_regset_free(drp, reg);
> -		dt_cg_tstring_free(yypcb, src);
>   		return;
>   	}

Did you also want s/srcsz/dnpsz/?  (Of course "it does not matter.")

> @@ -2370,7 +2381,7 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp,
>   	 * the disassembler expects this sequence in support for annotating
>   	 * the disassembly with variables names.
>   	 */
> -	emit(dlp,  BPF_MOV_REG(BPF_REG_2, src->dn_reg));
> +	emit(dlp,  BPF_MOV_REG(BPF_REG_2, dnp->dn_reg));
>   	emit(dlp,  BPF_MOV_IMM(BPF_REG_1, varid));
>   	dt_regset_xalloc(drp, BPF_REG_0);
>   	emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
> @@ -2830,6 +2841,35 @@ dt_cg_ternary_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>   
>   	emitl(dlp, lbl_post,
>   		   BPF_NOP());
> +
> +	/*
> +	 * Strings complicate things a bit because dn_left and dn_right might
> +	 * actually be temporary strings (tstring) *and* in different slots.
> +	 * We need to allocate a new tstring to hold the result, and copy the
> +	 * value into the new tstring (and free any tstrings in dn_left and
> +	 * dn_right).
> +	 */
> +	if (dt_node_is_string(dnp)) {
> +		/*
> +		 * At this point, dnp->dn_reg holds a pointer to the string we
> +		 * need to copy.  But we want to copy it into a tstring which
> +		 * location is to be stored in dnp->dn_reg.  So, we need to
> +		 * shuffle things a bit.
> +		 */
> +		emit(dlp,  BPF_MOV_REG(BPF_REG_0, dnp->dn_reg));
> +		dt_cg_tstring_alloc(yypcb, dnp);
> +
> +		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_MEM));
> +		emit(dlp,  BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, dnp->dn_tstring->dn_value));
> +
> +		dt_cg_memcpy(dlp, drp, dnp->dn_reg, BPF_REG_0,
> +			     DT_STRLEN_BYTES +
> +			     yypcb->pcb_hdl->dt_options[DTRACEOPT_STRSIZE]);
> +
> +		dt_cg_tstring_free(yypcb, dnp->dn_left);
> +		dt_cg_tstring_free(yypcb, dnp->dn_right);
> +	}
>   }

Would it not be safer to allocate a register than to hardwire %r0?

Should the memcpy not include an extra byte for the NULL terminator?

> diff --git a/test/unittest/codegen/tst.tstring_asgn_expr.d b/test/unittest/codegen/tst.tstring_asgn_expr.d
> new file mode 100644
> index 00000000..6b0d7d73
> --- /dev/null
> +++ b/test/unittest/codegen/tst.tstring_asgn_expr.d
> @@ -0,0 +1,29 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * DESC
> + */

DESC?

> diff --git a/test/unittest/codegen/tst.tstring_ternary.d b/test/unittest/codegen/tst.tstring_ternary.d
> new file mode 100644
> index 00000000..c59d8c2e
> --- /dev/null
> +++ b/test/unittest/codegen/tst.tstring_ternary.d
> @@ -0,0 +1,28 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * DESC
> + */
DESC?



More information about the DTrace-devel mailing list