[DTrace-devel] [PATCH 16/16] PID provider implementation

Kris Van Hees kris.van.hees at oracle.com
Thu Mar 18 21:55:07 PDT 2021


This patch provides an implementation of the pid provider.  This is
a provider that makes it possible to do function boundary tracing
at the userspace level (in shared libraries and executables).

The implementation of userspace probes is built on the uprobes
support in the kernel tracing infrastructure.  The uprobes are
inode based and therefore not process specific whereas pid probes in
DTrace are process specific.  This means that there is a n-to-1
relation between pid probes and uprobes.  It is also worth noting
that a pid probe together with its underlying uprobe provides
equivalent functionality as any other non-pid DTrace probes.  The
(process specific) pid probe represents the named probe and has
D clauses associated eith it.  The uprobe represents the underlying
system probe (not process specific) that our program will be attached
to.

When we want to trace the main() functon in a process with PID 1234,
we can specify this probes as pid1234:a.out:main:entry.  A lookup is
performed to see if we already have a pid:<ino>:main:entry probe to
associate the new pid probe with.  If not, it is created.  It is this
pid:<ino>:main:entry probe that will be added to the enablings list of
probes to which we need to attach a BPF program.

Any clauses for pid1234:a.out:main:entry will be associated with that
specific probe.

When the final BPF program is constructed for a pid related enaling,
we construct the program for probe pid:<ino>:main:entry.  The program
(trampoline) will comprise basic environment setup, copying of any
possible probe arguments, and a sequence of code blocks following the
pattern:

	if (pid == <some-pid>) {
		casee dt_clause_0(dctx);
		casee dt_clause_1(dctx);
		<...>
	}

In other words, although the uprobe will fire for any process that
reaches the probe point, we check the PID of the process that caused
the probe to fire against the registered probes and we only execute
the clauses for the matching PID.

Future patches will augment the functionality provided here with
arbitrary instruction tracing at the userspace level.

Signee-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/Build                     |   2 +
 libdtrace/dt_cc.c                   |   4 +-
 libdtrace/dt_impl.h                 |   1 +
 libdtrace/dt_open.c                 |   1 +
 libdtrace/dt_pid.c                  |  32 ++-
 libdtrace/dt_prov_pid.c             | 360 ++++++++++++++++++++++++++++
 libdtrace/dt_provider.h             |   5 +
 test/unittest/pid/tst.addprobes.sh  |   2 +-
 test/unittest/pid/tst.args1.d       |   6 +-
 test/unittest/pid/tst.coverage.d    |   4 +-
 test/unittest/pid/tst.float.d       |   4 +-
 test/unittest/pid/tst.main.sh       |   3 +-
 test/unittest/pid/tst.manypids.sh   |   3 +-
 test/unittest/pid/tst.probemod.sh   |   7 +-
 test/unittest/pid/tst.provregex1.sh |   3 +-
 test/unittest/usdt/tst.dlclose3.sh  |   3 +-
 16 files changed, 416 insertions(+), 24 deletions(-)
 create mode 100644 libdtrace/dt_prov_pid.c

diff --git a/libdtrace/Build b/libdtrace/Build
index 9c683e8f..cbc52659 100644
--- a/libdtrace/Build
+++ b/libdtrace/Build
@@ -50,6 +50,7 @@ libdtrace-build_SOURCES = dt_aggregate.c \
 			  dt_program.c \
 			  dt_prov_dtrace.c \
 			  dt_prov_fbt.c \
+			  dt_prov_pid.c \
 			  dt_prov_profile.c \
 			  dt_prov_sdt.c \
 			  dt_prov_syscall.c \
@@ -88,6 +89,7 @@ dt_dis.c_CFLAGS := -Wno-pedantic
 dt_proc.c_CFLAGS := -Wno-pedantic
 dt_prov_dtrace.c_CFLAGS := -Wno-pedantic
 dt_prov_fbt.c_CFLAGS := -Wno-pedantic
+dt_prov_pid.c_CFLAGS := -Wno-pedantic
 dt_prov_profile.c_CFLAGS := -Wno-pedantic
 dt_prov_sdt.c_CFLAGS := -Wno-pedantic
 dt_prov_syscall.c_CFLAGS := -Wno-pedantic
diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
index 4769daa6..3bb521f5 100644
--- a/libdtrace/dt_cc.c
+++ b/libdtrace/dt_cc.c
@@ -1707,7 +1707,7 @@ dt_setcontext(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp)
 	 * that process if:
 	 *
 	 * (1) The provider doesn't exist, or,
-	 * (2) The provider exists and has DTRACE_PRIV_PROC privilege.
+	 * (2) The provider exists and has DT_PROVIDER_PID flag set.
 	 *
 	 * On an error, dt_pid_create_probes() will set the error message
 	 * and tag -- we just have to longjmp() out of here.
@@ -1715,7 +1715,7 @@ dt_setcontext(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp)
 	if (pdp->prv && pdp->prv[0] &&
 	    isdigit(pdp->prv[strlen(pdp->prv) - 1]) &&
 	    ((pvp = dt_provider_lookup(dtp, pdp->prv)) == NULL ||
-	    pvp->desc.dtvd_priv.dtpp_flags & DTRACE_PRIV_PROC) &&
+	     pvp->pv_flags & DT_PROVIDER_PID) &&
 	    dt_pid_create_probes(pdp, dtp, yypcb) != 0) {
 		longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
 	}
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 687132fe..47029804 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -293,6 +293,7 @@ struct dtrace_hdl {
 	struct dt_provider **dt_provs; /* hash table of dt_provider_t's */
 	uint_t dt_provbuckets;	/* number of provider hash buckets */
 	uint_t dt_nprovs;	/* number of providers in hash and list */
+	const struct dt_provider *dt_prov_pid; /* PID provider */
 	dt_proc_hash_t *dt_procs; /* hash table of grabbed process handles */
 	dt_intdesc_t dt_ints[6]; /* cached integer type descriptions */
 	ctf_id_t dt_type_func;	/* cached CTF identifier for function type */
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index 79b834e7..74405d3b 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -64,6 +64,7 @@ const dt_version_t _dtrace_versions[] = {
 static const dt_provimpl_t *dt_providers[] = {
 	&dt_dtrace,
 	&dt_fbt,
+	&dt_pid,
 	&dt_profile,
 	&dt_sdt,
 	&dt_syscall,
diff --git a/libdtrace/dt_pid.c b/libdtrace/dt_pid.c
index 7bd299e5..210b199d 100644
--- a/libdtrace/dt_pid.c
+++ b/libdtrace/dt_pid.c
@@ -21,6 +21,7 @@
 
 #include <dt_impl.h>
 #include <dt_program.h>
+#include <dt_provider.h>
 #include <dt_pid.h>
 #include <dt_string.h>
 
@@ -94,15 +95,29 @@ static int
 dt_pid_create_fbt_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
     pid_probespec_t *psp, const GElf_Sym *symp, pid_probetype_t type)
 {
+	const dt_provider_t	*pvp;
+
 	psp->pps_type = type;
 	psp->pps_pc = (uintptr_t)symp->st_value;
 	psp->pps_size = (size_t)symp->st_size;
 	psp->pps_glen = 0;		/* no glob pattern */
 	psp->pps_gstr[0] = '\0';
 
+	/* Make sure we have a PID provider. */
+	pvp = dtp->dt_prov_pid;
+	if (pvp == NULL) {
+		pvp = dt_provider_lookup(dtp, "pid");
+		if (pvp == NULL)
+			return 0;
+
+		dtp->dt_prov_pid = pvp;
+	}
+
+	assert(pvp->impl != NULL && pvp->impl->provide_pid != NULL);
+
 	/* Create a probe using 'psp'. */
 
-	return 1;
+	return pvp->impl->provide_pid(dtp, psp);
 }
 
 static int
@@ -231,6 +246,7 @@ dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
 
 out:
 	free(psp->pps_mod);
+	free(psp->pps_fn);
 	dt_free(dtp, psp);
 	return rc;
 }
@@ -261,6 +277,12 @@ dt_pid_sym_filt(void *arg, const GElf_Sym *symp, const char *func)
 		if (strcmp(func, "_init") == 0 || strcmp(func, "_fini") == 0)
 			return 0;
 
+		/*
+		 * Versioned identifiers are a problem.
+		 */
+		if (strchr(func, '@') != NULL)
+			return 0;
+
 		if ((pp->dpp_last_taken = gmatch(func, pp->dpp_func)) != 0) {
 			pp->dpp_last = *symp;
 			return dt_pid_per_sym(pp, symp, func);
@@ -286,7 +308,7 @@ dt_pid_per_mod(void *arg, const prmap_t *pmp, const char *obj)
 	dt_Plmid(pp->dpp_dtp, pid, pmp->pr_vaddr, &pp->dpp_lmid);
 
 	pp->dpp_ino = pmp->pr_inum;
-	pp->dpp_vaddr = pmp->pr_vaddr;
+	pp->dpp_vaddr = pmp->pr_file->first_segment->pr_vaddr;
 
 	/*
 	 * Note: if an execve() happens in the victim after this point, the
@@ -518,6 +540,7 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
 	pp.dpp_func = pdp->fun[0] != '\0' ? pdp->fun : "*";
 	pp.dpp_name = pdp->prb[0] != '\0' ? pdp->prb : "*";
 	pp.dpp_last_taken = 0;
+	pp.dpp_fname = NULL;
 
 	if (strcmp(pp.dpp_func, "-") == 0) {
 		const prmap_t *aout, *pmp;
@@ -568,6 +591,11 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
 		}
 	}
 
+	if (pp.dpp_func != pdp->fun) {
+		free((char *)pdp->fun);
+		pdp->fun = pp.dpp_func;
+	}
+
 	free(pp.dpp_fname);
 
 	return ret;
diff --git a/libdtrace/dt_prov_pid.c b/libdtrace/dt_prov_pid.c
new file mode 100644
index 00000000..681874f1
--- /dev/null
+++ b/libdtrace/dt_prov_pid.c
@@ -0,0 +1,360 @@
+/*
+ * 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.
+ *
+ * The PID provider for DTrace.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <bpf_asm.h>
+
+#include "dt_dctx.h"
+#include "dt_cg.h"
+#include "dt_list.h"
+#include "dt_provider.h"
+#include "dt_probe.h"
+
+static const char		prvname[] = "pid";
+
+#define PRV			"pid%d"
+
+#define UPROBE_EVENTS		TRACEFS "uprobe_events"
+
+#define PID_GROUP_FMT		GROUP_FMT "_%lx"
+#define PID_GROUP_DATA		GROUP_DATA, pp->ino
+
+typedef struct pid_probe {
+	ino_t		ino;
+	char		*fn;
+	uint64_t	off;
+	tp_probe_t	*tp;
+	dt_list_t	probes;
+} pid_probe_t;
+
+static const dtrace_pattr_t	pattr = {
+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+};
+
+dt_provimpl_t	dt_pid_sub;
+
+static int populate(dtrace_hdl_t *dtp)
+{
+	dt_provider_create(dtp, prvname, &dt_pid, &pattr);
+	return 0;
+}
+
+static void probe_destroy(dtrace_hdl_t *dtp, void *datap)
+{
+	pid_probe_t	*pp = datap;
+
+	dt_tp_destroy(dtp, pp->tp);
+	dt_free(dtp, pp->fn);
+	dt_free(dtp, pp);
+}
+
+static int provide_pid(dtrace_hdl_t *dtp, const pid_probespec_t *psp)
+{
+	char			prv[DTRACE_PROVNAMELEN];
+	char			mod[DTRACE_MODNAMELEN];
+	char			prb[DTRACE_NAMELEN];
+	dt_provider_t		*pidpvp;
+	dt_provider_t		*pvp;
+	dtrace_probedesc_t	pd;
+	pid_probe_t		*pp;
+	dt_probe_t		*prp;
+	uint64_t		off = psp->pps_pc - psp->pps_vaddr;
+
+	/*
+	 * First check whether this pid probe already exists.  If so, there is
+	 * nothing left to do.
+	 */
+	snprintf(prv, sizeof(prv), "pid%d", psp->pps_pid);
+
+	switch (psp->pps_type) {
+	case DTFTP_ENTRY:
+		strncpy(prb, "entry", sizeof(prb));
+		break;
+	case DTFTP_RETURN:
+		strncpy(prb, "return", sizeof(prb));
+		break;
+	case DTFTP_OFFSETS:
+		snprintf(prb, sizeof(prb), "%lx", off);
+		break;
+	default:
+		return 0;
+	}
+
+	pd.id = DTRACE_IDNONE;
+	pd.prv = prv;
+	pd.mod = psp->pps_mod;
+	pd.fun = psp->pps_fun;
+	pd.prb = prb;
+
+	prp = dt_probe_lookup(dtp, &pd);
+	if (prp != NULL)
+		return 1;		/* probe found */
+
+	/* Get the main (real) pid provider. */
+	pidpvp = dt_provider_lookup(dtp, prvname);
+	if (pidpvp == NULL)
+		return 0;
+
+	/* Get (or create) the provider for the PID of the probe. */
+	pvp = dt_provider_lookup(dtp, prv);
+	if (pvp == NULL) {
+		pvp = dt_provider_create(dtp, prv, &dt_pid_sub, &pattr);
+		if (pvp == NULL)
+			return 0;
+	}
+
+	/* Mark the provider as a PID provider. */
+	pvp->pv_flags |= DT_PROVIDER_PID;
+
+	/*
+	 * Fill in the probe description for the main (real) probe.  The
+	 * module is the inode number (in hex), the function name is as
+	 * specified for the pid probe, and the probe name is "entry",
+	 * "return", or the offset into the function (in hex).
+	 */
+	snprintf(mod, sizeof(mod), "%lx", psp->pps_ino);
+
+	/*
+	 * Try to lookup the main (real) probe.  Since multiple pid probes may
+	 * all map onto the same underlying main (real) probe, we may already
+	 * have one in the system.
+	 *
+	 * If not found, we create a new probe.
+	 */
+	pd.id = DTRACE_IDNONE;
+	pd.prv = prvname;
+	pd.mod = mod;
+	pd.fun = psp->pps_fun;
+	pd.prb = prb;
+	prp = dt_probe_lookup(dtp, &pd);
+	if (prp == NULL) {
+		/* Set up the pid probe data. */
+		pp = dt_zalloc(dtp, sizeof(pid_probe_t));
+		if (pp == NULL)
+			return 0;
+
+		pp->ino = psp->pps_ino;
+		pp->fn = strdup(psp->pps_fn);
+		pp->off = off;
+		pp->tp = dt_tp_alloc(dtp);
+		if (pp->tp == NULL)
+			goto fail;
+
+		prp = dt_probe_insert(dtp, pidpvp, prvname, mod, psp->pps_fun,
+				      prb, pp);
+		if (prp == NULL)
+			goto fail;
+	} else
+		pp = prp->prv_data;
+
+	/* Try to add the pid probe. */
+	prp = dt_probe_insert(dtp, pvp, prv, psp->pps_mod, psp->pps_fun, prb,
+			      prp);
+	if (prp == NULL)
+		goto fail;
+
+	/* Add the pid probe to the list of probes for the main (real) probe. */
+	dt_list_append(&pp->probes, prp);
+
+	return 1;
+
+fail:
+	probe_destroy(dtp, pp);
+	return 0;
+}
+
+static void enable(dtrace_hdl_t *dtp, dt_probe_t *prp)
+{
+	assert(prp->prov->impl == &dt_pid_sub);
+
+	/* We should enable the main (real) probe (if not enabled yet). */
+	prp = prp->prv_data;
+
+	if (!dt_in_list(&dtp->dt_enablings, prp))
+		dt_list_append(&dtp->dt_enablings, prp);
+}
+
+/*
+ * Generate a BPF trampoline for a pid probe.
+ *
+ * The trampoline function is called when a pid probe triggers, and it must
+ * satisfy the following prototype:
+ *
+ *	int dt_pid(dt_pt_regs *regs)
+ *
+ * The trampoline will first populate a dt_dctx_t struct.  It will then emulate
+ * the firing of all dependent pid* probes and their clauses.
+ */
+static void trampoline(dt_pcb_t *pcb)
+{
+	dt_irlist_t		*dlp = &pcb->pcb_ir;
+	const dt_probe_t	*prp = pcb->pcb_probe;
+	const dt_probe_t	*pprp;
+	const pid_probe_t	*pp = prp->prv_data;
+
+	dt_cg_tramp_prologue(pcb);
+
+	/*
+	 * After the dt_cg_tramp_prologue() call, we have:
+	 *				//     (%r7 = dctx->mst)
+	 *				//     (%r8 = dctx->ctx)
+	 */
+
+#if 0
+	/*
+	 *     dctx->mst->regs = *(dt_pt_regs *)dctx->ctx;
+	 *				// lddw %r0, [%r8 + 0]
+	 *				// stdw [%r7 + DMST_REGS + 0], %r0
+	 *				// lddw %r0, [%r8 + 8]
+	 *				// stdw [%r7 + DMST_REGS + 8], %r0
+	 *				//     (...)
+	 */
+	for (i = 0; i < sizeof(dt_pt_regs); i += 8) {
+		emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_8, i));
+		emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_REGS + i, BPF_REG_0));
+	}
+#endif
+
+	dt_cg_tramp_copy_args_from_regs(pcb, BPF_REG_8);
+
+	/*
+	 * Retrieve the PID of the process that caused the probe to fire.
+	 */
+	emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_get_current_pid_tgid));
+	emit(dlp,  BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32));
+	for (pprp = dt_list_next(&pp->probes); pprp != NULL;
+	     pprp = dt_list_next(pprp)) {
+		uint_t	lbl_next = dt_irlist_label(dlp);
+		pid_t	pid = strtoul(pprp->desc->prv + 3, NULL, 10);
+
+		/*
+		 * Check whether this pid-provider probe serves the current
+		 * process.
+		 */
+		emit(dlp,  BPF_BRANCH_IMM(BPF_JNE, BPF_REG_0, pid, lbl_next));
+		dt_cg_tramp_call_clauses(pcb, pprp, DT_ACTIVITY_ACTIVE);
+		emitl(dlp, lbl_next,
+			   BPF_NOP());
+	}
+
+	dt_cg_tramp_return(pcb);
+}
+
+static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
+{
+	pid_probe_t	*pp = prp->prv_data;
+
+	if (!dt_tp_is_attached(pp->tp)) {
+		char	*fn;
+		FILE	*f;
+		size_t	len;
+		int	fd, rc = -1;
+
+		/* add the uprobe */
+		fd = open(UPROBE_EVENTS, O_WRONLY | O_APPEND);
+		if (fd != -1) {
+			rc = dprintf(fd,
+				     "%c:" PID_GROUP_FMT "/%s_%s %s:0x%lx\n",
+				     prp->desc->prb[0] == 'e' ? 'p' : 'r',
+				     PID_GROUP_DATA, prp->desc->fun,
+				     prp->desc->prb, pp->fn, pp->off);
+			close(fd);
+		}
+		if (rc == -1)
+			return -ENOENT;
+
+		/* open format file */
+		len = snprintf(NULL, 0, "%s" PID_GROUP_FMT "/%s_%s/format",
+			       EVENTSFS, PID_GROUP_DATA, prp->desc->fun,
+			       prp->desc->prb) + 1;
+		fn = dt_alloc(dtp, len);
+		if (fn == NULL)
+			return -ENOENT;
+
+		snprintf(fn, len, "%s" PID_GROUP_FMT "/%s_%s/format",
+			 EVENTSFS, PID_GROUP_DATA, prp->desc->fun,
+			 prp->desc->prb);
+		f = fopen(fn, "r");
+		dt_free(dtp, fn);
+		if (f == NULL)
+			return -ENOENT;
+
+		rc = dt_tp_event_info(dtp, f, 0, pp->tp, NULL, NULL);
+		fclose(f);
+	}
+
+	/* attach BPF program to the probe */
+	return dt_tp_attach(dtp, pp->tp, bpf_fd);
+}
+
+static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
+		      int *argcp, dt_argdesc_t **argvp)
+{
+	*argcp = 0;			/* no arguments */
+	*argvp = NULL;
+
+	return 0;
+}
+
+/*
+ * Try to clean up system resources that may have been allocated for this
+ * probe.
+ *
+ * If there is an event FD, we close it.
+ *
+ * We also try to remove any uprobe that may have been created for the probe.
+ * This is harmless for probes that didn't get created.  If the removal fails
+ * for some reason we are out of luck - fortunately it is not harmful to the
+ * system as a whole.
+ */
+static void detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
+{
+	int		fd;
+	pid_probe_t	*pp = prp->prv_data;
+
+	if (!dt_tp_is_attached(pp->tp))
+		return;
+
+	dt_tp_detach(dtp, pp->tp);
+
+	fd = open(UPROBE_EVENTS, O_WRONLY | O_APPEND);
+	if (fd == -1)
+		return;
+
+	dprintf(fd, "-:" PID_GROUP_FMT "/%s_%s\n", PID_GROUP_DATA,
+		prp->desc->fun, prp->desc->prb);
+	close(fd);
+}
+
+dt_provimpl_t	dt_pid = {
+	.name		= prvname,
+	.prog_type	= BPF_PROG_TYPE_KPROBE,
+	.populate	= &populate,
+	.provide_pid	= &provide_pid,
+	.trampoline	= &trampoline,
+	.attach		= &attach,
+	.probe_info	= &probe_info,
+	.detach		= &detach,
+	.probe_destroy	= &probe_destroy,
+};
+
+dt_provimpl_t	dt_pid_sub = {
+	.name		= prvname,
+	.prog_type	= BPF_PROG_TYPE_KPROBE,
+	.populate	= &populate,
+	.provide_pid	= &provide_pid,
+	.enable		= &enable,
+	.trampoline	= &trampoline,
+};
diff --git a/libdtrace/dt_provider.h b/libdtrace/dt_provider.h
index b8ac9c1e..c7a47d6d 100644
--- a/libdtrace/dt_provider.h
+++ b/libdtrace/dt_provider.h
@@ -8,6 +8,7 @@
 #ifndef	_DT_PROVIDER_H
 #define	_DT_PROVIDER_H
 
