[DTrace-devel] [PATCH 08/14] Use uprobes map to call clauses conditionally

eugene.loh at oracle.com eugene.loh at oracle.com
Tue Jun 4 18:11:07 UTC 2024


From: Eugene Loh <eugene.loh at oracle.com>

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/dt_prov_uprobe.c | 88 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 87 insertions(+), 1 deletion(-)

diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
index 591f2fab..cb79e0a3 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);
@@ -522,6 +522,7 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
 	emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_get_current_pid_tgid));
 	emit(dlp,  BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 32));
 
+#if 0
 	/*
 	 * Generate a composite conditional clause:
 	 *
@@ -565,6 +566,91 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
 		emitl(dlp, lbl_next,
 			   BPF_NOP());
 	}
+#else
+	dt_ident_t	*uprobes = dt_dlib_get_map(pcb->pcb_hdl, "uprobes");
+	list_clause_t	*cl;
+
+	assert(uprobes != NULL);
+
+	/*
+	 * Look up in the BPF uprobes map.  Space for the look-up key will be used
+	 * on the BPF stack at %r9-sizeof(uprobe_map_key_t).  The key comprises the
+	 * pid (in %r0) and the underlying-probe prid.
+	 */
+	emit(dlp,  BPF_STORE(BPF_W, BPF_REG_9, (int)(-sizeof(uprobe_map_key_t)), BPF_REG_0));
+	emit(dlp,  BPF_STORE_IMM(BPF_W, BPF_REG_9, (int)(-sizeof(dtrace_id_t)) /* or -sizeof(uprobe_map_key_t) + sizeof(pid_t) */, uprp->desc->id));
+	dt_cg_xsetx(dlp, uprobes, DT_LBL_NONE, BPF_REG_1, uprobes->di_id);
+	emit(dlp,  BPF_MOV_REG(BPF_REG_2, BPF_REG_9));
+	emit(dlp,  BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, (int)(-sizeof(uprobe_map_key_t))));
+	emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_map_lookup_elem));
+	emit(dlp,  BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_0, 0, lbl_exit));
+
+	/* 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));
+
+	/* Read the bit mask from the table lookup in %r6. */    // FIXME someday, extend this past 64 bits
+	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_6, BPF_REG_0, offsetof(uprobe_map_val_t, mask)));
+
+	/*
+	 * Now loop over clauses.
+	 *
+	 * How do we know which clauses are called by this underlying probe?
+	 * Each dt_probe_t has a "clauses" list, but that's built by
+	 *
+	 *     dt_program.c
+	 *         dtrace_program_exec()
+	 *             dtrace_stmt_iter(..., dt_prog_stmt, ...);
+	 *         dt_prog_stmt()
+	 *             dt_probe_iter(..., dt_stmt_probe, ...);
+	 *         dt_stmt_probe()
+	 *             dt_probe_add_clause(...);
+	 *
+	 * which is to say that the "clauses" list will be built for overlying
+	 * probes, while we are interested here in underlying probes.  Should
+	 * dt_probe_add_clause() also take some provider-specific action?
+	 *
+	 * For now, let's just look up the clause using what we know about
+	 * the clause numbering.
+	 */
+	/*
+	 * Hold the bit mask in %r6.
+	 */
+	for (cl = dt_list_next(&upp->clauses); cl != NULL; cl = dt_list_next(cl)) {
+		char		nm[32];       // FIXME hardwired size
+		dt_ident_t	*idp;
+		uint_t		lbl_next = dt_irlist_label(dlp);
+
+		sprintf(nm, "dt_clause_%d", cl->clause);
+		idp = dt_idhash_lookup(pcb->pcb_hdl->dt_bpfsyms, nm);       // FIXME what if idp is NULL?
+
+		/* Test the lowest bit. */
+		emit(dlp,  BPF_MOV_REG(BPF_REG_1, BPF_REG_6));
+		emit(dlp,  BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 1));
+		emit(dlp,  BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_1, 0, lbl_next));
+
+		/*
+		 *      if (*dctx.act != act)   // ldw %r0, [%r9 + DCTX_ACT]
+		 *	      goto exit;      // ldw %r0, [%r0 + 0]
+		 *			      // jne %r0, act, lbl_exit
+		 */
+		emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_9, DCTX_ACT));
+		emit(dlp,  BPF_LOAD(BPF_W, BPF_REG_0, BPF_REG_0, 0));
+		emit(dlp,  BPF_BRANCH_IMM(BPF_JNE, BPF_REG_0, DT_ACTIVITY_ACTIVE, lbl_exit));
+
+		/* dctx.mst->scratch_top = 8 */
+		emit(dlp,  BPF_STORE_IMM(BPF_W, BPF_REG_7, DMST_SCRATCH_TOP, 8));
+
+		/* Call clause. */
+		emit(dlp,  BPF_MOV_REG(BPF_REG_1, BPF_REG_9));
+		emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
+
+		/* Finished this clause. */
+		emitl(dlp, lbl_next,
+			   BPF_NOP());
+		emit(dlp,  BPF_ALU64_IMM(BPF_RSH, BPF_REG_6, 1));
+	}
+#endif
 
 	dt_cg_tramp_return(pcb);
 
-- 
2.18.4




More information about the DTrace-devel mailing list