[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