[DTrace-devel] [PATCH v3] Add support for array/struct/union to trace()

Eugene Loh eugene.loh at oracle.com
Tue Feb 1 18:50:28 UTC 2022


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

But were you going to change the clp2() comment beyond "range 1-8" since 
clp2() makes the effort to be more applicable than that limited range?  
In any case, the clp2() code movement should be eliminated entirely 
since it isn't necessary at all any more with the align=2 approach.

Is the output in tst.array.r stable?  Or are only the first 7 bytes 
("dtrace\0") stable?  The current tst.array.r might work for a broad 
range of cases, but strictly speaking it probably ought to be fixed.  
E.g., maybe add some .r.p file that does
sed 's/ 0: 64 74 72 61 63 65 00 .*  dtrace\..*/ 0: 64 74 72 61 63 65 00 
00 00 00 00 00 00 00 00 00  dtrace........../'

The additional tst.struct<n>.d tests are nice, but we often try to name 
tests more meaningfully.  That would be easy enough to do here.  E.g. 
tst.struct-int8.d and so on.

On 2/1/22 12:32 AM, Kris Van Hees via DTrace-devel wrote:
> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> ---
>   libdtrace/dt_cg.c                         | 73 +++++++++++++++--------
>   test/unittest/actions/trace/tst.array.d   | 18 ++++++
>   test/unittest/actions/trace/tst.array.r   |  8 +++
>   test/unittest/actions/trace/tst.struct.d  | 27 +++++++++
>   test/unittest/actions/trace/tst.struct.r  |  8 +++
>   test/unittest/actions/trace/tst.struct2.d | 23 +++++++
>   test/unittest/actions/trace/tst.struct2.r |  8 +++
>   test/unittest/actions/trace/tst.struct3.d | 23 +++++++
>   test/unittest/actions/trace/tst.struct3.r |  8 +++
>   test/unittest/actions/trace/tst.struct4.d | 23 +++++++
>   test/unittest/actions/trace/tst.struct4.r |  8 +++
>   test/unittest/actions/trace/tst.struct5.d | 23 +++++++
>   test/unittest/actions/trace/tst.struct5.r |  8 +++
>   test/unittest/actions/trace/tst.union.d   | 25 ++++++++
>   test/unittest/actions/trace/tst.union.r   |  8 +++
>   15 files changed, 267 insertions(+), 24 deletions(-)
>   create mode 100644 test/unittest/actions/trace/tst.array.d
>   create mode 100644 test/unittest/actions/trace/tst.array.r
>   create mode 100644 test/unittest/actions/trace/tst.struct.d
>   create mode 100644 test/unittest/actions/trace/tst.struct.r
>   create mode 100644 test/unittest/actions/trace/tst.struct2.d
>   create mode 100644 test/unittest/actions/trace/tst.struct2.r
>   create mode 100644 test/unittest/actions/trace/tst.struct3.d
>   create mode 100644 test/unittest/actions/trace/tst.struct3.r
>   create mode 100644 test/unittest/actions/trace/tst.struct4.d
>   create mode 100644 test/unittest/actions/trace/tst.struct4.r
>   create mode 100644 test/unittest/actions/trace/tst.struct5.d
>   create mode 100644 test/unittest/actions/trace/tst.struct5.r
>   create mode 100644 test/unittest/actions/trace/tst.union.d
>   create mode 100644 test/unittest/actions/trace/tst.union.r
>
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index c8421109..fcf96429 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -1,6 +1,6 @@
>   /*
>    * Oracle Linux DTrace.
> - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2005, 2022, 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.
>    */
> @@ -905,6 +905,25 @@ static const uint_t	ldstw[] = {
>   					0,	0,	0, BPF_DW,
>   				};
>   
> +/*
> + * When loading bit-fields, we want to convert a byte count in the range
> + * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc).  The clp2() function
> + * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
> + */
> +static size_t
> +clp2(size_t x)
> +{
> +	x--;
> +
> +	x |= (x >> 1);
> +	x |= (x >> 2);
> +	x |= (x >> 4);
> +	x |= (x >> 8);
> +	x |= (x >> 16);
> +
> +	return x + 1;
> +}
> +
>   static int
>   dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
>   		dt_pfargv_t *pfp, int arg)
> @@ -1002,6 +1021,31 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
>   		return 0;
>   	}
>   
> +	/* Handle tracing of by-ref values (arrays, struct, union). */
> +	if (kind == DTRACEACT_DIFEXPR && (arg & DT_NF_REF)) {
> +		off = dt_rec_add(dtp, dt_cg_fill_gap, kind, size, 2, pfp, arg);
> +
> +		TRACE_REGSET("store_val(): Begin ");
> +		dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
> +
> +		if (dt_regset_xalloc_args(drp) == -1)
> +			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +
> +		emit(dlp, BPF_MOV_REG(BPF_REG_1, BPF_REG_9));
> +		emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, off));
> +		emit(dlp, BPF_MOV_IMM(BPF_REG_2, size));
> +		emit(dlp, BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
> +		dt_regset_free(drp, dnp->dn_reg);
> +		dt_regset_xalloc(drp, BPF_REG_0);
> +		emit(dlp, BPF_CALL_HELPER(BPF_FUNC_probe_read));
> +		dt_regset_free_args(drp);
> +
> +		dt_regset_free(drp, BPF_REG_0);
> +		TRACE_REGSET("store_val(): End   ");
> +
> +		return 0;
> +	}
> +
>   	return -1;
>   }
>   
> @@ -1669,7 +1713,7 @@ dt_cg_act_trace(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
>   {
>   	char		n[DT_TYPE_NAMELEN];
>   	dt_node_t	*arg = dnp->dn_args;
> -	int		type = 0;
> +	int		flags = 0;
>   
>   	if (dt_node_is_void(arg))
>   		dnerror(arg, D_TRACE_VOID,
> @@ -1681,11 +1725,11 @@ dt_cg_act_trace(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
>   			"expression\n");
>   
>   	if (arg->dn_flags & DT_NF_REF)
> -		type = DT_NF_REF;
> +		flags = DT_NF_REF;
>   	else if (arg->dn_flags & DT_NF_SIGNED)
> -		type = DT_NF_SIGNED;
> +		flags = DT_NF_SIGNED;
>   
> -	if (dt_cg_store_val(pcb, arg, DTRACEACT_DIFEXPR, NULL, type) == -1)
> +	if (dt_cg_store_val(pcb, arg, DTRACEACT_DIFEXPR, NULL, flags) == -1)
>   		dnerror(arg, D_PROTO_ARG,
>   			"trace( ) argument #1 is incompatible with prototype:\n"
>   			"\tprototype: scalar or string\n\t argument: %s\n",
> @@ -1934,25 +1978,6 @@ dt_cg_setx(dt_irlist_t *dlp, int reg, uint64_t x)
>   	dt_cg_xsetx(dlp, NULL, DT_LBL_NONE, reg, x);
>   }
>   
> -/*
> - * When loading bit-fields, we want to convert a byte count in the range
> - * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc).  The clp2() function
> - * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
> - */
> -static size_t
> -clp2(size_t x)
> -{
> -	x--;
> -
> -	x |= (x >> 1);
> -	x |= (x >> 2);
> -	x |= (x >> 4);
> -	x |= (x >> 8);
> -	x |= (x >> 16);
> -
> -	return x + 1;
> -}
> -
>   /*
>    * Lookup the correct load opcode to use for the specified node and CTF type.
>    * We determine the size and convert it to a 3-bit index.  Our lookup table
> diff --git a/test/unittest/actions/trace/tst.array.d b/test/unittest/actions/trace/tst.array.d
> new file mode 100644
> index 00000000..104d42e1
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.array.d
> @@ -0,0 +1,18 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, 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.
> + */
> +
> +/*
> + * ASSERTION: The trace() action prints an array correctly.
> + *
> + * SECTION: Actions and Subroutines/trace()
> + */
> +
> +BEGIN
> +{
> +	trace(curthread->comm);
> +	exit(0);
> +}
> diff --git a/test/unittest/actions/trace/tst.array.r b/test/unittest/actions/trace/tst.array.r
> new file mode 100644
> index 00000000..872f16f6
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.array.r
> @@ -0,0 +1,8 @@
> +                   FUNCTION:NAME
> +                          :BEGIN
> +             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
> +         0: 64 74 72 61 63 65 00 00 73 68 00 00 00 00 00 00  dtrace..sh......
> +
> +
> +-- @@stderr --
> +dtrace: script 'test/unittest/actions/trace/tst.array.d' matched 1 probe
> diff --git a/test/unittest/actions/trace/tst.struct.d b/test/unittest/actions/trace/tst.struct.d
> new file mode 100644
> index 00000000..ec60ea11
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct.d
> @@ -0,0 +1,27 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, 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.
> + */
> +
> +/*
> + * ASSERTION: The trace() action prints a struct correctly.
> + *
> + * SECTION: Actions and Subroutines/trace()
> + */
> +
> +struct {
> +	int	a;
> +	char	b;
> +	int	c;
> +} st;
> +
> +BEGIN
> +{
> +	st.a = 0x1234;
> +	st.b = 0;
> +	st.c = 0x9876;
> +	trace(st);
> +	exit(0);
> +}
> diff --git a/test/unittest/actions/trace/tst.struct.r b/test/unittest/actions/trace/tst.struct.r
> new file mode 100644
> index 00000000..0658ea88
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct.r
> @@ -0,0 +1,8 @@
> +                   FUNCTION:NAME
> +                          :BEGIN
> +             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
> +         0: 34 12 00 00 00 00 00 00 76 98 00 00              4.......v...
> +
> +
> +-- @@stderr --
> +dtrace: script 'test/unittest/actions/trace/tst.struct.d' matched 1 probe
> diff --git a/test/unittest/actions/trace/tst.struct2.d b/test/unittest/actions/trace/tst.struct2.d
> new file mode 100644
> index 00000000..36de485f
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct2.d
> @@ -0,0 +1,23 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, 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.
> + */
> +
> +/*
> + * ASSERTION: The trace() action prints a struct { int8_t } correctly.
> + *
> + * SECTION: Actions and Subroutines/trace()
> + */
> +
> +struct {
> +	int8_t	x;
> +} st;
> +
> +BEGIN
> +{
> +	st.x = 0x34;
> +	trace(st);
> +	exit(0);
> +}
> diff --git a/test/unittest/actions/trace/tst.struct2.r b/test/unittest/actions/trace/tst.struct2.r
> new file mode 100644
> index 00000000..2154b90e
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct2.r
> @@ -0,0 +1,8 @@
> +                   FUNCTION:NAME
> +                          :BEGIN
> +             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
> +         0: 34                                               4
> +
> +
> +-- @@stderr --
> +dtrace: script 'test/unittest/actions/trace/tst.struct2.d' matched 1 probe
> diff --git a/test/unittest/actions/trace/tst.struct3.d b/test/unittest/actions/trace/tst.struct3.d
> new file mode 100644
> index 00000000..642364f2
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct3.d
> @@ -0,0 +1,23 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, 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.
> + */
> +
> +/*
> + * ASSERTION: The trace() action prints a struct { int16_t } correctly.
> + *
> + * SECTION: Actions and Subroutines/trace()
> + */
> +
> +struct {
> +	int16_t	x;
> +} st;
> +
> +BEGIN
> +{
> +	st.x = 0x34;
> +	trace(st);
> +	exit(0);
> +}
> diff --git a/test/unittest/actions/trace/tst.struct3.r b/test/unittest/actions/trace/tst.struct3.r
> new file mode 100644
> index 00000000..3b8fb3b3
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct3.r
> @@ -0,0 +1,8 @@
> +                   FUNCTION:NAME
> +                          :BEGIN
> +             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
> +         0: 34 00                                            4.
> +
> +
> +-- @@stderr --
> +dtrace: script 'test/unittest/actions/trace/tst.struct3.d' matched 1 probe
> diff --git a/test/unittest/actions/trace/tst.struct4.d b/test/unittest/actions/trace/tst.struct4.d
> new file mode 100644
> index 00000000..94360d90
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct4.d
> @@ -0,0 +1,23 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, 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.
> + */
> +
> +/*
> + * ASSERTION: The trace() action prints a struct { int32_t } correctly.
> + *
> + * SECTION: Actions and Subroutines/trace()
> + */
> +
> +struct {
> +	int32_t	x;
> +} st;
> +
> +BEGIN
> +{
> +	st.x = 0x34;
> +	trace(st);
> +	exit(0);
> +}
> diff --git a/test/unittest/actions/trace/tst.struct4.r b/test/unittest/actions/trace/tst.struct4.r
> new file mode 100644
> index 00000000..90fa1a17
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct4.r
> @@ -0,0 +1,8 @@
> +                   FUNCTION:NAME
> +                          :BEGIN
> +             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
> +         0: 34 00 00 00                                      4...
> +
> +
> +-- @@stderr --
> +dtrace: script 'test/unittest/actions/trace/tst.struct4.d' matched 1 probe
> diff --git a/test/unittest/actions/trace/tst.struct5.d b/test/unittest/actions/trace/tst.struct5.d
> new file mode 100644
> index 00000000..0ecc9771
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct5.d
> @@ -0,0 +1,23 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, 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.
> + */
> +
> +/*
> + * ASSERTION: The trace() action prints a struct { int64_t } correctly.
> + *
> + * SECTION: Actions and Subroutines/trace()
> + */
> +
> +struct {
> +	int64_t	x;
> +} st;
> +
> +BEGIN
> +{
> +	st.x = 0x34;
> +	trace(st);
> +	exit(0);
> +}
> diff --git a/test/unittest/actions/trace/tst.struct5.r b/test/unittest/actions/trace/tst.struct5.r
> new file mode 100644
> index 00000000..687a0e59
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.struct5.r
> @@ -0,0 +1,8 @@
> +                   FUNCTION:NAME
> +                          :BEGIN
> +             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
> +         0: 34 00 00 00 00 00 00 00                          4.......
> +
> +
> +-- @@stderr --
> +dtrace: script 'test/unittest/actions/trace/tst.struct5.d' matched 1 probe
> diff --git a/test/unittest/actions/trace/tst.union.d b/test/unittest/actions/trace/tst.union.d
> new file mode 100644
> index 00000000..56b2ff81
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.union.d
> @@ -0,0 +1,25 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2022, 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.
> + */
> +
> +/*
> + * ASSERTION: The trace() action prints a union correctly.
> + *
> + * SECTION: Actions and Subroutines/trace()
> + */
> +
> +union {
> +	int	a;
> +	char	b[3];
> +	short	c;
> +} u;
> +
> +BEGIN
> +{
> +	u.a = 0x12345678;
> +	trace(u);
> +	exit(0);
> +}
> diff --git a/test/unittest/actions/trace/tst.union.r b/test/unittest/actions/trace/tst.union.r
> new file mode 100644
> index 00000000..48098d11
> --- /dev/null
> +++ b/test/unittest/actions/trace/tst.union.r
> @@ -0,0 +1,8 @@
> +                   FUNCTION:NAME
> +                          :BEGIN
> +             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
> +         0: 78 56 34 12                                      xV4.
> +
> +
> +-- @@stderr --
> +dtrace: script 'test/unittest/actions/trace/tst.union.d' matched 1 probe



More information about the DTrace-devel mailing list