[DTrace-devel] [PATCH 09/14] Systemwide USDT WIP
eugene.loh at oracle.com
eugene.loh at oracle.com
Tue Jun 4 18:11:08 UTC 2024
From: Eugene Loh <eugene.loh at oracle.com>
need to:
- review tests
- add process monitoring
- deal with FIXMEs
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
libdtrace/dt_cc.c | 3 +-
libdtrace/dt_pid.c | 136 +++++++++++++++---
libdtrace/dt_prov_uprobe.c | 1 +
.../dtrace-util/tst.ListProbesNameUSDT.sh | 1 -
.../dtrace-util/tst.ListProbesProviderUSDT.sh | 1 -
5 files changed, 122 insertions(+), 20 deletions(-)
diff --git a/libdtrace/dt_cc.c b/libdtrace/dt_cc.c
index 6bff7e0f..eddf8252 100644
--- a/libdtrace/dt_cc.c
+++ b/libdtrace/dt_cc.c
@@ -279,7 +279,8 @@ dt_setcontext(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
* and tag -- we just have to longjmp() out of here.
*/
if (pdp->prv && pdp->prv[0] &&
- isdigit(pdp->prv[strlen(pdp->prv) - 1]) &&
+ (isdigit(pdp->prv[strlen(pdp->prv) - 1]) ||
+ pdp->prv[strlen(pdp->prv) - 1] == '*') &&
((pvp = dt_provider_lookup(dtp, pdp->prv)) == NULL ||
pvp->pv_flags & DT_PROVIDER_PID) &&
dt_pid_create_probes((dtrace_probedesc_t *)pdp, dtp, yypcb) != 0) {
diff --git a/libdtrace/dt_pid.c b/libdtrace/dt_pid.c
index 93a7ce76..e07a3a4b 100644
--- a/libdtrace/dt_pid.c
+++ b/libdtrace/dt_pid.c
@@ -780,8 +780,8 @@ validate_dof_record(const char *path, const dof_parsed_t *parsed,
/*
* Create underlying probes relating to the probespec passed on input.
*
- * If dpr is set, just set up probes relating to mappings found in that one
- * process. (dpr must in this case be locked.)
+ * dpr must be set and locked. Just set up probes relating to mappings found
+ * in this one process.
*
* Return 0 on success or -1 on error. (Failure to create specific underlying
* probes is not an error.)
@@ -795,9 +795,6 @@ dt_pid_create_usdt_probes(dtrace_hdl_t *dtp, dt_proc_t *dpr, dtrace_probedesc_t
char *probepath = NULL;
glob_t probeglob = {0};
- /*
- * Systemwide probing: not yet implemented.
- */
assert(dpr != NULL && dpr->dpr_proc);
assert(MUTEX_HELD(&dpr->dpr_lock));
@@ -1104,22 +1101,96 @@ dt_pid_get_pid(const dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb,
return pid;
}
+static char *
+convert_pidglob(char *s) // FIXME expect const char *?
+{
+ /*
+ * Convert a glob for "pid[1-9][0-9]*" into one for just the numerical
+ * portion. It will always be a subset of the input string. A NULL
+ * pointer is returned if there is no such string -- e.g., if the input
+ * string is "foo1234".
+ *
+ * There is no need to check the entire string for legality. E.g., if
+ * the input string is "pid*q*", we can simply return "*q*". Then, this
+ * string will not match any "[1-9][0-9]*"; we do not need to intervene.
+ */
+ char *p;
+ int nchars = 0; /* number of chars of "pid" we have seen so far */
+
+ for (p = s; ; p++) {
+ switch (*p) {
+// FIXME: I think this passes stuff like "pd1234", "id1234" etc. So make sure 'p' 'i' and 'd' are hit or else there is a '*' to jump over them.
+ case 'p':
+ if (nchars > 0)
+ return NULL;
+ nchars = 1;
+ break;
+ case 'i':
+ if (nchars > 1)
+ return NULL;
+ nchars = 2;
+ break;
+ case 'd':
+ if (nchars > 2)
+ return NULL;
+ nchars = 3;
+ break;
+ case '*':
+ break;
+ case '\0':
+ if (p == s)
+ return NULL;
+ if (*(p - 1) != '*')
+ return p;
+ return p - 1;
+ default:
+ if (*p < '0' || *p > '9')
+ return NULL;
+ if (p == s)
+ return NULL;
+ if (*(p - 1) != '*')
+ return p;
+ return p - 1;
+ }
+ }
+}
+
int
dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
{
- char provname[DTRACE_PROVNAMELEN];
dt_proc_t *dpr;
pid_t pid;
- int err = 0;
+ int err = 0, i, nmatches = 0;
+ glob_t globbuf;
+ char globpat[256]; // FIXME hardwired size
assert(pcb != NULL);
- if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1)
+ /* Exclude pid0 from being specifically requested. */
+ if (strcmp(pdp->prv, "pid0") == 0) {
+ dt_pid_error(dtp, pcb, NULL, D_PROC_BADPID,
+ "pid0 does not contain a valid pid");
return -1;
+ }
+
+ /*
+ * Try pid probes.
+ */
+ sprintf(globpat, "/proc/%s/map_files", convert_pidglob(pdp->prv));
+ nmatches = glob(globpat, 0, NULL, &globbuf) ? 0 : globbuf.gl_pathc;
+ for (i = 0; i < nmatches; i++) {
+ if (strncmp(globbuf.gl_pathv[i], "/proc/self", 10) == 0)
+ continue;
- snprintf(provname, sizeof(provname), "pid%d", (int)pid);
+ pid = strtol(globbuf.gl_pathv[i] + strlen("/proc/"), NULL, 10); // FIXME need error checking or anything?
+
+#if 1
+ // FIXME: omit this check?
+ char provname[DTRACE_PROVNAMELEN];
+ snprintf(provname, sizeof(provname), "pid%d", (int)pid);
+ assert(gmatch(provname, pdp->prv) != 0);
+#endif
- if (gmatch(provname, pdp->prv) != 0) {
if (dt_proc_grab_lock(dtp, pid, DTRACE_PROC_WAITING) < 0) {
dt_pid_error(dtp, pcb, NULL, D_PROC_GRAB,
"failed to grab process %d", (int)pid);
@@ -1129,14 +1200,45 @@ dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
dpr = dt_proc_lookup(dtp, pid);
assert(dpr != NULL);
- err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr);
+ // FIXME handle err better
+ err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr); // FIXME rename to dt_pid_create_pid_probe()?
dt_proc_release_unlock(dtp, pid);
}
+ globfree(&globbuf);
/*
- * If it's not strictly a pid provider, we might match a USDT provider.
+ * Try USDT probes.
*/
- if (strcmp(provname, pdp->prv) != 0) {
+ sprintf(globpat, "%s/probes/*/%s/%s/%s/%s", dtp->dt_dofstash_path,
+ pdp->prv,
+ pdp->mod[0] == '\0' ? "*" : pdp->mod,
+ pdp->fun[0] == '\0' ? "*" : pdp->fun,
+ pdp->prb[0] == '\0' ? "*" : pdp->prb);
+ nmatches = glob(globpat, 0, NULL, &globbuf) ? 0 : globbuf.gl_pathc;
+
+ for (i = 0; i < nmatches; i++) {
+ char *s = strdup(globbuf.gl_pathv[i] + strlen(dtp->dt_dofstash_path) + strlen("/probes/"));
+ // FIXME: do we really need to strdup/free this, or can modify in-place?
+ char *p = strchr(s, '/'), *q;
+ char nullchar = '\0';
+ dtrace_probedesc_t pdptmp;
+
+ *p = '\0';
+ p++;
+ q = strchr(p, '/');
+ *q = '\0'; q++;
+// FIXME should also check dof_version, though that doesn't do much yet
+ pid = atoll(s);
+
+ // Check, since dtprobed takes a while to clean up dead processes.
+ if (!Pexists(pid))
+ continue;
+
+ pdptmp.prv = p;
+ pdptmp.mod = &nullchar; pdptmp.mod = q; q = strchr(q, '/'); *q = '\0'; q++;
+ pdptmp.fun = &nullchar; pdptmp.fun = q; q = strchr(q, '/'); *q = '\0'; q++;
+ pdptmp.prb = &nullchar; pdptmp.prb = q;
+
if (dt_proc_grab_lock(dtp, pid, DTRACE_PROC_WAITING |
DTRACE_PROC_SHORTLIVED) < 0) {
dt_pid_error(dtp, pcb, NULL, D_PROC_GRAB,
@@ -1147,17 +1249,17 @@ dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
dpr = dt_proc_lookup(dtp, pid);
assert(dpr != NULL);
- err = dt_pid_create_usdt_probes(dtp, dpr, pdp, pcb);
+ err = dt_pid_create_usdt_probes(dtp, dpr, &pdptmp, pcb); // FIXME: we care about not just the last err
/*
* Put the module name in its canonical form.
*/
- dt_pid_fix_mod(NULL, pdp, dtp, dpr->dpr_pid);
+ dt_pid_fix_mod(NULL, &pdptmp, dtp, dpr->dpr_pid);
dt_proc_release_unlock(dtp, pid);
+ free(s);
}
-
- /* (USDT systemwide probing goes here.) */
+ globfree(&globbuf);
return err ? -1 : 0;
}
diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
index cb79e0a3..618219b8 100644
--- a/libdtrace/dt_prov_uprobe.c
+++ b/libdtrace/dt_prov_uprobe.c
@@ -766,6 +766,7 @@ static int trampoline_is_enabled(dt_pcb_t *pcb, uint_t exitlbl)
emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_0, pid, lbl_assign));
}
emit(dlp, BPF_JUMP(lbl_exit));
+
copyout_val(pcb, lbl_assign, 1, 0);
dt_cg_tramp_return(pcb);
diff --git a/test/unittest/dtrace-util/tst.ListProbesNameUSDT.sh b/test/unittest/dtrace-util/tst.ListProbesNameUSDT.sh
index c5dfc72b..9d8f06e9 100755
--- a/test/unittest/dtrace-util/tst.ListProbesNameUSDT.sh
+++ b/test/unittest/dtrace-util/tst.ListProbesNameUSDT.sh
@@ -5,7 +5,6 @@
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.
#
-# @@xfail: dtv2
##
#
diff --git a/test/unittest/dtrace-util/tst.ListProbesProviderUSDT.sh b/test/unittest/dtrace-util/tst.ListProbesProviderUSDT.sh
index 644da2ac..6eae82ed 100755
--- a/test/unittest/dtrace-util/tst.ListProbesProviderUSDT.sh
+++ b/test/unittest/dtrace-util/tst.ListProbesProviderUSDT.sh
@@ -5,7 +5,6 @@
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.
#
-# @@xfail: dtv2
##
#
--
2.18.4
More information about the DTrace-devel
mailing list