[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