[DTrace-devel] [PATCH 10/14] Fix the consumer's picture of the EPID
eugene.loh at oracle.com
eugene.loh at oracle.com
Tue Jun 4 18:11:09 UTC 2024
From: Eugene Loh <eugene.loh at oracle.com>
THIS PATCH IS BACKED OUT BY THE PATCH THAT IMMEDIATELY SUCCEEDS IT!
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
libdtrace/dt_prov_uprobe.c | 80 +++++++++++++++++++++++++++++++++++++-
1 file changed, 79 insertions(+), 1 deletion(-)
diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
index 618219b8..83acb7a4 100644
--- a/libdtrace/dt_prov_uprobe.c
+++ b/libdtrace/dt_prov_uprobe.c
@@ -498,7 +498,7 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
dt_irlist_t *dlp = &pcb->pcb_ir;
const dt_probe_t *uprp = pcb->pcb_probe;
const dt_uprobe_t *upp = uprp->prv_data;
-// const list_probe_t *pop;
+ const list_probe_t *pop;
uint_t lbl_exit = pcb->pcb_exitlbl;
dt_cg_tramp_prologue(pcb);
@@ -585,6 +585,84 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
emit(dlp, BPF_CALL_HELPER(BPF_FUNC_map_lookup_elem));
emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_0, 0, lbl_exit));
+#if 1
+/*
+ * Here is a big hack. I hope I understand and explain it correctly.
+ *
+ * DTrace's underlying model is that each EPID represents a combination
+ * of PRID and clause. EPIDs are enumerated so that, for a given EPID,
+ * the consumer can look up which PRID to use. A clause sets its EPID
+ * to some placeholder value.
+ *
+ * During dt_bpf_load_progs(), each probe's BPF program is loaded into
+ * the kernel. Each clause it calls is likewise loaded. Each time a
+ * clause is loaded for a probe, a new EPID is assigned. Clause code
+ * undergoes relocation, and the placeholder EPID value is replaced with
+ * the newly assigned EPID value.
+ *
+ * What's tricky is that the BPF code and the consumer get their PRID
+ * values from different places. While producer might send a PRID value
+ * to the consumer -- e.g., with "trace(id)" -- usually what happens is:
+ *
+ * - BPF code has PRID set in the trampoline, to a value that
+ * is set during relocation
+ *
+ * - the consumer sees the EPID for a record and looks up the
+ * associated PRID, that association made during relocation
+ *
+ * Specifically, during dt_link_construct(), when a new
+ * clause is added, the PRID is associated with the new
+ * EPID through a dt_epid_add() call.
+ *
+ * Further, if an underlying probe trampoline needs to call
+ * clauses for an overlying probe, then dt_link_construct()
+ * watches -- for idp->di_kind==DT_IDENT_SCALAR and
+ * idp->di_id default -- for any overlying probe specification,
+ * switching the prid to the new value.
+ *
+ * We are now changing our USDT support. The PRID is longer set in the
+ * trampoline to a value known at relocation. Rather, the trampoline
+ * now looks a PRID up at run time in a BPF map. The side effect of
+ * associating a PRID with an EPID during relocation is lost. An EPID
+ * could be associated with multiple PRIDs.
+ *
+ * A variety of solutions are possible.
+ *
+ * For example, the BPF map could be keyed on pid, clause, and uprobe.
+ * The output value could be a PRID and EPID for the clause. Clearly,
+ * this would take more BPF map space and more lookups than the current
+ * bitmap approach.
+ *
+ * Here, a different approach is chosen. The PRID that the consumer
+ * associates with an EPID does not need to be exact. A "representative"
+ * PRID suffices. Usually, the consumer only cares about the function
+ * and name components of the probe. So, set the mst->prid in the trampoline
+ * to any representative PRID. Then, dt_link_construct() will continue
+ * to have the same side effect, associating the PRID with the EPID.
+ *
+ * Another option is to write the PRID alongside the EPID in the output
+ * buffer.
+ *
+ * Work in progress.
+ */
+ /*
+ * Store a representative PRID to mst->prid. It will immediately
+ * be overwritten by the correct PRID, but we store it anyhow for
+ * the side effect it has of making a representative PRID known to
+ * the consumer.
+ */
+ pop = dt_list_next(&upp->probes);
+ if (pop != NULL) {
+ const dt_probe_t *pprp = pop->probe;
+ dt_ident_t *idp;
+
+ idp = dt_dlib_add_probe_var(pcb->pcb_hdl, pprp);
+ assert(idp != NULL);
+
+ emite(dlp, BPF_STORE_IMM(BPF_W, BPF_REG_7, DMST_PRID, pprp->desc->id), idp);
+ }
+#endif
+
/* Read the PRID from the table lookup and store to mst->prid. */
emit(dlp, BPF_LOAD(BPF_W, BPF_REG_1, BPF_REG_0, 0));
emit(dlp, BPF_STORE(BPF_W, BPF_REG_7, DMST_PRID, BPF_REG_1));
--
2.18.4
More information about the DTrace-devel
mailing list