[DTrace-devel] [PATCH 7/9] Consolidate bpf_get_stack()-call code generation for stack and ustack()

eugene.loh at oracle.com eugene.loh at oracle.com
Thu Oct 5 21:14:05 UTC 2023


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

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/dt_cg.c | 141 ++++++++++++++++++++++++++++------------------
 1 file changed, 85 insertions(+), 56 deletions(-)

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 6cae8814..ba698d2f 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -2225,33 +2225,90 @@ dt_cg_ustack_arg(dtrace_hdl_t *dtp, dt_node_t *dnp)
 	return DTRACE_USTACK_ARG(nframes, strsize);
 }
 
-static void
-dt_cg_act_stack(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
+/*
+ * Call the bpf_get_stack() helper function.
+ *
+ * dnp->dn_arg has optional, integer-constant sizing information.
+ *
+ * If reg>=0, reg is a register holding the output pointer.
+ * If reg<0, we write the stack to the output buffer in %r9.
+ *
+ * These cases treat "off" differently:
+ *   - reg>=0: "off" tracks how far the pointer in "reg" has
+ *             been advanced, both at function entry and return
+ *
+ *   - reg<0: "off" is basically just a local variable since
+ *            offsets with the %r9 buffer are managed by
+ *            dt_rec_add()
+ *
+ * The "user" flag indicates whether a user (or kernel) stack is desired.
+ */
+static int
+dt_cg_act_stack_sub(dt_pcb_t *pcb, dt_node_t *dnp, int reg, int off, int user)
 {
 	dtrace_hdl_t	*dtp = pcb->pcb_hdl;
 	dt_irlist_t	*dlp = &pcb->pcb_ir;
 	dt_regset_t	*drp = pcb->pcb_regs;
-	int		nframes;
-	int		skip = 0;
-	uint_t		off;
+	uint64_t	arg;
+	int		nframes, stacksize, prefsz, align = sizeof(uint64_t);
 	uint_t		lbl_valid = dt_irlist_label(dlp);
 
-	nframes = dt_cg_stack_nframes(dtp, dnp);
+	/* Get sizing information from dnp->dn_arg. */
+	if (user) {
+		arg = dt_cg_ustack_arg(dtp, dnp);
+		nframes = DTRACE_USTACK_NFRAMES(arg);
+		prefsz = sizeof(uint64_t);
+	} else {
+		nframes = dt_cg_stack_nframes(dtp, dnp);
+		arg = nframes;
+		prefsz = 0;
+	}
+	stacksize = nframes * sizeof(uint64_t);
+
+	/* Handle alignment and reserve space in the output buffer. */
+	if (reg >= 0) {
+		uint_t	nextoff;
+		nextoff = (off + (align - 1)) & ~(align - 1);
+		if (off < nextoff)
+			emit(dlp,  BPF_ALU64_IMM(BPF_ADD, reg, nextoff - off));
+		off = nextoff + prefsz + stacksize;
+	} else {
+		off = dt_rec_add(dtp, dt_cg_fill_gap,
+				 user ? DTRACEACT_USTACK : DTRACEACT_STACK,
+				 prefsz + stacksize, align, NULL, arg);
+	}
 
-	/* Reserve space in the output buffer. */
-	off = dt_rec_add(dtp, dt_cg_fill_gap, DTRACEACT_STACK,
-			 sizeof(uint64_t) * nframes, sizeof(uint64_t),
-			 NULL, nframes);
+	/* Write the tgid. */
+	if (user) {
+		if (dt_regset_xalloc_args(drp) == -1)
+			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+		dt_regset_xalloc(drp, BPF_REG_0);
+		emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_get_current_pid_tgid));
+		dt_regset_free_args(drp);
+		emit(dlp,  BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff));
+		if (reg >= 0)
+			emit(dlp,  BPF_STORE(BPF_DW, reg, 0, BPF_REG_0));
+		else
+			emit(dlp,  BPF_STORE(BPF_DW, BPF_REG_9, off, BPF_REG_0));
+		dt_regset_free(drp, BPF_REG_0);
+	}
 
-	/* Now call bpf_get_stack(ctx, buf, size, flags). */
+	/* Call bpf_get_stack(ctx, buf, size, flags). */
 	if (dt_regset_xalloc_args(drp) == -1)
 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
 	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_DCTX));
 	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_1, DCTX_CTX));
