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

Kris Van Hees kris.van.hees at oracle.com
Tue Nov 2 00:46:25 UTC 2021


On Mon, Nov 01, 2021 at 05:39:30PM -0400, Eugene Loh wrote:
> On 11/1/21 4:32 PM, Kris Van Hees wrote:
> 
> > On Mon, Nov 01, 2021 at 03:33:01PM -0400, Eugene Loh wrote:
> >>> @@ -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);
> >>> +	}
> >>>    }
> >> Should the memcpy not include an extra byte for the NULL terminator?
> > Excellent question!  The answer here is 'no' mainly because we don't do that in
> > other places either but whether that is the perfect behaviour or not is a bit
> > unclear.  The documentation states:
> >
> >    In DTrace, strings are represented as an array of characters terminated by a
> >    null byte (that is, a byte whose value is zero, usually written as '\0').
> >    The visible part of the string is of variable length, depending on the
> >    location of the null byte, but DTrace stores each string in a fixed-size
> >    array so that each probe traces a consistent amount of data. Strings cannot
> >    exceed the length of the predefined string limit. However, the limit can be
> >    modified in your D program or on the dtrace command line by tuning the
> >    strsize option.
> >
> > The terminology shifts a bit near the end of the paragraph when we go from
> > a "fixed-size array" and "consistent amount of data" to "string limit".  The
> > implementation seems to be a bit inconsistent on what the interpretation ought
> > to be.  Whether the setting of strsize is meant to be the limit on the
> > "consistent amount of data" or whether it is that value - 1 to account for
> > the null byte is not clear.
> 
> Okay, but to be clear, regardless of whether we make space for that NULL 
> char internally, we do expect that strsize should be the cap on the 
> number of visible chars, right?  E.g., if Solaris is the reference 
> implementation:

Well, yes, of course.  But since that is not the case right now in other parts
of the code (surely a bug) it makes sense to at least be consistent right now.
This needs a patch that fixes it everywhere.

It is even more fun when you look at the original code base because it is
really unclear whether the current behaviour is intended or a side effect of
the implementation (without actual intent).

> # uname -r
> 5.11
> # /usr/sbin/dtrace -xstrsize=8 -n 'BEGIN { x = "123456789"; 
> printf("|%s|\n", x); exit(0) }'
> dtrace: description 'BEGIN ' matched 1 probe
>   CPU     ID                    FUNCTION:NAME
>    62      1                           :BEGIN |12345678|
> 
> # /usr/sbin/dtrace -xstrsize=7 -n 'BEGIN { x = "123456789"; 
> printf("|%s|\n", x); exit(0) }'
> dtrace: description 'BEGIN ' matched 1 probe
>   CPU     ID                    FUNCTION:NAME
>    62      1                           :BEGIN |1234567|
> 
> # /usr/sbin/dtrace -n 'BEGIN {
>      x = " 123456";
>      printf("%d |%s| |%s|\n", strlen(x), substr(x, 250), x);
>      exit(0);
> }'
> dtrace: description 'BEGIN ' matched 1 probe
>   CPU     ID                    FUNCTION:NAME
>    12      1                           :BEGIN 256 |123456| | 123456|
> 
> That is, 7 chars are visible with strsize=7, 8 with strsize=8, and 256 
> by default.
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list