[DTrace-devel] [PATCH 1/2] Add support for progenyof() subroutine

eugene.loh at oracle.com eugene.loh at oracle.com
Thu Feb 17 20:45:30 UTC 2022


From: Eugene Loh <eugene.loh at oracle.com>

Also, clean up err*progeny*.d tests.  In particular,

*)  err.D_FUNC_UNDEF.progenyofbad1.d was failing because it had always
    been wrong:  the test was mislabeled.  The test was introduced in patch
        c17a42e11dba "Add the OpenSolaris dtrace testsuite."
    with a .r results file that explicitly indicates D_PROTO_LEN,
    even though the test name expects D_FUNC_UNDEF.  However, runtest.sh
    did not check the error tag.  Though runtest.sh was eventually fixed,
    the test fail was simply dismissed XFAIL.

*)  err.D_PROTO_LEN.progenyofbad2.d was passing, but for reasons unrelated
    to progenyof() or its argument checks.  The test used progenyof(trace())
    and therefore did not test progenyof() at all;  rather, it failed on
    trace(), which is missing its argument.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 bpf/Build                                     |  1 +
 bpf/progenyof.S                               | 88 +++++++++++++++++++
 libdtrace/dt_bpf.h                            |  2 +
 libdtrace/dt_cc.c                             | 26 ++++++
 libdtrace/dt_cg.c                             | 30 ++++++-
 libdtrace/dt_dlibs.c                          |  2 +
 .../funcs/err.D_FUNC_UNDEF.progenyofbad1.r    |  2 -
 ...bad2.d => err.D_PROTO_ARG.progenyofbad1.d} | 11 +--
 .../funcs/err.D_PROTO_ARG.progenyofbad1.r     |  4 +
 .../funcs/err.D_PROTO_ARG.progenyofbad2.d     | 18 ++++
 .../funcs/err.D_PROTO_ARG.progenyofbad2.r     |  4 +
 .../funcs/err.D_PROTO_LEN.progenyofbad2.r     |  2 -
 .../funcs/err.D_PROTO_LEN.progenyoftoofew.d   | 18 ++++
 .../funcs/err.D_PROTO_LEN.progenyoftoofew.r   |  2 +
 ...1.d => err.D_PROTO_LEN.progenyoftoomany.d} | 10 +--
 .../funcs/err.D_PROTO_LEN.progenyoftoomany.r  |  2 +
 test/unittest/funcs/tst.progenyof.d           |  3 +-
 17 files changed, 203 insertions(+), 22 deletions(-)
 create mode 100644 bpf/progenyof.S
 delete mode 100644 test/unittest/funcs/err.D_FUNC_UNDEF.progenyofbad1.r
 rename test/unittest/funcs/{err.D_PROTO_LEN.progenyofbad2.d => err.D_PROTO_ARG.progenyofbad1.d} (55%)
 create mode 100644 test/unittest/funcs/err.D_PROTO_ARG.progenyofbad1.r
 create mode 100644 test/unittest/funcs/err.D_PROTO_ARG.progenyofbad2.d
 create mode 100644 test/unittest/funcs/err.D_PROTO_ARG.progenyofbad2.r
 delete mode 100644 test/unittest/funcs/err.D_PROTO_LEN.progenyofbad2.r
 create mode 100644 test/unittest/funcs/err.D_PROTO_LEN.progenyoftoofew.d
 create mode 100644 test/unittest/funcs/err.D_PROTO_LEN.progenyoftoofew.r
 rename test/unittest/funcs/{err.D_FUNC_UNDEF.progenyofbad1.d => err.D_PROTO_LEN.progenyoftoomany.d} (59%)
 create mode 100644 test/unittest/funcs/err.D_PROTO_LEN.progenyoftoomany.r

diff --git a/bpf/Build b/bpf/Build
index 69a2e4d4..5cf9c45f 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -30,6 +30,7 @@ bpf_dlib_SOURCES = \
 	index.S \
 	inet_ntoa.S \
 	lltostr.S \
+	progenyof.S \
 	probe_error.c \
 	rindex.S \
 	speculation.c \