+#include <dtrace/pid.h>
 #include <dt_impl.h>
 #include <dt_ident.h>
 #include <dt_list.h>
@@ -63,6 +64,8 @@ typedef struct dt_provimpl {
 		       const dtrace_probedesc_t *pdp);
 	void (*enable)(dtrace_hdl_t *dtp,	/* enable the given probe */
 		       struct dt_probe *prp);
+	int (*provide_pid)(dtrace_hdl_t *dtp,	/* provide PID probes */
+		       const pid_probespec_t *psp);
 	void (*trampoline)(dt_pcb_t *pcb);	/* generate BPF trampoline */
 	int (*attach)(dtrace_hdl_t *dtp,	/* attach BPF prog to probe */
 		      const struct dt_probe *prp, int bpf_fd);
@@ -77,6 +80,7 @@ typedef struct dt_provimpl {
 
 extern dt_provimpl_t dt_dtrace;
 extern dt_provimpl_t dt_fbt;
+extern dt_provimpl_t dt_pid;
 extern dt_provimpl_t dt_profile;
 extern dt_provimpl_t dt_sdt;
 extern dt_provimpl_t dt_syscall;
@@ -117,6 +121,7 @@ extern void dt_tp_probe_destroy(dtrace_hdl_t *dtp, void *datap);
 
 #define	DT_PROVIDER_INTF	0x1	/* provider interface declaration */
 #define	DT_PROVIDER_IMPL	0x2	/* provider implementation is loaded */
+#define DT_PROVIDER_PID		0x4	/* provider is a PID provider */
 
 extern dt_provider_t *dt_provider_lookup(dtrace_hdl_t *, const char *);
 extern dt_provider_t *dt_provider_create(dtrace_hdl_t *, const char *,
diff --git a/test/unittest/pid/tst.addprobes.sh b/test/unittest/pid/tst.addprobes.sh
index 99f6d5be..d12ad201 100755
--- a/test/unittest/pid/tst.addprobes.sh
+++ b/test/unittest/pid/tst.addprobes.sh
@@ -5,7 +5,7 @@
 # Licensed under the Universal Permissive License v 1.0 as shown at
 # http://oss.oracle.com/licenses/upl.
 #
-# @@xfail: dtv2
+# @@skip: not relevant in dtv2
 
 #
 # This test verifies that it's possible to add new pid probes to an existing
diff --git a/test/unittest/pid/tst.args1.d b/test/unittest/pid/tst.args1.d
index 9eecb8b1..c92bf719 100644
--- a/test/unittest/pid/tst.args1.d
+++ b/test/unittest/pid/tst.args1.d
@@ -1,10 +1,10 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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.
  */
-/* @@xfail: dtv2 */
+
 /* @@runtest-opts: $_pid */
 /* @@trigger: pid-tst-args1 */
 /* @@trigger-timing: before */
@@ -58,6 +58,6 @@ pid$1:a.out:go:entry
 profile:::tick-4
 /timestamp > timeout/
 {
-	trace("test timed out");
+	printf("test timed out");
 	exit(1);
 }
diff --git a/test/unittest/pid/tst.coverage.d b/test/unittest/pid/tst.coverage.d
index 54420cc2..9670665a 100644
--- a/test/unittest/pid/tst.coverage.d
+++ b/test/unittest/pid/tst.coverage.d
@@ -1,10 +1,10 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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.
  */
-/* @@xfail: dtv2 */
+
 /* @@runtest-opts: $_pid */
 /* @@trigger: pid-tst-args1 */
 /* @@trigger-timing: before */
diff --git a/test/unittest/pid/tst.float.d b/test/unittest/pid/tst.float.d
index 66de824b..f5ec25ef 100644
--- a/test/unittest/pid/tst.float.d
+++ b/test/unittest/pid/tst.float.d
@@ -1,10 +1,10 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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.
  */
-/* @@xfail: dtv2 */
+
 /* @@runtest-opts: $_pid */
 /* @@trigger: pid-tst-float */
 /* @@trigger-timing: after */
diff --git a/test/unittest/pid/tst.main.sh b/test/unittest/pid/tst.main.sh
index 589414a9..5faafa5f 100755
--- a/test/unittest/pid/tst.main.sh
+++ b/test/unittest/pid/tst.main.sh
@@ -1,11 +1,10 @@
 #!/bin/bash
 #
 # Oracle Linux DTrace.
-# Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 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.
 #
-# @@xfail: dtv2
 
 if [ $# != 1 ]; then
 	echo expected one argument: '<'dtrace-path'>'
diff --git a/test/unittest/pid/tst.manypids.sh b/test/unittest/pid/tst.manypids.sh
index a043c120..8f853c0f 100755
--- a/test/unittest/pid/tst.manypids.sh
+++ b/test/unittest/pid/tst.manypids.sh
@@ -1,11 +1,10 @@
 #!/bin/bash
 #
 # Oracle Linux DTrace.
-# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 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.
 #
-# @@xfail: needs porting
 
 if [ $# != 1 ]; then
 	echo expected one argument: '<'dtrace-path'>'
diff --git a/test/unittest/pid/tst.probemod.sh b/test/unittest/pid/tst.probemod.sh
index 29a4b34b..ef278b9e 100755
--- a/test/unittest/pid/tst.probemod.sh
+++ b/test/unittest/pid/tst.probemod.sh
@@ -1,11 +1,10 @@
 #!/bin/bash
 #
 # Oracle Linux DTrace.
-# Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 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.
 #
-# @@xfail: dtv2
 
 if [ $# != 1 ]; then
 	echo expected one argument: '<'dtrace-path'>'
@@ -22,7 +21,7 @@ dtrace=$1
 # First we need to determine the basename of the linked libc for
 # sleep(1)
 #
-names=`ldd /usr/bin/sleep | \
+names=`ldd /bin/sleep | \
 	awk '/libc.so/ {
 		n = split($1, a, /\./);
 		l = a[1];
@@ -38,7 +37,7 @@ for lib in $names; do
 	sleep 60 &
 	pid=$!
 	disown %+
-	$dtrace $dt_flags -n "pid$pid:$lib::entry" -n 'tick-2s{exit(0);}'
+	$dtrace $dt_flags -n "pid$pid:$lib:malloc*:entry" -n 'tick-2s{exit(0);}'
 	status=$?
 
 	kill $pid
diff --git a/test/unittest/pid/tst.provregex1.sh b/test/unittest/pid/tst.provregex1.sh
index 41c5b7b3..c672b23f 100755
--- a/test/unittest/pid/tst.provregex1.sh
+++ b/test/unittest/pid/tst.provregex1.sh
@@ -1,14 +1,13 @@
 #!/bin/bash
 #
 # Oracle Linux DTrace.
-# Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 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.
 #
 # This test verifies that specifying a glob in a pid provider name
 # (e.g., p*d$target) works.
 #
-# @@xfail: dtv2
 
 if [ $# != 1 ]; then
 	echo expected one argument: '<'dtrace-path'>'
diff --git a/test/unittest/usdt/tst.dlclose3.sh b/test/unittest/usdt/tst.dlclose3.sh
index e206d216..0a98608f 100755
--- a/test/unittest/usdt/tst.dlclose3.sh
+++ b/test/unittest/usdt/tst.dlclose3.sh
@@ -1,11 +1,10 @@
 #!/bin/bash
 #
 # Oracle Linux DTrace.
-# Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 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.
 #
-# @@xfail: dtv2
 
 #
 # This test verifies that performing a dlclose(3dl) on a library doesn't
-- 
2.28.0




More information about the DTrace-devel mailing list