[DTrace-devel] [PATCH v2 3/3] Add support for inet_ntoa() subroutine

Kris Van Hees kris.van.hees at oracle.com
Fri Apr 22 06:32:07 UTC 2022


On Fri, Mar 18, 2022 at 03:36:44PM -0400, eugene.loh--- via DTrace-devel wrote:
> From: Eugene Loh <eugene.loh at oracle.com>
> 
> For the time being, there is no definition of ipaddr_t, which
> traditionally has been defined in the kernel portion of DTrace.  So
> for now, the prototype for the subroutine is not string(ipaddr_t*)
> but string(void*) and the test defines ipaddr_t itself.
> 
> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>

Reviewed-by: Kris Van Hees <kris.van.hees at oracle.com>

... and added to dev

> ---
>  bpf/Build                           |   3 +-
>  bpf/inet_ntoa.S                     | 220 ++++++++++++++++++++++++++++
>  libdtrace/dt_cg.c                   |   8 +-
>  libdtrace/dt_open.c                 |   2 +-
>  test/unittest/funcs/tst.inet_ntoa.d |   5 +-
>  5 files changed, 233 insertions(+), 5 deletions(-)
>  create mode 100644 bpf/inet_ntoa.S
> 
> diff --git a/bpf/Build b/bpf/Build
> index d2c19857..43f4b638 100644
> --- a/bpf/Build
> +++ b/bpf/Build
> @@ -1,5 +1,5 @@
>  # Oracle Linux DTrace.
> -# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
> +# Copyright (c) 2020, 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.
>  
> @@ -28,6 +28,7 @@ bpf_dlib_SOURCES = \
>  	get_bvar.c \
>  	get_tvar.c \
>  	index.S \
> +	inet_ntoa.S \
>  	lltostr.S \
>  	mutex_owned.S \
>  	mutex_owner.S \
> diff --git a/bpf/inet_ntoa.S b/bpf/inet_ntoa.S
> new file mode 100644
> index 00000000..f8a3f112
> --- /dev/null
> +++ b/bpf/inet_ntoa.S
> @@ -0,0 +1,220 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
> + */
> +
> +	.text
> +
> +/*
> + * // This helper writes a uint8 as a string.
> + * // The output buffer is dst[STRSZ] and we start writing at &dst[off].
> + *
> + * uint64_t dt_inet_ntoa_write_uint8(uint64_t inp, char *dst, uint64_t off) {
> + *     uint64_t dig, nzr, len;
> + *
> + *     nzr = 0;         // nonzero if any nonzero digits have been written
> + *     len = STRSZ;
> + *     inp &= 0xff;
> + *
> + *     // write 100s digit
> + *     if (off >= len) return off;
> + *     dig = inp / 100;
> + *     nzr += dig;
> + *     dst[off] = '0' + dig;
> + *     if (nzr != 0) off++;
> + *
> + *     // write 10s digit
> + *     if (off >= len) return off;
> + *     inp -= 100 * dig;
> + *     dig = inp / 10;
> + *     nzr += dig;
> + *     dst[off] = '0' + dig;
> + *     if (nzr != 0) off++;
> + *
> + *     // write 1s digit
> + *     if (off >= len) return off;
> + *     inp -= 10 * dig;
> + *     dst[off] = '0' + inp;
> + *     off++;
> + *
> + *     return off;
> + * }
> + *
> + */
> +
> +	.align	4
> +	.global	dt_inet_ntoa_write_uint8
> +	.type	dt_inet_ntoa_write_uint8, @function
> +dt_inet_ntoa_write_uint8:
> +
> +#define OFF %r0
> +#define INP %r1
> +#define DST %r2
> +#define DIG %r5
> +#define NZR %r6
> +#define LEN %r7
> +#define CHR %r8
> +#define PTR %r9
> +	mov	OFF, %r3
> +
> +	mov	NZR, 0
> +	lddw	LEN, STRSZ
> +	and	INP, 0xff
> +
> +	/* write 100s digit */
> +	jlt	OFF, LEN, 1
> +	exit
> +	mov	DIG, INP
> +	div	DIG, 100
> +	add	NZR, DIG
> +	mov	CHR, DIG
> +	add	CHR, '0'
> +	mov	PTR, DST
> +	add	PTR, OFF
> +	stxb	[PTR+0], CHR
> +	jeq	NZR, 0, 1
> +	add	OFF, 1
> +
> +	/* write 10s digit */
> +	jlt	OFF, LEN, 1
> +	exit
> +	mul	DIG, 100
> +	sub	INP, DIG
> +	mov	DIG, INP
> +	div	DIG, 10
> +	add	NZR, DIG
> +	mov	CHR, DIG
> +	add	CHR, '0'
> +	mov	PTR, DST
> +	add	PTR, OFF
> +	stxb	[PTR+0], CHR
> +	jeq	NZR, 0, 1
> +	add	OFF, 1
> +
> +	/* write 1s digit */
> +	jlt	OFF, LEN, 1
> +	exit
> +	mul	DIG, 10
> +	sub	INP, DIG
> +	add	INP, '0'
> +	add	DST, OFF
> +	stxb	[DST+0], INP
> +	add	OFF, 1
> +	exit
> +	.size	dt_inet_ntoa_write_uint8, .-dt_inet_ntoa_write_uint8
> +#undef OFF
> +#undef INP
> +#undef DST
> +#undef DIG
> +#undef NZR
> +#undef LEN
> +#undef CHR
> +#undef PTR
> +
> +/*
> + * void dt_inet_ntoa(uint8_t *src, char *dst) {
> + *     uint64_t off, inp, len;
> + *
> + *     off = 0
> + *     len = STRSZ;
> + *
> + *     inp = src[0];
> + *     off = dt_inet_ntoa_write_uint8(inp, dst, off);
> + *     if (off >= STRSZ) goto done:
> + *     dst[off++] = ':';
> + *
> + *     inp = src[1];
> + *     off = dt_inet_ntoa_write_uint8(inp, dst, off);
> + *     if (off >= STRSZ) goto done:
> + *     dst[off++] = ':';
> + *
> + *     inp = src[2];
> + *     off = dt_inet_ntoa_write_uint8(inp, dst, off);
> + *     if (off >= STRSZ) goto done:
> + *     dst[off++] = ':';
> + *
> + *     inp = src[3];
> + *     off = dt_inet_ntoa_write_uint8(inp, dst, off);
> + *
> + *     done:
> + *     dst[off] = '\0';
> + * }
> + *
> + */
> +	.align	4
> +	.global	dt_inet_ntoa
> +	.type	dt_inet_ntoa, @function
> +dt_inet_ntoa:
> +
> +/* off cycles between %r3 (input arg to subroutine) and %r0 (its return) */
> +#define INP %r1
> +#define SRC %r6
> +#define DST %r7
> +#define LEN %r8
> +
> +	mov	SRC, %r1
> +	mov	DST, %r2
> +
> +#if 1
> +#define BPF_FUNC_probe_read	4
> +	/*
> +	 * FIXME: copy src data over
> +	 *
> +	 * Currently, the code generator's handling of DT_CG_ALLOCA_NULLPTR
> +	 * is such that there are scenarios where the BPF verifier thinks an
> +	 * unsuitable value is being passed in as the "src" argument.  Until
> +	 * this is fixed, simply use bpf_probe_read() to copy the src data
> +	 * onto the BPF stack.  Reset the src argument to point to that
> +	 * stack location.
> +	 */
> +	mov	%r3, %r1
> +	mov	%r2, 4
> +	mov	SRC, %fp
> +	add	SRC, -4
> +	mov	%r1, SRC
> +	call	BPF_FUNC_probe_read
> +#endif
> +
> +	mov	%r3, 0
> +	lddw	LEN, STRSZ
> +
> +	ldxb	INP, [SRC+0]
> +	mov	%r2, DST
> +	call	dt_inet_ntoa_write_uint8
> +	jge	%r0, LEN, .Ldone
> +	mov	%r3, %r0
> +	add	%r3, 1
> +	add	%r0, DST
> +	stb	[%r0+0], '.'
> +
> +	ldxb	INP, [SRC+1]
> +	mov	%r2, DST
> +	call	dt_inet_ntoa_write_uint8
> +	jge	%r0, LEN, .Ldone
> +	mov	%r3, %r0
> +	add	%r3, 1
> +	add	%r0, DST
> +	stb	[%r0+0], '.'
> +
> +	ldxb	INP, [SRC+2]
> +	mov	%r2, DST
> +	call	dt_inet_ntoa_write_uint8
> +	jge	%r0, LEN, .Ldone
> +	mov	%r3, %r0
> +	add	%r3, 1
> +	add	%r0, DST
> +	stb	[%r0+0], '.'
> +
> +	ldxb	INP, [SRC+3]
> +	mov	%r2, DST
> +	call	dt_inet_ntoa_write_uint8
> +
> +.Ldone:
> +	add	DST, %r0
> +	stb	[DST+0], 0
> +	exit
> +	.size	dt_inet_ntoa, .-dt_inet_ntoa
> +#undef INP
> +#undef SRC
> +#undef DST
> +#undef LEN
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index 9bda35f3..88e0ed2b 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -4186,6 +4186,12 @@ dt_cg_subr_htonll(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  	emit(dlp, BPF_END_REG(BPF_DW, dnp->dn_reg, BPF_TO_BE));
>  }
>  
> +static void
> +dt_cg_subr_inet_ntoa(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> +{
> +	dt_cg_subr_tstring1_helper(dnp, dlp, drp, "dt_inet_ntoa");
> +}
> +
>  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] = {
> @@ -4231,7 +4237,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
>  	[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_NTOA]		= &dt_cg_subr_inet_ntoa,
>  	[DIF_SUBR_INET_NTOA6]		= NULL,
>  	[DIF_SUBR_D_PATH]		= NULL,
>  	[DIF_SUBR_LINK_NTOP]		= NULL,
> diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
> index 5bdc6037..1dcc5c7a 100644
> --- a/libdtrace/dt_open.c
> +++ b/libdtrace/dt_open.c
> @@ -192,7 +192,7 @@ static const dt_ident_t _dtrace_globals[] = {
>  { "index", DT_IDENT_FUNC, 0, DIF_SUBR_INDEX, DT_ATTR_STABCMN, DT_VERS_1_1,
>  	&dt_idops_func, "int(const char *, const char *, [int])" },
>  { "inet_ntoa", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOA, DT_ATTR_STABCMN,
> -	DT_VERS_1_5, &dt_idops_func, "string(ipaddr_t *)" },
> +	DT_VERS_1_5, &dt_idops_func, "string(void *)" }, /* FIXME should be ipaddr_t* */
>  { "inet_ntoa6", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOA6, DT_ATTR_STABCMN,
>  	DT_VERS_1_5, &dt_idops_func, "string(struct in6_addr *)" },
>  { "inet_ntop", DT_IDENT_FUNC, 0, DIF_SUBR_INET_NTOP, DT_ATTR_STABCMN,
> diff --git a/test/unittest/funcs/tst.inet_ntoa.d b/test/unittest/funcs/tst.inet_ntoa.d
> index 75161cf1..42ea7107 100644
> --- a/test/unittest/funcs/tst.inet_ntoa.d
> +++ b/test/unittest/funcs/tst.inet_ntoa.d
> @@ -1,13 +1,14 @@
>  /*
>   * Oracle Linux DTrace.
> - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
> + * Copyright (c) 2007, 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.
>   */
> -/* @@xfail: dtv2 */
>  
>  #pragma D option quiet
>  
> +typedef vmlinux`__be32 ipaddr_t;                  /* FIXME: how should this really be handled? */
> +
>  ipaddr_t *ip4a;
>  ipaddr_t *ip4b;
>  ipaddr_t *ip4c;
> -- 
> 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