[DTrace-devel] [PATCH 3/3] Alternative handling of tracemem's dynamic size.
Kris Van Hees
kris.van.hees at oracle.com
Fri Feb 24 03:28:43 UTC 2023
On Mon, Jan 30, 2023 at 04:36:16PM -0500, eugene.loh--- via DTrace-devel wrote:
> From: Eugene Loh <eugene.loh at oracle.com>
>
> The tracemem() action takes a constant size argument that gives the size
> of the buffer used.
>
> Optionally, it also takes another size argument that is dynamically
> computed. Currently, in this DTrace port, this dsize is used only by the
> consumer, to limit how much data is displayed. The documentation is
> unclear if dsize should also limit how much data is written into the
> buffer in the first place. Arguably, it should:
>
> *) Copying less data might mean faster run time, although the
> savings would be very small and would incur the cost of extra
> BPF instructions.
>
> *) Copying less data might protect against accessing memory
> illegally.
>
> Using dsize to cap how much data is written into the buffer is
> implemented in this patch.
>
> Since any changes in behavior would not be seen in our testing, no test
> changes are made.
>
> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
> ---
> libdtrace/dt_cg.c | 29 +++++++++++++++++++++++++++--
> 1 file changed, 27 insertions(+), 2 deletions(-)
>
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index 17843415..30c48155 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -2028,9 +2028,34 @@ dt_cg_act_tracemem(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
> off = dt_rec_add(dtp, dt_cg_fill_gap, DTRACEACT_TRACEMEM, nsiz->dn_value, 1, NULL,
> dsiz ? DTRACE_TRACEMEM_DYNAMIC : DTRACE_TRACEMEM_STATIC);
>
> - if (dsiz != NULL)
> - dt_cg_store_val(pcb, dsiz, DTRACEACT_TRACEMEM, NULL,
> + if (dsiz != NULL) {
> + uint_t off_dsiz;
> + size_t wid_dsiz = ctf_type_size(dsiz->dn_ctfp, dsiz->dn_type);
> + uint_t Lokay = dt_irlist_label(dlp);
> +
> + assert(wid_dsiz > 0 && wid_dsiz <= 8 && (wid_dsiz & (wid_dsiz - 1)) == 0);
> +
> + /* compute and record dsiz at the appropriate offset */
> + dt_cg_node(dsiz, dlp, drp);
> + off_dsiz = dt_rec_add(dtp, dt_cg_fill_gap, DTRACEACT_TRACEMEM, wid_dsiz, wid_dsiz, NULL,
> dsiz->dn_flags & DT_NF_SIGNED ? DTRACE_TRACEMEM_SSIZE : DTRACE_TRACEMEM_SIZE);
> + emit(dlp, BPF_STORE(ldstw[wid_dsiz], BPF_REG_9, off_dsiz, dsiz->dn_reg));
> +
> + /*
> + * Decide whether to reduce the size of the data that is
> + * actually being recorded. We do this only if the dynamic
> + * size is non-negative and less than the nsiz. Note that the
> + * dsiz->dn_reg value has been sign-extended to 64 bits and we
> + * will never have an nsiz that is 1<<63 or greater. So, just
> + * treat dsiz->dn_reg as an unsigned value.
> + */
> + emit(dlp, BPF_BRANCH_REG(BPF_JLE, nsiz->dn_reg, dsiz->dn_reg, Lokay));
> + emit(dlp, BPF_MOV_REG(nsiz->dn_reg, dsiz->dn_reg));
> + emitl(dlp, Lokay,
> + BPF_NOP());
> +
> + dt_regset_free(drp, dsiz->dn_reg);
I think it would be much cleaner to do things in a different order:
1. compute dsiz (dt_cg_node)
2. decide whether to reduce nsiz based on diz
3. use dt_cg_store_val to store the dsiz in the output buffer
That avoids the manual operations you do to record dsiz in the buffer.
> + }
>
> if (dt_regset_xalloc_args(drp) == -1)
> longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> --
> 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