diff --git a/bpf/progenyof.S b/bpf/progenyof.S
new file mode 100644
index 00000000..e17eaa98
--- /dev/null
+++ b/bpf/progenyof.S
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#define BPF_FUNC_probe_read	4
+#define BPF_FUNC_get_current_task	35
+
+	.text
+	.align	4
+	.global	dt_progenyof
+	.type	dt_progenyof, @function
+dt_progenyof:
+#define ARG %r6
+#define CNT %r7
+#define PTR %r8
+#define VAL %r9
+
+	/* uint64_t dt_progenyof(pid_t arg); */
+	mov	ARG, %r1
+	lsh	ARG, 32
+	rsh	ARG, 32
+
+	/* assure the BPF verifier there is no infinite loop */
+	mov	CNT, 256
+
+	/* ptr = bpf_get_current_task() */
+	call	BPF_FUNC_get_current_task
+	mov	PTR, %r0
+
+.Lloop:
+	/* if (ptr == 0) goto Lret0 */
+	jeq	PTR, 0, .Lret0
+
+	/* if (count <= 0) goto Lret0 */
+	jsle	CNT, 0, .Lret0
+
+	/* val = *((uint32_t *)(ptr + TASK_PID)), using [%fp+-8] as temp */
+	mov	%r1, %fp
+	add	%r1, -8
+	mov	%r2, 4
+	lddw	%r3, TASK_PID
+	add	%r3, PTR
+	call	BPF_FUNC_probe_read
+	jne	%r0, 0, .Lret0
+	ldxw	VAL, [%fp+-8]
+	lsh	VAL, 32
+	rsh	VAL, 32
+
+	/* if (val == arg) goto Lret1 */
+	jeq	VAL, ARG, .Lret1
+
+	/* val = *((uint64_t *)(ptr + TASK_REAL_PARENT)), using [%fp+-8] as temp */
+	mov	%r1, %fp
+	add	%r1, -8
+	mov	%r2, 8
+	lddw	%r3, TASK_REAL_PARENT
+	add	%r3, PTR
+	call	BPF_FUNC_probe_read
+	jne	%r0, 0, .Lret0
+	ldxdw	VAL, [%fp+-8]
+
+	/* if (val == ptr) goto Lret0 */
+	jeq	VAL, PTR, .Lret0
+
+	/* ptr = val */
+	mov	PTR, VAL
+
+	/* count-- */
+	sub	CNT, 1
+
+	/* goto Lloop */
+	ja	.Lloop
+
+.Lret0:
+	/* return 0 */
+	mov	%r0, 0
+	exit
+
+.Lret1:
+	/* return 1 */
+	mov	%r0, 1
+	exit
+	.size	dt_progenyof, .-dt_progenyof
+#undef ARG
+#undef CNT
+#undef PTR
+#undef VAL
diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
index 5b9bae80..e361d103 100644
--- a/libdtrace/dt_bpf.h
+++ b/libdtrace/dt_bpf.h
@@ -28,6 +28,8 @@ extern "C" {
 #define DT_CONST_BOOTTM	8
 #define DT_CONST_NSPEC	9
 #define DT_CONST_NCPUS	10
+#define DT_CONST_TASK_REAL_PARENT	11
+#define DT_CONST_TASK_PID	12
 
 extern int perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu,
 			   int group_fd, unsigned long flags);
diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
index ce824eb5..f5b59109 100644
--- a/libdtrace/dt_cc.c
+++ b/libdtrace/dt_cc.c
@@ -2367,6 +2367,32 @@ dt_link_construct(dtrace_hdl_t *dtp, const dt_probe_t *prp, dtrace_difo_t *dp,
 					return -1;
 				nrp->dofr_data = boottime;
 				continue;
+			case DT_CONST_TASK_REAL_PARENT: {
+				ctf_file_t *cfp = dtp->dt_shared_ctf;
+				ctf_id_t type = ctf_lookup_by_name(cfp, "struct task_struct");
+				ctf_membinfo_t ctm;
+
+				if (type == CTF_ERR)
+					return -1;
+
+				if (ctf_member_info(cfp, type, "real_parent", &ctm) == CTF_ERR)
+					return -1;
+				nrp->dofr_data = ctm.ctm_offset / NBBY;
+				continue;
+			}
+			case DT_CONST_TASK_PID: {
+				ctf_file_t *cfp = dtp->dt_shared_ctf;
+				ctf_id_t type = ctf_lookup_by_name(cfp, "struct task_struct");
+				ctf_membinfo_t ctm;
+
+				if (type == CTF_ERR)
+					return -1;
+
+				if (ctf_member_info(cfp, type, "pid", &ctm) == CTF_ERR)
+					return -1;
+				nrp->dofr_data = ctm.ctm_offset / NBBY;
+				continue;
+			}
 			default:
 				/* probe name -> value is probe id */
 				if (strchr(idp->di_name, ':') != NULL)
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index ef04fafd..30f9705f 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3499,6 +3499,34 @@ dt_cg_subr_lltostr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	TRACE_REGSET("    subr-lltostr:End  ");
 }
 