-	emit(dlp,  BPF_MOV_REG(BPF_REG_2, BPF_REG_9));
-	emit(dlp,  BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, off));
-	emit(dlp,  BPF_MOV_IMM(BPF_REG_3, sizeof(uint64_t) * nframes));
-	emit(dlp,  BPF_MOV_IMM(BPF_REG_4, skip & BPF_F_SKIP_FIELD_MASK));
+	if (reg >= 0) {
+		emit(dlp,  BPF_MOV_REG(BPF_REG_2, reg));
+		if (prefsz)
+			emit(dlp,  BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, prefsz));
+	} else {
+		emit(dlp,  BPF_MOV_REG(BPF_REG_2, BPF_REG_9));
+		emit(dlp,  BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, off + prefsz));
+	}
+	emit(dlp,  BPF_MOV_IMM(BPF_REG_3, stacksize));
+	emit(dlp,  BPF_MOV_IMM(BPF_REG_4, (0 & BPF_F_SKIP_FIELD_MASK)
+					  | (user ? BPF_F_USER_STACK : 0)));
 	dt_regset_xalloc(drp, BPF_REG_0);
 	emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_get_stack));
 	dt_regset_free_args(drp);
@@ -2260,6 +2317,18 @@ dt_cg_act_stack(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
 	dt_cg_probe_error(pcb, DTRACEFLT_BADSTACK, DT_ISIMM, 0);
 	emitl(dlp, lbl_valid,
 		   BPF_NOP());
+
+	/* Finish. */
+	if (reg >= 0)
+		emit(dlp,  BPF_ALU64_IMM(BPF_ADD, reg, prefsz + stacksize));
+
+	return off;
+}
+
+static void
+dt_cg_act_stack(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
+{
+	dt_cg_act_stack_sub(pcb, dnp, -1, 0, 0);
 }
 
 static void
@@ -2417,47 +2486,7 @@ dt_cg_act_trunc(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
 static void
 dt_cg_act_ustack(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
 {
-	dt_irlist_t	*dlp = &pcb->pcb_ir;
-	dt_regset_t	*drp = pcb->pcb_regs;
-	dtrace_hdl_t	*dtp = pcb->pcb_hdl;
-	uint64_t	arg;
-	int		nframes, stacksize;
-	int		skip = 0;
-	uint_t		off;
-	uint_t		lbl_valid = dt_irlist_label(dlp);
-
-	arg = dt_cg_ustack_arg(dtp, dnp);
-	nframes = DTRACE_USTACK_NFRAMES(arg);
-	stacksize = nframes * sizeof(uint64_t);
-
-	/* Reserve space in the output buffer. */
-	off = dt_rec_add(pcb->pcb_hdl, dt_cg_fill_gap, DTRACEACT_USTACK,
-			 8 + stacksize, 8, NULL, arg);
-
-	if (dt_regset_xalloc_args(drp) == -1)
-		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-	dt_regset_xalloc(drp, BPF_REG_0);
-
-	/* Write the tgid. */
-	emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_get_current_pid_tgid));
-	emit(dlp,  BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff));
-	emit(dlp,  BPF_STORE(BPF_DW, BPF_REG_9, off, BPF_REG_0));
-
-	/* Now call bpf_get_stack(ctx, buf, size, flags). */
-	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_FP, DT_STK_DCTX));
-	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_1, BPF_REG_1, DCTX_CTX));
-	emit(dlp,  BPF_MOV_REG(BPF_REG_2, BPF_REG_9));
-	emit(dlp,  BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, off + 8));
-	emit(dlp,  BPF_MOV_IMM(BPF_REG_3, stacksize));
-	emit(dlp,  BPF_MOV_IMM(BPF_REG_4, (skip & BPF_F_SKIP_FIELD_MASK)
-					  | BPF_F_USER_STACK));
-	emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_get_stack));
-	dt_regset_free_args(drp);
-	emit(dlp,  BPF_BRANCH_IMM(BPF_JSGE, BPF_REG_0, 0, lbl_valid));
-	dt_regset_free(drp, BPF_REG_0);
-	dt_cg_probe_error(pcb, DTRACEFLT_BADSTACK, DT_ISIMM, 0);
-	emitl(dlp, lbl_valid,
-		   BPF_NOP());
+	dt_cg_act_stack_sub(pcb, dnp, -1, 0, 1);
 }
 
 typedef void dt_cg_action_f(dt_pcb_t *, dt_node_t *, dtrace_actkind_t);
-- 
2.18.4




More information about the DTrace-devel mailing list