[DTrace-devel] [PATCH 04/04] rawtp: retrieve probe arguments from CTF data
Kris Van Hees
kris.van.hees at oracle.com
Wed Nov 22 15:49:55 UTC 2023
We were determining the number of arguments using a trial-and-error
approach using mimnimal BPF programs. If there is CTF type data for
the raw tracepoints (in the form of a function prototype), we use
that because it also gives us the types of the arguuments.
If no such CTF data is available, we fallback to the trial-and-error
approach.
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
libdtrace/dt_prov_rawtp.c | 83 +++++++++++++++++--
.../rawtp/tst.lv-sched_process_fork.r | 16 ++++
.../rawtp/tst.lv-sched_process_fork.r.p | 5 ++
.../rawtp/tst.lv-sched_process_fork.sh | 11 +++
4 files changed, 110 insertions(+), 5 deletions(-)
create mode 100644 test/unittest/providers/rawtp/tst.lv-sched_process_fork.r
create mode 100755 test/unittest/providers/rawtp/tst.lv-sched_process_fork.r.p
create mode 100755 test/unittest/providers/rawtp/tst.lv-sched_process_fork.sh
diff --git a/libdtrace/dt_prov_rawtp.c b/libdtrace/dt_prov_rawtp.c
index c2d75150..67cc4319 100644
--- a/libdtrace/dt_prov_rawtp.c
+++ b/libdtrace/dt_prov_rawtp.c
@@ -157,8 +157,14 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
return 0;
}
-static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
- int *argcp, dt_argdesc_t **argvp)
+/*
+ * If there is no btf_trace_* prototype available in CTF, we can still probe
+ * the number of available argument for a raw tracepoint by means of a trial
+ * and error loop to see what the highest argument index is that the BPF
+ * verifier allows us to load from.
+ */
+static int probe_info_bpf(dtrace_hdl_t *dtp, const dt_probe_t *prp,
+ int *argcp, dt_argdesc_t **argvp)
{
int argc, i;
dt_argdesc_t *argv = NULL;
@@ -205,10 +211,77 @@ static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
}
done:
- *argcp = argc;
- *argvp = argv;
+ *argcp = argc;
+ *argvp = argv;
+
+ return 0;
+}
+
+static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
+ int *argcp, dt_argdesc_t **argvp)
+{
+ int rc, i;
+ char *str;
+ ctf_dict_t *ctfp;
+ ctf_id_t type;
+ int argc = 0;
+ dt_argdesc_t *argv = NULL;
+ ctf_funcinfo_t fi;
+ dtrace_typeinfo_t sym;
+ ctf_id_t *argt;
+
+ if (asprintf(&str, "btf_trace_%s", prp->desc->prb) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
+ rc = dtrace_lookup_by_type(dtp, DTRACE_OBJ_EVERY, str, &sym);
+ free(str);
+ if (rc ||
+ ctf_type_kind(sym.dtt_ctfp, sym.dtt_type) != CTF_K_TYPEDEF)
+ goto use_alt;
+
+ ctfp = sym.dtt_ctfp;
+ type = ctf_type_reference(ctfp, sym.dtt_type);
+ if (ctf_type_kind(ctfp, type) != CTF_K_POINTER)
+ goto use_alt;
+ type = ctf_type_reference(ctfp, type);
+ if (ctf_type_kind(ctfp, type) != CTF_K_FUNCTION)
+ goto use_alt;
+ if (ctf_func_type_info(ctfp, type, &fi) == -1)
+ goto use_alt;
+
+ /*
+ * Raw tracepoints have an extra first argument for the context, so we
+ * need to skip that. (We also handle the case where fi.ctc_argc is 0
+ * even though that is not supposed to happen.)
+ */
+ if (fi.ctc_argc <= 1)
+ goto done;
+
+ argc = fi.ctc_argc;
+ argt = dt_calloc(dtp, argc, sizeof(ctf_id_t));
+ ctf_func_type_args(ctfp, type, argc, argt);
+
+ argc--;
+ argv = dt_zalloc(dtp, argc * sizeof(dt_argdesc_t));
+
+ for (i = 0; i < argc; i++) {
+ char n[DT_TYPE_NAMELEN];
+
+ ctf_type_name(ctfp, argt[i + 1], n, sizeof(n));
+ argv[i].mapping = i;
+ argv[i].native = strdup(n);
+ argv[i].xlate = NULL;
+ }
+
+ free(argt);
+
+done:
+ *argcp = argc;
+ *argvp = argv;
+
+ return 0;
- return 0;
+use_alt:
+ return probe_info_bpf(dtp, prp, argcp, argvp);
}
dt_provimpl_t dt_rawtp = {
diff --git a/test/unittest/providers/rawtp/tst.lv-sched_process_fork.r b/test/unittest/providers/rawtp/tst.lv-sched_process_fork.r
new file mode 100644
index 00000000..c099f70d
--- /dev/null
+++ b/test/unittest/providers/rawtp/tst.lv-sched_process_fork.r
@@ -0,0 +1,16 @@
+PROBE rawtp sched sched_process_fork
+
+ Probe Description Attributes
+ Identifier Names: Private
+ Data Semantics: Private
+ Dependency Class: Unknown
+
+ Argument Attributes
+ Identifier Names: Private
+ Data Semantics: Private
+ Dependency Class: ISA
+
+ Argument Types
+ args[0]: struct task_struct *
+ args[1]: struct task_struct *
+
diff --git a/test/unittest/providers/rawtp/tst.lv-sched_process_fork.r.p b/test/unittest/providers/rawtp/tst.lv-sched_process_fork.r.p
new file mode 100755
index 00000000..c538e345
--- /dev/null
+++ b/test/unittest/providers/rawtp/tst.lv-sched_process_fork.r.p
@@ -0,0 +1,5 @@
+#!/usr/bin/awk -f
+NR == 1 { next; }
+NR == 2 { print "PROBE", $2, $3, $NF; next; }
+/^ *[0-9]+/ { exit; }
+{ print; }
diff --git a/test/unittest/providers/rawtp/tst.lv-sched_process_fork.sh b/test/unittest/providers/rawtp/tst.lv-sched_process_fork.sh
new file mode 100755
index 00000000..bbfb7749
--- /dev/null
+++ b/test/unittest/providers/rawtp/tst.lv-sched_process_fork.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# 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.
+
+dtrace=$1
+
+$dtrace $dt_flags -lvn rawtp:::sched_process_fork
+exit $?
--
2.39.3
More information about the DTrace-devel
mailing list