+static void
+dt_cg_subr_progenyof(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dt_ident_t	*idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_progenyof");
+	dt_node_t	*arg = dnp->dn_args;
+
+	assert(idp != NULL);
+
+	TRACE_REGSET("    subr-progenyof:Begin");
+	dt_cg_node(arg, dlp, drp);
+
+	if (dt_regset_xalloc_args(drp) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	emit(dlp, BPF_MOV_REG(BPF_REG_1, arg->dn_reg));
+	dt_regset_free(drp, arg->dn_reg);
+	dt_regset_xalloc(drp, BPF_REG_0);
+	emite(dlp,  BPF_CALL_FUNC(idp->di_id), idp);
+	dt_regset_free_args(drp);
+
+	dnp->dn_reg = dt_regset_alloc(drp);
+	if (dnp->dn_reg == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	emit(dlp, BPF_MOV_REG(dnp->dn_reg, BPF_REG_0));
+	dt_regset_free(drp, BPF_REG_0);
+
+	TRACE_REGSET("    subr-progenyof:End  ");
+}
+
 static void
 dt_cg_subr_rand(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 {
@@ -4137,7 +4165,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
 	[DIF_SUBR_COPYIN]		= NULL,
 	[DIF_SUBR_COPYINSTR]		= NULL,
 	[DIF_SUBR_SPECULATION]		= &dt_cg_subr_speculation,
-	[DIF_SUBR_PROGENYOF]		= NULL,
+	[DIF_SUBR_PROGENYOF]		= &dt_cg_subr_progenyof,
 	[DIF_SUBR_STRLEN]		= &dt_cg_subr_strlen,
 	[DIF_SUBR_COPYOUT]		= NULL,
 	[DIF_SUBR_COPYOUTSTR]		= NULL,
diff --git a/libdtrace/dt_dlibs.c b/libdtrace/dt_dlibs.c
index ebed0509..a8d112d4 100644
--- a/libdtrace/dt_dlibs.c
+++ b/libdtrace/dt_dlibs.c
@@ -79,6 +79,8 @@ static const dt_ident_t		dt_bpf_symbols[] = {
 	DT_BPF_SYMBOL_ID(BOOTTM, DT_IDENT_SCALAR, DT_CONST_BOOTTM),
 	DT_BPF_SYMBOL_ID(NSPEC, DT_IDENT_SCALAR, DT_CONST_NSPEC),
 	DT_BPF_SYMBOL_ID(NCPUS, DT_IDENT_SCALAR, DT_CONST_NCPUS),
+	DT_BPF_SYMBOL_ID(TASK_REAL_PARENT, DT_IDENT_SCALAR, DT_CONST_TASK_REAL_PARENT),
+	DT_BPF_SYMBOL_ID(TASK_PID, DT_IDENT_SCALAR, DT_CONST_TASK_PID),
 
 	/* End-of-list marker */
 	{ NULL, }
diff --git a/test/unittest/funcs/err.D_FUNC_UNDEF.progenyofbad1.r b/test/unittest/funcs/err.D_FUNC_UNDEF.progenyofbad1.r
deleted file mode 100644
index e7a64031..00000000
--- a/test/unittest/funcs/err.D_FUNC_UNDEF.progenyofbad1.r
+++ /dev/null
@@ -1,2 +0,0 @@
--- @@stderr --
-dtrace: failed to compile script test/unittest/funcs/err.D_FUNC_UNDEF.progenyofbad1.d: [D_PROTO_LEN] line 19: progenyof( ) prototype mismatch: 2 args passed, 1 expected
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.progenyofbad2.d b/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad1.d
similarity index 55%
rename from test/unittest/funcs/err.D_PROTO_LEN.progenyofbad2.d
rename to test/unittest/funcs/err.D_PROTO_ARG.progenyofbad1.d
index 033b3d54..4a00d08f 100644
--- a/test/unittest/funcs/err.D_PROTO_LEN.progenyofbad2.d
+++ b/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad1.d
@@ -1,23 +1,18 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /*
- * ASSERTION:
- *	progenyof() should return an error if the argument is an
- *	incorrect type.
+ * ASSERTION: progenyof() should take a pid_t argument.
  *
  * SECTION: Actions and Subroutines/progenyof()
- *
  */
 
-
 BEGIN
 {
-	progenyof(trace());
+	progenyof("some_string");
 	exit(0);
 }
-
diff --git a/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad1.r b/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad1.r
new file mode 100644
index 00000000..158eee85
--- /dev/null
+++ b/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad1.r
@@ -0,0 +1,4 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_ARG.progenyofbad1.d: [D_PROTO_ARG] line 16: progenyof( ) argument #1 is incompatible with prototype:
+	prototype: pid_t
+	 argument: string
diff --git a/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad2.d b/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad2.d
new file mode 100644
index 00000000..67735b79
--- /dev/null
+++ b/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad2.d
@@ -0,0 +1,18 @@
+/*
+ * Oracle Linux DTrace.
+ * 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.
+ */
+
+/*
+ * ASSERTION: progenyof() should take a pid_t argument.
+ *
+ * SECTION: Actions and Subroutines/progenyof()
+ */
+
+BEGIN
+{
+	progenyof(trace(1));
+	exit(0);
+}
diff --git a/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad2.r b/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad2.r
new file mode 100644
index 00000000..73dec003
--- /dev/null
+++ b/test/unittest/funcs/err.D_PROTO_ARG.progenyofbad2.r
@@ -0,0 +1,4 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_ARG.progenyofbad2.d: [D_PROTO_ARG] line 16: progenyof( ) argument #1 is incompatible with prototype:
+	prototype: pid_t
+	 argument: void
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.progenyofbad2.r b/test/unittest/funcs/err.D_PROTO_LEN.progenyofbad2.r
deleted file mode 100644
index 35145323..00000000
--- a/test/unittest/funcs/err.D_PROTO_LEN.progenyofbad2.r
+++ /dev/null
@@ -1,2 +0,0 @@
--- @@stderr --
-dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.progenyofbad2.d: [D_PROTO_LEN] line 20: trace( ) prototype mismatch: 0 args passed, 1 expected
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoofew.d b/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoofew.d
new file mode 100644
index 00000000..96bf8b4d
--- /dev/null
+++ b/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoofew.d
@@ -0,0 +1,18 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 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.
+ */
+
+/*
+ * ASSERTION: progenyof() should take one argument.
+ *
+ * SECTION: Actions and Subroutines/progenyof()
+ */
+
+BEGIN
+{
+	progenyof();
+	exit(0);
+}
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoofew.r b/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoofew.r
new file mode 100644
index 00000000..e31d0be3
--- /dev/null
+++ b/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoofew.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.progenyoftoofew.d: [D_PROTO_LEN] line 16: progenyof( ) prototype mismatch: 0 args passed, 1 expected
diff --git a/test/unittest/funcs/err.D_FUNC_UNDEF.progenyofbad1.d b/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoomany.d
similarity index 59%
rename from test/unittest/funcs/err.D_FUNC_UNDEF.progenyofbad1.d
rename to test/unittest/funcs/err.D_PROTO_LEN.progenyoftoomany.d
index dca7f283..2d4d922a 100644
--- a/test/unittest/funcs/err.D_FUNC_UNDEF.progenyofbad1.d
+++ b/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoomany.d
@@ -1,22 +1,18 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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 */
+
 /*
- * ASSERTION:
- *	progenyof() should accept one argument - a pid
+ * ASSERTION: progenyof() should take one argument.
  *
  * SECTION: Actions and Subroutines/progenyof()
- *
  */
 
-
 BEGIN
 {
 	progenyof(1, 2);
 	exit(0);
 }
-
diff --git a/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoomany.r b/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoomany.r
new file mode 100644
index 00000000..46b4f985
--- /dev/null
+++ b/test/unittest/funcs/err.D_PROTO_LEN.progenyoftoomany.r
@@ -0,0 +1,2 @@
+-- @@stderr --
+dtrace: failed to compile script test/unittest/funcs/err.D_PROTO_LEN.progenyoftoomany.d: [D_PROTO_LEN] line 16: progenyof( ) prototype mismatch: 2 args passed, 1 expected
diff --git a/test/unittest/funcs/tst.progenyof.d b/test/unittest/funcs/tst.progenyof.d
index cadeb654..9d73420f 100644
--- a/test/unittest/funcs/tst.progenyof.d
+++ b/test/unittest/funcs/tst.progenyof.d
@@ -1,6 +1,6 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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.
  */
@@ -14,7 +14,6 @@
  *
  */
 
-/* @@xfail: dtv2 */
 /* @@trigger: pid-tst-float */
 
 #pragma D option quiet
-- 
2.18.4




More information about the DTrace-devel mailing list