[DTrace-devel] [PATCH 2/2 v3] Add support for the dirname() action

Kris Van Hees kris.van.hees at oracle.com
Wed Dec 1 20:00:19 UTC 2021


On Fri, Nov 19, 2021 at 02:56:21PM -0500, eugene.loh--- via DTrace-devel wrote:
> From: Eugene Loh <eugene.loh at oracle.com>
> 
> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>

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

... I'll be putting it in 'dev' later today.

> ---
>  bpf/Build                          |   1 +
>  bpf/dirname.S                      | 140 +++++++++++++++++++++++++++++
>  libdtrace/dt_cg.c                  |   8 +-
>  libdtrace/dt_dlibs.c               |   1 +
>  test/unittest/dif/dirname.d        |   1 -
>  test/unittest/funcs/tst.dirname0.d |  39 ++++++++
>  test/unittest/funcs/tst.dirname0.r |  21 +++++
>  7 files changed, 209 insertions(+), 2 deletions(-)
>  create mode 100644 bpf/dirname.S
>  create mode 100644 test/unittest/funcs/tst.dirname0.d
>  create mode 100644 test/unittest/funcs/tst.dirname0.r
> 
> diff --git a/bpf/Build b/bpf/Build
> index e66e8dc9..258a505d 100644
> --- a/bpf/Build
> +++ b/bpf/Build
> @@ -24,6 +24,7 @@ bpf_dlib_SRCDEPS = $(objdir)/include/.dir.stamp
>  bpf_dlib_SOURCES = \
>  	agg_lqbin.c agg_qbin.c \
>  	basename.S \
> +	dirname.S \
>  	get_bvar.c \
>  	get_tvar.c set_tvar.c \
>  	index.S \
> diff --git a/bpf/dirname.S b/bpf/dirname.S
> new file mode 100644
> index 00000000..1ab676ce
> --- /dev/null
> +++ b/bpf/dirname.S
> @@ -0,0 +1,140 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
> + */
> +
> +#define DT_STRLEN_BYTES		2
> +
> +#define BPF_FUNC_probe_read_str	45
> +
> +/*
> + * void dt_dirname(char *src, char *dst);
> + */
> +	.text
> +	.align	4
> +	.global	dt_dirname
> +	.type	dt_dirname, @function
> +dt_dirname :
> +#define SRC %r6
> +#define DST %r7
> +#define LEN %r8
> +
> +	/* store copies of input arguments */
> +	mov	SRC, %r1
> +	mov	DST, %r2
> +
> +	/* ignore the string-length prefix */
> +	add	SRC, DT_STRLEN_BYTES
> +
> +	/* r0 = bpf_probe_read_str(dst, STRSZ + 1, src) */
> +	mov	%r1, DST
> +	lddw	%r2, STRSZ
> +	add	%r2, 1
> +	mov	%r3, SRC
> +	call	BPF_FUNC_probe_read_str
> +
> +	/* if (r0 s<= 1) goto Ldot */
> +	jsle	%r0, 1, .Ldot
> +
> +	/* len = r0 - 1 */
> +	mov	LEN, %r0
> +	sub	LEN, 1
> +
> +	/*
> +	 * In general, the string will look like
> +	 * "dirname////basename////".
> +	 */
> +
> +	/*
> +	 * Back up, looking for a non-'/' char.
> +	 * That gives us the end of basename.
> +	 */
> +.L1:
> +	/* len-- */
> +	sub	LEN, 1
> +	/* if (len s< 0) goto Lslash */
> +	jslt	LEN, 0, .Lslash
> +	/* if (src[len] == '/') goto L1 */
> +	mov	%r0, SRC
> +	add	%r0, LEN
> +	ldxb	%r0, [%r0+0]
> +	and	%r0, 0xff
> +	jeq	%r0, '/', .L1
> +
> +	/*
> +	 * Back up, looking for a '/' char.
> +	 * That gives us right before the start of basename.
> +	 */
> +.L2:
> +	/* len-- */
> +	sub	LEN, 1
> +	/* if (len s< 0) goto Ldot */
> +	jslt	LEN, 0, .Ldot
> +	/* if (src[len] != '/') goto L2 */
> +	mov	%r0, SRC
> +	add	%r0, LEN
> +	ldxb	%r0, [%r0+0]
> +	and	%r0, 0xff
> +	jne	%r0, '/', .L2
> +
> +	/*
> +	 * Back up, looking for a non-'/' char.
> +	 * That gives us the end of dirname.
> +	 */
> +.L3:
> +	/* len-- */
> +	sub	LEN, 1
> +	/* if (len s< 0) goto Lslash */
> +	jslt	LEN, 0, .Lslash
> +	/* if (src[len] == '/') goto L3 */
> +	mov	%r0, SRC
> +	add	%r0, LEN
> +	ldxb	%r0, [%r0+0]
> +	and	%r0, 0xff
> +	jeq	%r0, '/', .L3
> +
> +	/* len++ */
> +	add	LEN, 1
> +
> +	/*
> +	 * The output string is up to the end of the dirname.
> +	 */
> +
> +	/* bpf_probe_read_str(dst + DT_STRLEN_BYTES, len + 1, src) */
> +	mov	%r1, DST
> +	add	%r1, DT_STRLEN_BYTES
> +	mov	%r2, LEN
> +	add	%r2, 1
> +	mov	%r3, SRC
> +	call	BPF_FUNC_probe_read_str
> +
> +.Lcoda:
> +	/* dt_strlen_store(len, dst) */
> +	mov	%r1, LEN
> +	mov	%r2, DST
> +	call	dt_strlen_store
> +
> +	/* return */
> +	exit
> +
> +.Ldot:
> +	/*
> +	 * The output string is simply ".".
> +	 */
> +	mov	LEN, 1
> +	stb	[DST+DT_STRLEN_BYTES], '.'
> +	stb	[DST+(DT_STRLEN_BYTES+1)], '\0'
> +	ja	.Lcoda
> +
> +.Lslash:
> +	/*
> +	 * The output string is simply "/".
> +	 */
> +	mov	LEN, 1
> +	stb	[DST+DT_STRLEN_BYTES], '/'
> +	stb	[DST+(DT_STRLEN_BYTES+1)], '\0'
> +	ja	.Lcoda
> +#undef SRC
> +#undef DST
> +#undef LEN
> +	.size	dt_dirname, .-dt_dirname
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index ff28b748..7be96561 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -3348,6 +3348,12 @@ dt_cg_subr_basename(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  	dt_cg_subr_path_helper(dnp, dlp, drp, "dt_basename");
>  }
>  
> +static void
> +dt_cg_subr_dirname(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> +{
> +	dt_cg_subr_path_helper(dnp, dlp, drp, "dt_dirname");
> +}
> +
>  /*
>   * Get and return a new speculation ID.  These are unallocated entries in the
>   * specs map, obtained by calling dt_speculation().  Return zero if none is
> @@ -4041,7 +4047,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
>  	[DIF_SUBR_STRJOIN]		= dt_cg_subr_strjoin,
>  	[DIF_SUBR_LLTOSTR]		= &dt_cg_subr_lltostr,
>  	[DIF_SUBR_BASENAME]		= &dt_cg_subr_basename,
> -	[DIF_SUBR_DIRNAME]		= NULL,
> +	[DIF_SUBR_DIRNAME]		= &dt_cg_subr_dirname,
>  	[DIF_SUBR_CLEANPATH]		= NULL,
>  	[DIF_SUBR_STRCHR]		= &dt_cg_subr_strchr,
>  	[DIF_SUBR_STRRCHR]		= &dt_cg_subr_strrchr,
> diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
> index 771eba64..58fa9597 100644
> --- a/libdtrace/dt_dlibs.c
> +++ b/libdtrace/dt_dlibs.c
> @@ -55,6 +55,7 @@ static const dt_ident_t		dt_bpf_symbols[] = {
>  	DT_BPF_SYMBOL(dt_agg_lqbin, DT_IDENT_SYMBOL),
>  	DT_BPF_SYMBOL(dt_agg_qbin, DT_IDENT_SYMBOL),
>  	DT_BPF_SYMBOL(dt_basename, DT_IDENT_SYMBOL),
> +	DT_BPF_SYMBOL(dt_dirname, DT_IDENT_SYMBOL),
>  	DT_BPF_SYMBOL(dt_error, DT_IDENT_SYMBOL),
>  	DT_BPF_SYMBOL(dt_get_bvar, DT_IDENT_SYMBOL),
>  	DT_BPF_SYMBOL(dt_get_string, DT_IDENT_SYMBOL),
> diff --git a/test/unittest/dif/dirname.d b/test/unittest/dif/dirname.d
> index ed8053b0..7919180a 100644
> --- a/test/unittest/dif/dirname.d
> +++ b/test/unittest/dif/dirname.d
> @@ -1,4 +1,3 @@
> -/* @@xfail: dtv2 */
>  BEGIN
>  {
>  	exit(dirname("/foo/bar") == "/foo" ? 0 : 1);
> diff --git a/test/unittest/funcs/tst.dirname0.d b/test/unittest/funcs/tst.dirname0.d
> new file mode 100644
> index 00000000..a3708d56
> --- /dev/null
> +++ b/test/unittest/funcs/tst.dirname0.d
> @@ -0,0 +1,39 @@
> +/*
> + * 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.
> + */
> +
> +#pragma D option quiet
> +
> +BEGIN
> +{
> +	printf("|%s|\n", dirname("/foo/bar/baz"));
> +	printf("|%s|\n", dirname("/foo/bar///baz/"));
> +	printf("|%s|\n", dirname("/foo/bar/baz/"));
> +	printf("|%s|\n", dirname("/foo/bar/baz//"));
> +	printf("|%s|\n", dirname("/foo/bar/baz/."));
> +	printf("|%s|\n", dirname("/foo/bar/baz/./"));
> +	printf("|%s|\n", dirname("/foo/bar/baz/.//"));
> +	printf("|%s|\n", dirname("foo/bar/baz/"));
> +	printf("|%s|\n", dirname("/"));
> +	printf("|%s|\n", dirname("./"));
> +	printf("|%s|\n", dirname("//"));
> +	printf("|%s|\n", dirname("/."));
> +	printf("|%s|\n", dirname("/./"));
> +	printf("|%s|\n", dirname("/./."));
> +	printf("|%s|\n", dirname("/.//"));
> +	printf("|%s|\n", dirname("."));
> +	printf("|%s|\n", dirname("f"));
> +	printf("|%s|\n", dirname("f/"));
> +	printf("|%s|\n", dirname("/////"));
> +	printf("|%s|\n", dirname(""));
> +	exit(0);
> +}
> +
> +ERROR
> +{
> +	exit(1);
> +}
> +
> diff --git a/test/unittest/funcs/tst.dirname0.r b/test/unittest/funcs/tst.dirname0.r
> new file mode 100644
> index 00000000..c1e5f257
> --- /dev/null
> +++ b/test/unittest/funcs/tst.dirname0.r
> @@ -0,0 +1,21 @@
> +|/foo/bar|
> +|/foo/bar|
> +|/foo/bar|
> +|/foo/bar|
> +|/foo/bar/baz|
> +|/foo/bar/baz|
> +|/foo/bar/baz|
> +|foo/bar|
> +|/|
> +|.|
> +|/|
> +|/|
> +|/|
> +|/.|
> +|/|
> +|.|
> +|.|
> +|.|
> +|/|
> +|.|
> +
> -- 
> 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