[DTrace-devel] [PATCH 4/6] cg: add argument remapping in the trampoline

Nick Alcock nick.alcock at oracle.com
Fri Oct 18 19:58:06 UTC 2024


Before now, argument remapping was restricted to the args[] array, and was
implemented in dt_cg_array_op in the same place where we decide whether
to automatically copyin() userspace strings.

But existing DTrace testcases suggest that remapping is also applied to argN
for USDT, and it would definitely be more *convenient* if it were (so that
argN and arg[N] always contain the same content, and only their types
differ).  Add a new function dt_cg_tramp_remap_args(), which can be
called from trampolines to apply remappings (destructively, but it keeps a
copy of the old args in the save area so you can unapply them if you need
to).  No existing providers do any remapping, so this is not yet called, but
it's about to be.

The remapping info is still propagated up out of per-provider state so that
the parser can use it to tell what types the remapped arguments are and
to apply array-op remapping: users of dt_cg_tramp_remap_args() should set
the probe remapping to 1:1 and shuffle the native types correspondingly,
to match what dt_cg_tramp_remap_args() has done (in effect, calling it has
moved the native types around).

Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
---
 libdtrace/dt_cg.c | 35 ++++++++++++++++++++++++++++++++++-
 libdtrace/dt_cg.h |  1 +
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 39c27ab0ec0b..9709667d97fb 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -831,6 +831,34 @@ dt_cg_tramp_restore_args(dt_pcb_t *pcb)
 	}
 }
 
+/*
+ * Remap arguments according to the array of remappings given.  The original
+ * arguments are overwritten (but saved).
+ *
+ * The caller must ensure that %r7 contains the value set by the
+ * dt_cg_tramp_prologue*() functions.
+ */
+void
+dt_cg_tramp_remap_args(dt_pcb_t *pcb, uint8_t *remappings, size_t nremappings)
+{
+	dt_irlist_t	*dlp = &pcb->pcb_ir;
+	int		i;
+
+	/*
+	 * Work from saved args so we don't need to worry about overwriting regs
+	 * we're about to remap.
+	 */
+	dt_cg_tramp_save_args(pcb);
+
+	for (i = 0; i < nremappings; i++) {
+		if (remappings[i] != i) {
+			dt_dprintf("Remap: loading from %i, storing to %i\n", remappings[i], i);
+			emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_7, DMST_ORIG_ARG(remappings[i])));
+			emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(i), BPF_REG_0));
+		}
+	}
+}
+
 typedef struct {
 	dt_irlist_t	*dlp;
 	dt_activity_t	act;
@@ -5060,7 +5088,12 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	 * array index according to the static argument mapping (if any),
 	 * unless the argument reference is provided by a dynamic translator.
 	 * If we're using a dynamic translator for args[], then just set dn_reg
-	 * to an invalid reg and return: DIF_OP_XLARG will fetch the arg later.
+	 *
+	 * If dt_cg_tramp_remap_args is in use, you should apply the remapping
+	 * at the probe_info stage, since the effective "native" arg positions
+	 * will be changed.
+	 *
+	 * If this is a userland variable, note that we need to copy it in.
 	 */
 	if (idp->di_id == DIF_VAR_ARGS) {
 		if ((idp->di_kind == DT_IDENT_XLPTR ||
diff --git a/libdtrace/dt_cg.h b/libdtrace/dt_cg.h
index 0a7c7ba6a8c5..4c6d0f5dac6a 100644
--- a/libdtrace/dt_cg.h
+++ b/libdtrace/dt_cg.h
@@ -34,6 +34,7 @@ extern void dt_cg_tramp_get_var(dt_pcb_t *pcb, const char *name, int isstore,
 extern void dt_cg_tramp_del_var(dt_pcb_t *pcb, const char *name);
 extern void dt_cg_tramp_save_args(dt_pcb_t *pcb);
 extern void dt_cg_tramp_restore_args(dt_pcb_t *pcb);
+extern void dt_cg_tramp_remap_args(dt_pcb_t *pcb, uint8_t *remappings, size_t nremappings);
 extern void dt_cg_tramp_call_clauses(dt_pcb_t *pcb, const dt_probe_t *prp,
 				     dt_activity_t act);
 extern void dt_cg_tramp_return(dt_pcb_t *pcb);
-- 
2.46.0.278.g36e3a12567




More information about the DTrace-devel mailing list