[DTrace-devel] [PATCH v3 7/9] Consolidate bpf_get_stack()-call code generation for stack and ustack()
Kris Van Hees
kris.van.hees at oracle.com
Mon Jan 29 19:38:20 UTC 2024
On Sat, Jan 27, 2024 at 03:12:28PM -0500, eugene.loh--- via DTrace-devel wrote:
> From: Eugene Loh <eugene.loh at oracle.com>
>
> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
> ---
> libdtrace/dt_cg.c | 142 ++++++++++++++++++++++++++--------------------
> 1 file changed, 80 insertions(+), 62 deletions(-)
>
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index 084157a0..6d3aed13 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -2559,34 +2559,83 @@ dt_cg_stack_arg(dtrace_hdl_t *dtp, dt_node_t *dnp, int user)
> 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)
As mentioned in [5/9] I would pass kind (DTRACEACT_STACK or DTRACEACT_USTACK)
explicitly to make the caller more clear on what is meant with that last arg.
> {
> dtrace_hdl_t *dtp = pcb->pcb_hdl;
> dt_irlist_t *dlp = &pcb->pcb_ir;
> dt_regset_t *drp = pcb->pcb_regs;
> uint64_t arg;
> - int nframes;
> - int skip = 0;
> - uint_t off;
> + int nframes, stacksize, prefsz, align = sizeof(uint64_t);
> uint_t lbl_valid = dt_irlist_label(dlp);
>
> - arg = dt_cg_stack_arg(dtp, dnp, 0);
> + /* Get sizing information from dnp->dn_arg. */
> + arg = dt_cg_stack_arg(dtp, dnp, user);
arg = dt_cg_stack_arg(dtp, dnp, kind);
> + prefsz = user * sizeof(uint64_t);
> nframes = DTRACE_USTACK_NFRAMES(arg);
> + stacksize = nframes * sizeof(uint64_t);
>
> - /* 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);
> + /* 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);
off = dt_rec_add(dtp, dt_cg_fill_gap, kind, prefsz + stacksize,
align, NULL, arg);
> + }
>
> - /* Now call bpf_get_stack(ctx, buf, size, flags). */
> + /* Write the tgid. */
> + if (user) {
if (kind == DTRACEACT_USTACK) {
> + 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);
> + }
> +
> + /* Call bpf_get_stack(ctx, buf, size, flags). */
> if (dt_regset_xalloc_args(drp) == -1)
> longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> dt_cg_access_dctx(BPF_REG_1, dlp, drp, 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)));
emit(dlp, BPF_MOV_IMM(BPF_REG_4, (0 & BPF_F_SKIP_FIELD_MASK) |
(kind == DTRACEACT_USTACK
? BPF_F_USER_STACK : 0)));
or it mght be cleaner to actually declare a variable for this last argument,
with initial value 0, and in the earlier conditional on kind set it to to
BPF_F_USER_STACK.
> dt_regset_xalloc(drp, BPF_REG_0);
> emit(dlp, BPF_CALL_HELPER(BPF_FUNC_get_stack));
> dt_regset_free_args(drp);
> @@ -2595,6 +2644,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, kind == DTRACEACT_USTACK ? 1 : 0);
dt_cg_act_stack_sub(pcb, dnp, -1, 0, kind);
> }
>
> static void
> @@ -2749,51 +2810,6 @@ dt_cg_act_trunc(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
> dt_cg_store_val(pcb, trunc, DTRACEACT_LIBACT, NULL, DT_ACT_TRUNC);
> }
>
> -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_stack_arg(dtp, dnp, 1);
> - 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). */
> - dt_cg_access_dctx(BPF_REG_1, dlp, drp, 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());
> -}
> -
> static void
> dt_cg_act_print(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
> {
> @@ -2853,7 +2869,8 @@ static const dt_cg_actdesc_t _dt_cg_actions[DT_ACT_MAX] = {
> DTRACEACT_PRINTF },
> [DT_ACT_IDX(DT_ACT_TRACE)] = { &dt_cg_act_trace, },
> [DT_ACT_IDX(DT_ACT_TRACEMEM)] = { &dt_cg_act_tracemem, },
> - [DT_ACT_IDX(DT_ACT_STACK)] = { &dt_cg_act_stack, },
> + [DT_ACT_IDX(DT_ACT_STACK)] = { &dt_cg_act_stack,
> + DTRACEACT_STACK },
> [DT_ACT_IDX(DT_ACT_STOP)] = { &dt_cg_act_stop,
> DTRACEACT_STOP },
> [DT_ACT_IDX(DT_ACT_BREAKPOINT)] = { &dt_cg_act_breakpoint,
> @@ -2870,7 +2887,8 @@ static const dt_cg_actdesc_t _dt_cg_actions[DT_ACT_MAX] = {
> DTRACEACT_CHILL },
> [DT_ACT_IDX(DT_ACT_EXIT)] = { &dt_cg_act_exit,
> DTRACEACT_EXIT },
> - [DT_ACT_IDX(DT_ACT_USTACK)] = { &dt_cg_act_ustack, },
> + [DT_ACT_IDX(DT_ACT_USTACK)] = { &dt_cg_act_stack,
> + DTRACEACT_USTACK },
> [DT_ACT_IDX(DT_ACT_PRINTA)] = { &dt_cg_act_printa, },
> [DT_ACT_IDX(DT_ACT_RAISE)] = { &dt_cg_act_raise,
> DTRACEACT_RAISE },
> --
> 2.18.4
>
>
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel
More information about the DTrace-devel
mailing list