[DTrace-devel] [PATCH 2/2] cg: transition [u]stack() from action to subroutine
Kris Van Hees
kris.van.hees at oracle.com
Mon Sep 29 18:22:00 UTC 2025
On Mon, Sep 29, 2025 at 12:22:16AM -0400, Eugene Loh wrote:
> I don't follow all the details, but I guess this looks fine to me. I did
> have a few minor syntactical comments.
>
> It seems that dt_cg_subr_stack() and dt_cg_subr_ustack() are virtually
> identical. Might one combine the two functions into a
> dt_cg_subr_stack_common() (or whatever name seems suitable) and do this:
>
> static void
> dt_cg_subr_stack(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> {
> dt_cg_subr_stack_common(dnp, dlp, drp, DTRACEACT_STACK);
> }
>
> static void
> dt_cg_subr_ustack(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> {
> dt_cg_subr_stack_common(dnp, dlp, drp, DTRACEACT_USTACK);
> }
>
> The win is less the reduction in lines of code and more in the clarity of
> what is being done.
Sure.
> Also, a few others sprinkled below...
>
> On 9/23/25 12:01, Kris Van Hees wrote:
> > diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> > @@ -3987,50 +3996,63 @@ empty_args:
> > uint_t nextoff;
> > int is_symmod = 0;
> > - if (dnp->dn_kind == DT_NODE_FUNC &&
> > - dnp->dn_ident != NULL)
> > - switch (dnp->dn_ident->di_id) {
> > - case DT_ACT_STACK:
> > - tuplesize = dt_cg_act_stack_sub(yypcb, dnp, treg, tuplesize, DTRACEACT_STACK);
> > - continue;
> > - case DT_ACT_USTACK:
> > - tuplesize = dt_cg_act_stack_sub(yypcb, dnp, treg, tuplesize, DTRACEACT_USTACK);
> > - continue;
> > - case DT_ACT_UADDR:
> > - case DT_ACT_USYM:
> > - case DT_ACT_UMOD:
> > - nextoff = (tuplesize + (8 - 1)) & ~(8 - 1);
> > - if (tuplesize < nextoff)
> > - emit(dlp, BPF_ALU64_IMM(BPF_ADD, treg, nextoff - tuplesize));
> > -
> > - /* Preface the value with the user process pid. */
> > - 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_RSH, BPF_REG_0, 32));
> > - emit(dlp, BPF_STORE(BPF_DW, treg, 0, BPF_REG_0));
> > - dt_regset_free(drp, BPF_REG_0);
> > -
> > - /* Then store the value. */
> > - dt_regset_xalloc(drp, BPF_REG_0);
> > - emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, areg, -i * DT_STK_SLOT_SZ));
> > - emit(dlp, BPF_STORE(BPF_DW, treg, 8, BPF_REG_0));
> > - dt_regset_free(drp, BPF_REG_0);
> > -
> > - emit(dlp, BPF_ALU64_IMM(BPF_ADD, treg, 16));
> > - tuplesize = nextoff + 16;
> > -
> > - continue;
> > - case DT_ACT_SYM:
> > - case DT_ACT_MOD:
> > - is_symmod = 1;
> > - size = 8;
> > - dt_regset_xalloc(drp, BPF_REG_0);
> > - emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, areg, -i * DT_STK_SLOT_SZ));
> > - break;
> > + if (dnp->dn_kind == DT_NODE_FUNC) {
> > + dt_ident_t *fidp = dnp->dn_ident;
> > +
> > + if (fidp->di_kind == DT_IDENT_FUNC) {
> > + switch (fidp->di_id) {
> > + case DIF_SUBR_STACK:
> > + tuplesize = dt_cg_act_stack_sub(
> > + yypcb, dnp, treg,
> > + tuplesize,
> > + DTRACEACT_STACK);
> > + continue;
> > + case DIF_SUBR_USTACK:
> > + tuplesize = dt_cg_act_stack_sub(
> > + yypcb, dnp, treg,
> > + tuplesize,
> > + DTRACEACT_USTACK);
> > + continue;
> > + }
> > + } else if (fidp->di_kind == DT_IDENT_ACTFUNC) {
> > + switch (dnp->dn_ident->di_id) {
>
> s/dnp->dn_ident/fidp/
Thanks.
> > + case DT_ACT_UADDR:
> > + case DT_ACT_USYM:
> > + case DT_ACT_UMOD:
> > + nextoff = ALIGN(tuplesize, 8);
> > + if (tuplesize < nextoff)
> > + emit(dlp, BPF_ALU64_IMM(BPF_ADD, treg, nextoff - tuplesize));
> > +
> > + /* Preface the value with the user process pid. */
> > + 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_RSH, BPF_REG_0, 32));
> > + emit(dlp, BPF_STORE(BPF_DW, treg, 0, BPF_REG_0));
> > + dt_regset_free(drp, BPF_REG_0);
> > +
> > + /* Then store the value. */
> > + dt_regset_xalloc(drp, BPF_REG_0);
> > + emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, areg, -i * DT_STK_SLOT_SZ));
> > + emit(dlp, BPF_STORE(BPF_DW, treg, 8, BPF_REG_0));
> > + dt_regset_free(drp, BPF_REG_0);
> > +
> > + emit(dlp, BPF_ALU64_IMM(BPF_ADD, treg, 16));
> > + tuplesize = nextoff + 16;
> > +
> > + continue;
> > + case DT_ACT_SYM:
> > + case DT_ACT_MOD:
> > + is_symmod = 1;
> > + size = 8;
> > + dt_regset_xalloc(drp, BPF_REG_0);
> > + emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, areg, -i * DT_STK_SLOT_SZ));
> > + break;
> > + }
> > }
> > + }
> > if (!is_symmod) {
> > dt_node_diftype(dtp, dnp, &t);
> > @@ -6968,6 +7070,7 @@ dt_cg_call_subr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > assert(idp->di_id <= DIF_SUBR_MAX);
> > fun = _dt_cg_subr[idp->di_id];
> > +assert(fun != NULL);
>
> Weird indentation?
I think I added that as debugging. Will remove.
> > if (fun == NULL)
> > dnerror(dnp, D_FUNC_UNDEF, "unimplemented subroutine: %s\n",
> > idp->di_name);
> > diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
> > index 509f263d..9dd8956d 100644
> > --- a/libdtrace/dt_open.c
> > +++ b/libdtrace/dt_open.c
> > @@ -175,7 +175,7 @@ static const dt_ident_t _dtrace_globals[] = {
> > { "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0,
> > &dt_idops_type, "uint_t" },
> > { "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
>
> Add DT_IDFLG_ALLOCA? (Of course, it doesn't matter yet.)
Ah no, some other changes will make that not even needed because I will be
using the static area for storing stacks rather than allocating a new one for
each invocation.
> > - &dt_idops_func, "stack([uint32_t], [uint32_t])" },
> > + &dt_idops_func, "dt_stack([uint32_t], [uint32_t])" },
> > { "link_ntop", DT_IDENT_FUNC, 0, DIF_SUBR_LINK_NTOP, DT_ATTR_STABCMN,
> > DT_VERS_1_5, &dt_idops_func, "string(int, void *)" },
> > { "llquantize", DT_IDENT_AGGFUNC, 0, DT_AGG_LLQUANTIZE,
More information about the DTrace-devel
mailing list