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

Kris Van Hees kris.van.hees at oracle.com
Fri Nov 19 00:19:51 UTC 2021


Deferring this one until basename() review response since they are similar in
the .S file (so similar comments apply here) and this one depends on the
helper function in the basename patch.

On Tur, Nov 16, 2021 at 05:48:00PM -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>
> ---
>  bpf/Build                          |   1 +
>  bpf/dirname.S                      | 154 +++++++++++++++++++++++++++++
>  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, 223 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..3aee3af2
> --- /dev/null
> +++ b/bpf/dirname.S
> @@ -0,0 +1,154 @@
> +// 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	4
> +#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(dst + DT_STRLEN_BYTES, len, src) */
> +	mov	%r1, DST
> +	add	%r1, DT_STRLEN_BYTES
> +	mov	%r2, LEN
> +	mov	%r3, SRC
> +	call	BPF_FUNC_probe_read
> +
> +	/* dst[DT_STRLEN_BYTES + len] = '\0\ */
> +	mov	%r0, DST
> +	add	%r0, LEN
> +	stb	[%r0+DT_STRLEN_BYTES], 0
> +
> +	/* dt_strlen_store(len, dst) */
> +	mov	%r1, LEN
> +	mov	%r2, DST
> +	call	dt_strlen_store
> +
> +	/* return */
> +	exit
> +
> +.Ldot:
> +	/*
> +	 * The output string is simply ".".
> +	 */
> +	/* dt_strlen_store(1, dst) */
> +	mov	%r1, 1
> +	mov	%r2, DST
> +	call	dt_strlen_store
> +	/* dst[DT_STRLEN_BYTES+0] = '.' */
> +	stb	[DST+DT_STRLEN_BYTES], '.'
> +	/* dst[DT_STRLEN_BYTES+1] = '\0' */
> +	stb	[DST+(DT_STRLEN_BYTES+1)], '\0'
> +	exit
> +
> +.Lslash:
> +	/*
> +	 * The output string is simply "/".
> +	 */
> +	/* dt_strlen_store(1, dst) */
> +	mov	%r1, 1
> +	mov	%r2, DST
> +	call	dt_strlen_store
> +	/* dst[DT_STRLEN_BYTES+0] = '/' */
> +	stb	[DST+DT_STRLEN_BYTES], '/'
> +	/* dst[DT_STRLEN_BYTES+1] = '\0' */
> +	stb	[DST+(DT_STRLEN_BYTES+1)], '\0'
> +	exit
> +#undef SRC
> +#undef DST
> +#undef LEN
> +	.size	dt_dirname, .-dt_dirname
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index ac7ea603..270169ca 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -3347,6 +3347,12 @@ dt_cg_subr_basename(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
>  	dt_cg_subr_str_of_str(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_str_of_str(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
> @@ -4040,7 +4046,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