[DTrace-devel] [PATCH] add BEGIN and END probes
eugene.loh at oracle.com
eugene.loh at oracle.com
Sat Mar 21 13:39:16 PDT 2020
From: Eugene Loh <eugene.loh at oracle.com>
Add BEGIN and END probes as uprobes on libdtrace functions
BEGIN_probe() and END_probe(), which were added as part of an earlier
patch.
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
libdtrace/dt_prov_dtrace.c | 116 +++++++++++++++++++++++++++++++++----
libdtrace/dt_prov_fbt.c | 2 +-
2 files changed, 107 insertions(+), 11 deletions(-)
diff --git a/libdtrace/dt_prov_dtrace.c b/libdtrace/dt_prov_dtrace.c
index b2327dc2..699541c9 100644
--- a/libdtrace/dt_prov_dtrace.c
+++ b/libdtrace/dt_prov_dtrace.c
@@ -7,6 +7,7 @@
* The core probe provider for DTrace for the BEGIN, END, and ERROR probes.
*/
#include <assert.h>
+#include <errno.h>
#include <string.h>
#include <bpf_asm.h>
@@ -22,7 +23,101 @@ static const dtrace_pattr_t pattr = {
{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
};
-static int dtrace_populate(dtrace_hdl_t *dtp)
+#define UPROBE_EVENTS TRACEFS "uprobe_events"
+
+static int dt_get_uprobe(char *dtrace_probe_name, char *uprobe_name, int len) {
+ struct ps_prochandle *P;
+ int perr = 0, rc = 1;
+ GElf_Sym sym;
+ prsyminfo_t si;
+ prmap_t *pmptr;
+
+ P = Pgrab(getpid(), 2, 0, NULL, &perr);
+ if (P == NULL)
+ return 1; /* FIXME: do something with perr? */
+
+ if (Pxlookup_by_name(P, -1, PR_OBJ_EVERY, dtrace_probe_name, &sym, &si))
+ goto done;
+
+ pmptr = Paddr_to_map(P, sym.st_value);
+ if (pmptr == NULL)
+ goto done;
+
+ if (snprintf(uprobe_name, len, "%s:0x%lx", pmptr->pr_file->prf_mapname, sym.st_value - pmptr->pr_vaddr) >= len)
+ goto done;
+
+ rc = 0;
+
+done:
+ Prelease(P, PS_RELEASE_NORMAL);
+ Pfree(P);
+ return rc;
+}
+
+static int dtrace_prov_probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
+ int *idp, int *argcp, dt_argdesc_t **argvp)
+{
+ FILE *f;
+ int rc = 0;
+ char probe_name[256];
+ char s[256];
+
+ *idp = -1;
+
+ if (snprintf(probe_name, sizeof (probe_name), "%s_probe", prp->desc->prb) >= sizeof (probe_name)) {
+ assert(0);
+ }
+
+ /*
+ * We check to see if the event already exists in the tracing
+ * sub-system. If not, we try to register the probe with the tracing
+ * sub-system, and try accessing it again.
+ */
+again:
+ /*
+ * FIXME: gcc complains:
+ * warning: ‘%s’ directive output may be truncated writing up to 255 bytes
+ * into a region of size 215 [-Wformat-truncation=]
+ * note: ‘snprintf’ output between 49 and 304 bytes into a destination of size 256
+ * How do we make this complaint go away? Checking the snprintf()
+ * return value against the size of the buffer was supposed to do this.
+ */
+ if (snprintf(s, sizeof (s), "%suprobes/%s/format", EVENTSFS, probe_name) >= sizeof (s)) {
+ /* FIXME: now what? */
+ }
+ f = fopen(s, "r");
+ if (f == NULL) {
+ int fd;
+ char uprobe_name[256];
+
+ if (rc)
+ goto out;
+
+ rc = -ENOENT;
+
+ /* FIXME: check return value */
+ dt_get_uprobe(probe_name, uprobe_name, sizeof (uprobe_name));
+
+ fd = open(UPROBE_EVENTS, O_WRONLY | O_APPEND);
+ if (fd == -1)
+ goto out;
+
+ dprintf(fd, "p:uprobes/%s %s\n", probe_name, uprobe_name);
+ close(fd);
+
+ goto again;
+ }
+
+ *argcp = 0;
+ *argvp = NULL;
+ rc = tp_event_info(dtp, f, 0, idp, NULL, NULL);
+ fclose(f);
+
+out:
+ return rc;
+}
+
+static int dtrace_prov_populate(dtrace_hdl_t *dtp)
{
dt_provider_t *prv;
int n = 0;
@@ -42,7 +137,7 @@ static int dtrace_populate(dtrace_hdl_t *dtp)
}
/*
-* Generate a BPF trampoline for a dtrace probe (BEGIN, END, or ERROR).
+ * Generate a BPF trampoline for a dtrace probe (BEGIN, END, or ERROR).
*
* The trampoline function is called when a dtrace probe triggers, and it must
* satisfy the following prototype:
@@ -53,7 +148,7 @@ static int dtrace_populate(dtrace_hdl_t *dtp)
* function that implements tha compiled D clause. It returns the value that
* it gets back from that function.
*/
-static void dtrace_trampoline(dt_pcb_t *pcb, int haspred)
+static void dtrace_prov_trampoline(dt_pcb_t *pcb, int haspred)
{
int i;
dt_irlist_t *dlp = &pcb->pcb_ir;
@@ -183,7 +278,7 @@ static void dtrace_trampoline(dt_pcb_t *pcb, int haspred)
}
/*
- * rc = dt_program(scd, dctx);
+ * rc = dt_program(regs, dctx);
*/
idp = dt_dlib_get_func(pcb->pcb_hdl, "dt_program");
assert(idp != NULL);
@@ -208,7 +303,7 @@ static void dtrace_trampoline(dt_pcb_t *pcb, int haspred)
* ELF section name). We use an unused event group (dtrace) to be able to
* fake a section name that libbpf will allow us to use.
*/
-static struct dt_probe *dtrace_resolve_event(const char *name)
+static struct dt_probe *dtrace_prov_resolve_event(const char *name)
{
struct dt_probe tmpl;
struct dt_probe *probe;
@@ -232,7 +327,7 @@ static struct dt_probe *dtrace_resolve_event(const char *name)
return probe;
}
-static int dtrace_attach(const char *name, int bpf_fd)
+static int dtrace_prov_attach(const char *name, int bpf_fd)
{
return -1;
}
@@ -241,10 +336,11 @@ static int dtrace_attach(const char *name, int bpf_fd)
dt_provimpl_t dt_dtrace = {
.name = "dtrace",
.prog_type = BPF_PROG_TYPE_KPROBE,
- .populate = &dtrace_populate,
- .trampoline = &dtrace_trampoline,
+ .populate = &dtrace_prov_populate,
+ .trampoline = &dtrace_prov_trampoline,
#if 0
- .resolve_event = &dtrace_resolve_event,
- .attach = &dtrace_attach,
+ .resolve_event = &dtrace_prov_resolve_event,
+ .attach = &dtrace_prov_attach,
#endif
+ .probe_info = &dtrace_prov_probe_info,
};
diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
index cfaad8af..3262449c 100644
--- a/libdtrace/dt_prov_fbt.c
+++ b/libdtrace/dt_prov_fbt.c
@@ -356,7 +356,7 @@ static void fbt_trampoline(dt_pcb_t *pcb, int haspred)
}
/*
- * rc = dt_program(scd, dctx);
+ * rc = dt_program(regs, dctx);
*/
idp = dt_dlib_get_func(pcb->pcb_hdl, "dt_program");
assert(idp != NULL);
--
2.18.2
More information about the DTrace-devel
mailing list