[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