[DTrace-devel] [PATCH v2] sdt: consolidate the SDT infrastructure in its own provider framework
Kris Van Hees
kris.van.hees at oracle.com
Thu May 18 19:30:35 UTC 2023
The various SDT providers are implemented using the same underlying
mechanisms. A common SDT infrastructure avoids code duplication.
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
libdtrace/Build | 1 +
libdtrace/dt_provider_sdt.c | 165 ++++++++++++++++++++++++++++++++++++
libdtrace/dt_provider_sdt.h | 61 +++++++++++++
3 files changed, 227 insertions(+)
create mode 100644 libdtrace/dt_provider_sdt.c
create mode 100644 libdtrace/dt_provider_sdt.h
diff --git a/libdtrace/Build b/libdtrace/Build
index 299cb128..89972c66 100644
--- a/libdtrace/Build
+++ b/libdtrace/Build
@@ -57,6 +57,7 @@ libdtrace-build_SOURCES = dt_aggregate.c \
dt_prov_syscall.c \
dt_prov_uprobe.c \
dt_provider.c \
+ dt_provider_sdt.c \
dt_provider_tp.c \
dt_regset.c \
dt_string.c \
diff --git a/libdtrace/dt_provider_sdt.c b/libdtrace/dt_provider_sdt.c
new file mode 100644
index 00000000..ebd8b107
--- /dev/null
+++ b/libdtrace/dt_provider_sdt.c
@@ -0,0 +1,165 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, 2023, 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.
+ *
+ * Provider support code for tracepoint-based probes.
+ */
+#include <errno.h>
+#include <ctype.h>
+
+#include "dt_provider_sdt.h"
+#include "dt_probe.h"
+#include "dt_impl.h"
+
+typedef struct sdt_data {
+ const probe_dep_t *probes;
+ const probe_arg_t *probe_args;
+} sdt_data_t;
+
+/*
+ * Create an SDT provider and populate it from the provided list of probes
+ * (with dependency information) and probe argument data.
+ */
+int
+dt_sdt_populate(dtrace_hdl_t *dtp, const char *prvname, const char *modname,
+ const dt_provimpl_t *ops, const dtrace_pattr_t *pattr,
+ const probe_arg_t *probe_args, const probe_dep_t *probes)
+{
+ dt_provider_t *prv;
+ const probe_arg_t *arg;
+ sdt_data_t *sdp;
+ int n = 0;
+
+ sdp = dt_alloc(dtp, sizeof(sdt_data_t));
+ if (sdp == NULL)
+ return 0;
+
+ sdp->probes = probes;
+ sdp->probe_args = probe_args;
+ prv = dt_provider_create(dtp, prvname, ops, pattr, sdp);
+ if (prv == NULL)
+ return 0;
+
+ /*
+ * Create SDT probes based on the probe_args list. Since each probe
+ * will have at least one entry (with argno == 0), we can use those
+ * entries to identify the probe names.
+ */
+ for (arg = &probe_args[0]; arg->name != NULL; arg++) {
+ if (arg->argno == 0 &&
+ dt_probe_insert(dtp, prv, prvname, modname, "", arg->name,
+ NULL))
+ n++;
+ }
+
+ return n;
+}
+
+/*
+ * Add an SDT probe as a dependent probe for an underlying probe that has been
+ * provided by another provider.
+ */
+static int
+add_dependency(dtrace_hdl_t *dtp, dt_probe_t *uprp, void *arg)
+{
+ dt_probe_t *prp = arg;
+
+ dt_probe_add_dependent(dtp, uprp, prp);
+ dt_probe_enable(dtp, uprp);
+
+ return 0;
+}
+
+/*
+ * Enable an SDT probe.
+ */
+void
+dt_sdt_enable(dtrace_hdl_t *dtp, dt_probe_t *prp)
+{
+ const probe_dep_t *dep;
+
+ for (dep = ((sdt_data_t *)prp->prov->prv_data)->probes;
+ dep->name != NULL; dep++) {
+ dtrace_probedesc_t pd;
+
+ if (strcmp(prp->desc->prb, dep->name) != 0)
+ continue;
+
+ if (dtrace_str2desc(dtp, dep->spec, dep->str, &pd) == -1)
+ return;
+
+ dt_probe_iter(dtp, &pd, add_dependency, NULL, prp);
+
+ free((void *)pd.prv);
+ free((void *)pd.mod);
+ free((void *)pd.fun);
+ free((void *)pd.prb);
+ }
+
+ /*
+ * Finally, ensure we're in the list of enablings as well.
+ * (This ensures that, among other things, the probes map
+ * gains entries for us.)
+ */
+ if (!dt_in_list(&dtp->dt_enablings, prp))
+ dt_list_append(&dtp->dt_enablings, prp);
+}
+
+/*
+ * Populate the probe arguments for the given probe.
+ */
+int
+dt_sdt_probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp, int *argcp,
+ dt_argdesc_t **argvp)
+{
+ int i;
+ int pidx = -1;
+ int argc = 0;
+ dt_argdesc_t *argv = NULL;
+ const probe_arg_t *probe_args =
+ ((sdt_data_t *)prp->prov->prv_data)->probe_args;
+ const probe_arg_t *arg;
+
+ for (arg = &probe_args[i = 0]; arg->name != NULL; arg++, i++) {
+ if (strcmp(arg->name, prp->desc->prb) == 0) {
+ if (pidx == -1) {
+ pidx = i;
+
+ if (arg->argdesc.native == NULL)
+ break;
+ }
+
+ argc++;
+ }
+ }
+
+ if (argc == 0)
+ goto done;
+
+ argv = dt_zalloc(dtp, argc * sizeof(dt_argdesc_t));
+ if (!argv)
+ return -ENOMEM;
+
+ for (i = pidx; i < pidx + argc; i++) {
+ const probe_arg_t *arg = &probe_args[i];
+
+ argv[arg->argno] = arg->argdesc;
+ }
+
+done:
+ *argcp = argc;
+ *argvp = argv;
+
+ return 0;
+}
+
+/*
+ * Clean up SDT-specific data.
+ */
+void
+dt_sdt_destroy(dtrace_hdl_t *dtp, void *datap)
+{
+ dt_free(dtp, datap);
+}
diff --git a/libdtrace/dt_provider_sdt.h b/libdtrace/dt_provider_sdt.h
new file mode 100644
index 00000000..86f3b84b
--- /dev/null
+++ b/libdtrace/dt_provider_sdt.h
@@ -0,0 +1,61 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2023, 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.
+ */
+
+#ifndef _DT_PROVIDER_SDT_H
+#define _DT_PROVIDER_SDT_H
+
+#include <sys/dtrace_types.h>
+#include <dt_provider.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Probe dependencies
+ *
+ * SDT probes are implemented using probes made available by other providers.
+ * THe probe dependency table associates each SDT probe with one or more probe
+ * specifications (possibly containing wildcards). Each matching probe will
+ * have SDT lockstat probe added as a dependent probe.
+ */
+typedef struct probe_dep {
+ const char *name; /* probe name */
+ dtrace_probespec_t spec; /* spec type */
+ const char *str; /* spec string */
+} probe_dep_t;
+
+/*
+ * Probe signature specifications
+ *
+ * This table *must* group the arguments of probes. I.e. the arguments of a
+ * given probe must be listed in consecutive records.
+ *
+ * A single probe entry that mentions only name of the probe indicates a probe
+ * that provides no arguments.
+ */
+typedef struct probe_arg {
+ const char *name; /* name of probe */
+ int argno; /* argument number */
+ dt_argdesc_t argdesc; /* argument description */
+} probe_arg_t;
+
+extern int dt_sdt_populate(dtrace_hdl_t *dtp, const char *prvname,
+ const char *modname, const dt_provimpl_t *ops,
+ const dtrace_pattr_t *pattr,
+ const probe_arg_t *probe_args,
+ const probe_dep_t *probes);
+extern void dt_sdt_enable(dtrace_hdl_t *dtp, struct dt_probe *prp);
+extern int dt_sdt_probe_info(dtrace_hdl_t *dtp, const struct dt_probe *prp,
+ int *argcp, dt_argdesc_t **argvp);
+extern void dt_sdt_destroy(dtrace_hdl_t *dtp, void *datap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DT_PROVIDER_SDT_H */
--
2.40.1
More information about the DTrace-devel
mailing list