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

Eugene Loh eugene.loh at oracle.com
Mon Nov 1 21:39:30 UTC 2021


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:

# 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.



More information about the DTrace-devel mailing list