[DTrace-devel] [PATCH] Add support for hton and ntoh subroutines

Kris Van Hees kris.van.hees at oracle.com
Wed Jul 7 08:33:59 PDT 2021


Before deliving into this...

Did you take a look at the BPF_TO_BE and BPF_TO_LE instructions that BPF
provides as part of its ALUL64 support?  From what I can see, that ought to
do most of what you are implementing here?

On Fri, Jul 02, 2021 at 12:39:59AM -0400, eugene.loh at oracle.com wrote:
> From: Eugene Loh <eugene.loh at oracle.com>
> 
> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
> ---
>  libdtrace/dt_cg.c                       | 172 +++++++++++++++++++++++-
>  test/unittest/dif/htonl.d               |   1 -
>  test/unittest/dif/htonll.d              |   1 -
>  test/unittest/dif/htons.d               |   1 -
>  test/unittest/funcs/tst.hton2.aarch64.r |   7 +
>  test/unittest/funcs/tst.hton2.d         |  28 ++++
>  test/unittest/funcs/tst.hton2.x86_64.r  |   7 +
>  7 files changed, 208 insertions(+), 9 deletions(-)
>  create mode 100644 test/unittest/funcs/tst.hton2.aarch64.r
>  create mode 100644 test/unittest/funcs/tst.hton2.d
>  create mode 100644 test/unittest/funcs/tst.hton2.x86_64.r
> 
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index 0caae10a..be3a4a96 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -3283,6 +3283,166 @@ dt_cg_subr_strlen(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  	TRACE_REGSET("    subr-strlen:End  ");
>  }
>  
> +#ifdef _BIG_ENDIAN
> +static void
> +dt_cg_subr_htons(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> +{
> +	/* keep only lowest 16 bits */
> +	dt_cg_node(dnp->dn_args, dlp, drp);
> +	dnp->dn_reg = dnp->dn_args->dn_reg;
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, dnp->dn_reg, 0xffff));
> +}
> +
> +static void
> +dt_cg_subr_htonl(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> +{
> +	/* keep only lowest 32 bits */
> +	dt_cg_node(dnp->dn_args, dlp, drp);
> +	dnp->dn_reg = dnp->dn_args->dn_reg;
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, dnp->dn_reg, 32));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, dnp->dn_reg, 32));
> +}
> +
> +static void
> +dt_cg_subr_htonll(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> +{
> +	dt_cg_node(dnp->dn_args, dlp, drp);
> +	dnp->dn_reg = dnp->dn_args->dn_reg;
> +}
> +#else
> +static void
> +dt_cg_subr_htons(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> +{
> +	int dst, src, tmp;
> +
> +	dt_cg_node(dnp->dn_args, dlp, drp);
> +	src = dnp->dn_args->dn_reg;
> +	dst = dt_regset_alloc(drp);
> +	tmp = dt_regset_alloc(drp);
> +	if (dst == -1 || tmp == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +
> +	/* move bits 8-15 to bits 0-7 */
> +	emit(dlp, BPF_MOV_REG(dst, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, dst, 48));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, dst, 56));
> +
> +	/* add bits 0-7 at bits 8-15 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, tmp, 56));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, tmp, 48));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	dnp->dn_reg = dst;
> +	dt_regset_free(drp, tmp);
> +	dt_regset_free(drp, src);
> +}
> +
> +static void
> +dt_cg_subr_htonl(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> +{
> +	int dst, src, tmp;
> +
> +	dt_cg_node(dnp->dn_args, dlp, drp);
> +	src = dnp->dn_args->dn_reg;
> +	dst = dt_regset_alloc(drp);
> +	tmp = dt_regset_alloc(drp);
> +	if (dst == -1 || tmp == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +
> +	/* move bits 24-31 to bits 0-7 */
> +	emit(dlp, BPF_MOV_REG(dst, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, dst, 24));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, dst, 0xff));
> +
> +	/* add bits 16-23 at bits 8-15 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, tmp,  8));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, tmp, 0xff00));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	/* add bits 8-15 at bits 16-23 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, tmp, 0xff00));
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, tmp,  8));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	/* add bits 0-7 at bits 24-31 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, tmp, 0xff));
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, tmp, 24));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	dnp->dn_reg = dst;
> +	dt_regset_free(drp, tmp);
> +	dt_regset_free(drp, src);
> +}
> +
> +static void
> +dt_cg_subr_htonll(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> +{
> +	int dst, src, tmp;
> +
> +	dt_cg_node(dnp->dn_args, dlp, drp);
> +	src = dnp->dn_args->dn_reg;
> +	dst = dt_regset_alloc(drp);
> +	tmp = dt_regset_alloc(drp);
> +	if (dst == -1 || tmp == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +
> +	/* move bits 56-63 to bits 0-7 */
> +	emit(dlp, BPF_MOV_REG(dst, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, dst, 56));
> +
> +	/* add bits 48-55 at bits 8-15 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, tmp, 40));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, tmp, 0xff00));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	/* add bits 40-47 at bits 16-23 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, tmp, 24));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, tmp, 0xff0000));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	/* add bits 32-39 at bits 24-31 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, tmp, 16));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, tmp, 0xff0000));
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, tmp,  8));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	/* add bits 24-31 at bits 32-39 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_RSH, tmp,  8));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, tmp, 0xff0000));
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, tmp, 16));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	/* add bits 16-23 at bits 40-47 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, tmp, 0xff0000));
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, tmp, 24));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	/* add bits 8-15 at bits 48-55 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_AND, tmp, 0xff00));
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, tmp, 40));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	/* add bits 0-7 at bits 56-63 */
> +	emit(dlp, BPF_MOV_REG(tmp, src));
> +	emit(dlp, BPF_ALU64_IMM(BPF_LSH, tmp, 56));
> +	emit(dlp, BPF_ALU64_REG(BPF_ADD, dst, tmp));
> +
> +	dnp->dn_reg = dst;
> +	dt_regset_free(drp, tmp);
> +	dt_regset_free(drp, src);
> +}
> +#endif
> +
>  typedef void dt_cg_subr_f(dt_node_t *, dt_irlist_t *, dt_regset_t *);
>  
>  static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
> @@ -3321,12 +3481,12 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
>  	[DIF_SUBR_SUBSTR]		= NULL,
>  	[DIF_SUBR_INDEX]		= &dt_cg_subr_index,
>  	[DIF_SUBR_RINDEX]		= NULL,
> -	[DIF_SUBR_HTONS]		= NULL,
> -	[DIF_SUBR_HTONL]		= NULL,
> -	[DIF_SUBR_HTONLL]		= NULL,
> -	[DIF_SUBR_NTOHS]		= NULL,
> -	[DIF_SUBR_NTOHL]		= NULL,
> -	[DIF_SUBR_NTOHLL]		= NULL,
> +	[DIF_SUBR_HTONS]		= &dt_cg_subr_htons,
> +	[DIF_SUBR_HTONL]		= &dt_cg_subr_htonl,
> +	[DIF_SUBR_HTONLL]		= &dt_cg_subr_htonll,
> +	[DIF_SUBR_NTOHS]		= &dt_cg_subr_htons,
> +	[DIF_SUBR_NTOHL]		= &dt_cg_subr_htonl,
> +	[DIF_SUBR_NTOHLL]		= &dt_cg_subr_htonll,
>  	[DIF_SUBR_INET_NTOP]		= NULL,
>  	[DIF_SUBR_INET_NTOA]		= NULL,
>  	[DIF_SUBR_INET_NTOA6]		= NULL,
> diff --git a/test/unittest/dif/htonl.d b/test/unittest/dif/htonl.d
> index 142fccd0..410bc135 100644
> --- a/test/unittest/dif/htonl.d
> +++ b/test/unittest/dif/htonl.d
> @@ -1,5 +1,4 @@
>  /* @@runtest-opts: -C */
> -/* @@xfail: dtv2 */
>  
>  #include <endian.h>
>  
> diff --git a/test/unittest/dif/htonll.d b/test/unittest/dif/htonll.d
> index 5705b462..79828736 100644
> --- a/test/unittest/dif/htonll.d
> +++ b/test/unittest/dif/htonll.d
> @@ -1,5 +1,4 @@
>  /* @@runtest-opts: -C */
> -/* @@xfail: dtv2 */
>  
>  #include <endian.h>
>  
> diff --git a/test/unittest/dif/htons.d b/test/unittest/dif/htons.d
> index ad09f324..97a4534c 100644
> --- a/test/unittest/dif/htons.d
> +++ b/test/unittest/dif/htons.d
> @@ -1,5 +1,4 @@
>  /* @@runtest-opts: -C */
> -/* @@xfail: dtv2 */
>  
>  #include <endian.h>
>  
> diff --git a/test/unittest/funcs/tst.hton2.aarch64.r b/test/unittest/funcs/tst.hton2.aarch64.r
> new file mode 100644
> index 00000000..5ca2adb8
> --- /dev/null
> +++ b/test/unittest/funcs/tst.hton2.aarch64.r
> @@ -0,0 +1,7 @@
> +f0de
> +f0debc9a
> +f0debc9a78563412
> +f0de
> +f0debc9a
> +f0debc9a78563412
> +
> diff --git a/test/unittest/funcs/tst.hton2.d b/test/unittest/funcs/tst.hton2.d
> new file mode 100644
> index 00000000..a1a506ac
> --- /dev/null
> +++ b/test/unittest/funcs/tst.hton2.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.
> + */
> +
> +/*
> + * ASSERTION: Test network byte-ordering routines.
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	printf("%x\n", htons (0x123456789abcdef0ll));
> +	printf("%x\n", htonl (0x123456789abcdef0ll));
> +	printf("%x\n", htonll(0x123456789abcdef0ll));
> +	printf("%x\n", ntohs (0x123456789abcdef0ll));
> +	printf("%x\n", ntohl (0x123456789abcdef0ll));
> +	printf("%x\n", ntohll(0x123456789abcdef0ll));
> +	exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> diff --git a/test/unittest/funcs/tst.hton2.x86_64.r b/test/unittest/funcs/tst.hton2.x86_64.r
> new file mode 100644
> index 00000000..5ca2adb8
> --- /dev/null
> +++ b/test/unittest/funcs/tst.hton2.x86_64.r
> @@ -0,0 +1,7 @@
> +f0de
> +f0debc9a
> +f0debc9a78563412
> +f0de
> +f0debc9a
> +f0debc9a78563412
> +
> -- 
> 2.18.4
> 
> 
> _______________________________________________
> 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