[DTrace-devel] [PATCH] bpf: separate bvar implementation into separate functions
Kris Van Hees
kris.van.hees at oracle.com
Fri Jan 24 16:56:01 UTC 2025
On Fri, Jan 24, 2025 at 02:35:49AM -0500, Eugene Loh wrote:
> I think I'm on board with this patch, but two questions.
>
> 1. There is DIF_VAR_EXECARGS stuff in two places. Is that stuff in the
> wrong patch?
Oops, yes, that is for a follow-up patch. WIll adjust.
> 2. I'm confused why
> test/demo/builtin/ipl.d
> test/demo/builtin/vtimestamp.d
> were passing: there was no ipl or vtimestamp support before and there is
> none now. Presumably, the tests used to time out... so why was that
> considered a PASS? I guess I see why test/unittest/buffering/tst.cputime.sh
> used to pass, but maybe that suggests that the test needs to be tightened up
> and be made quite a bit more discriminating.
The test/demo cases are all mostly pointless, especially because e.g. these
PASSes came from the test/demo/test.options containing "@@timeout-success".
We should probably just remove the test/demo cases from the actual testsuite,
and leave them around (for now) as examples (and overall not very good ones
at that).
> On 1/23/25 22:48, Kris Van Hees wrote:
> > The handling of builtin variables was done with a single big function
> > that therefore got linked into every single BPF program (twice if the
> > builtin variable might raise a fault). Providing separate functions
> > for most builtin variables reduces BPF program size significantly.
> >
> > This also reduces pressure on the BPF verifies.
> >
> > Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> > ---
> > bpf/get_bvar.c | 412 +++++++++++++-----------
> > include/dtrace/dif_defines.h | 1 +
> > libdtrace/dt_cg.c | 39 ++-
> > libdtrace/dt_dis.c | 57 +++-
> > libdtrace/dt_open.c | 2 +
> > test/demo/builtin/ipl.d | 2 +
> > test/demo/builtin/vtimestamp.d | 2 +
> > test/demo/io/iocpu.d | 2 +
> > test/unittest/buffering/tst.cputime.sh | 1 +
> > test/unittest/disasm/tst.ann-bvar.r | 69 ++--
> > test/unittest/disasm/tst.ann-bvar.sh | 9 +-
> > test/unittest/disasm/tst.vartab-bvar.r | 2 -
> > test/unittest/disasm/tst.vartab-bvar.sh | 7 +-
> > 13 files changed, 360 insertions(+), 245 deletions(-)
> >
> > diff --git a/bpf/get_bvar.c b/bpf/get_bvar.c
> > index 1c0fa884..c760126d 100644
> > --- a/bpf/get_bvar.c
> > +++ b/bpf/get_bvar.c
> > @@ -19,18 +19,21 @@
> > # define noinline __attribute__((noinline))
> > #endif
> > -extern struct bpf_map_def cpuinfo;
> > -extern struct bpf_map_def probes;
> > -extern struct bpf_map_def state;
> > -extern struct bpf_map_def usdt_names;
> > -
> > -extern uint64_t PC;
> > -extern uint64_t STBSZ;
> > -extern uint64_t STKSIZ;
> > -extern uint64_t BOOTTM;
> > +extern struct bpf_map_def cpuinfo;
> > +extern struct bpf_map_def probes;
> > +extern struct bpf_map_def state;
> > +extern struct bpf_map_def usdt_names;
> > +
> > +extern uint64_t BOOTTM;
> > +extern uint64_t NPROBES;
> > +extern uint64_t PC;
> > +extern uint64_t STBSZ;
> > +extern uint64_t STKSIZ;
> > extern uint64_t STACK_OFF;
> > -extern uint64_t STACK_SKIP;
> > -extern uint64_t NPROBES;
> > +extern uint64_t STACK_SKIP;
> > +extern uint64_t TASK_COMM;
> > +extern uint64_t TASK_REAL_PARENT;
> > +extern uint64_t TASK_TGID;
> > #define error(dctx, fault, illval) \
> > ({ \
> > @@ -38,198 +41,231 @@ extern uint64_t NPROBES;
> > -1; \
> > })
> > -noinline uint64_t dt_get_bvar(const dt_dctx_t *dctx, uint32_t id, uint32_t idx)
> > +noinline uint64_t dt_bvar_args(const dt_dctx_t *dctx, uint32_t idx)
> > {
> > dt_mstate_t *mst = dctx->mst;
> > - switch (id) {
> > - case DIF_VAR_CURTHREAD:
> > - return bpf_get_current_task();
> > - case DIF_VAR_TIMESTAMP:
> > - if (mst->tstamp == 0)
> > - mst->tstamp = bpf_ktime_get_ns();
> > + if (idx >= sizeof(mst->argv) / sizeof(mst->argv[0]))
> > + return error(dctx, DTRACEFLT_ILLOP, 0);
> > - return mst->tstamp;
> > - case DIF_VAR_EPID: {
> > - return (((uint64_t)mst->prid) << 32) | mst->stid;
> > - }
> > - case DIF_VAR_ID:
> > - return mst->prid;
> > - case DIF_VAR_ARG0: case DIF_VAR_ARG1: case DIF_VAR_ARG2:
> > - case DIF_VAR_ARG3: case DIF_VAR_ARG4: case DIF_VAR_ARG5:
> > - case DIF_VAR_ARG6: case DIF_VAR_ARG7: case DIF_VAR_ARG8:
> > - case DIF_VAR_ARG9:
> > - return mst->argv[id - DIF_VAR_ARG0];
> > - case DIF_VAR_ARGS:
> > - if (idx >= sizeof(mst->argv) / sizeof(mst->argv[0]))
> > - return error(dctx, DTRACEFLT_ILLOP, 0);
> > -
> > - return mst->argv[idx];
> > - case DIF_VAR_STACKDEPTH:
> > - case DIF_VAR_USTACKDEPTH: {
> > - uint32_t bufsiz = (uint32_t) (uint64_t) (&STKSIZ);
> > - uint64_t flags;
> > - char *buf = dctx->mem + (uint64_t)(&STACK_OFF);
> > - uint64_t stacksize;
> > -
> > - if (id == DIF_VAR_USTACKDEPTH)
> > - flags = BPF_F_USER_STACK;
> > - else
> > - flags = (uint64_t)(&STACK_SKIP) & BPF_F_SKIP_FIELD_MASK;
> > -
> > - stacksize = bpf_get_stack(dctx->ctx, buf, bufsiz, flags);
> > - if (stacksize < 0)
> > - return error(dctx, DTRACEFLT_BADSTACK, 0 /* FIXME */);
> > + return mst->argv[idx];
> > +}
> > +
> > +noinline uint64_t dt_bvar_caller(const dt_dctx_t *dctx)
> > +{
> > + uint64_t buf[2] = { 0, };
> > + if (bpf_get_stack(dctx->ctx, buf, sizeof(buf),
> > + (uint64_t)(&STACK_SKIP) & BPF_F_SKIP_FIELD_MASK) < 0)
> > + return 0;
> > +
> > + return buf[1];
> > +}
> > +
> > +noinline uint64_t dt_bvar_curcpu(const dt_dctx_t *dctx)
> > +{
> > + uint32_t key = 0;
> > + void *val = bpf_map_lookup_elem(&cpuinfo, &key);
> > +
> > + if (val == NULL) {
> > /*
> > - * While linux/bpf.h does not describe the meaning of
> > - * bpf_get_stack()'s return value outside of its sign,
> > - * it is presumably the length of the copied stack.
> > - *
> > - * If stacksize==bufsiz, presumably the stack is larger than
> > - * what we can retrieve. But it's also possible that the
> > - * buffer was exactly large enough. So, leave it to the user
> > - * to interpret the result.
> > + * Typically, we would use 'return error(...);' but
> > + * that confuses the verifier because it returns -1.
> > + * So, instead, we explicitly return 0.
> > */
> > - return stacksize / sizeof(uint64_t);
> > - }
> > - case DIF_VAR_CALLER:
> > - case DIF_VAR_UCALLER: {
> > - uint64_t flags;
> > - uint64_t buf[2] = { 0, };
> > -
> > - if (id == DIF_VAR_UCALLER)
> > - flags = BPF_F_USER_STACK;
> > - else
> > - flags = (uint64_t)(&STACK_SKIP) & BPF_F_SKIP_FIELD_MASK;
> > -
> > - if (bpf_get_stack(dctx->ctx, buf, sizeof(buf), flags) < 0)
> > - return 0;
> > - return buf[1];
> > + error(dctx, DTRACEFLT_ILLOP, 0);
> > + return 0;
> > }
> > - case DIF_VAR_PROBEPROV:
> > - case DIF_VAR_PROBEMOD:
> > - case DIF_VAR_PROBEFUNC:
> > - case DIF_VAR_PROBENAME: {
> > - uint32_t key = mst->prid;
> > -
> > - if (key < ((uint64_t)&NPROBES)) {
> > - dt_bpf_probe_t *pinfo;
> > - uint64_t off;
> > -
> > - pinfo = bpf_map_lookup_elem(&probes, &key);
> > - if (pinfo == NULL)
> > - return (uint64_t)dctx->strtab;
> > -
> > - switch (id) {
> > - case DIF_VAR_PROBEPROV:
> > - off = pinfo->prv;
> > - break;
> > - case DIF_VAR_PROBEMOD:
> > - off = pinfo->mod;
> > - break;
> > - case DIF_VAR_PROBEFUNC:
> > - off = pinfo->fun;
> > - break;
> > - case DIF_VAR_PROBENAME:
> > - off = pinfo->prb;
> > - }
> > - if (off > (uint64_t)&STBSZ)
> > - return (uint64_t)dctx->strtab;
> > -
> > - return (uint64_t)(dctx->strtab + off);
> > - } else {
> > - char *s;
> > -
> > - s = bpf_map_lookup_elem(&usdt_names, &key);
> > - if (s == NULL)
> > - return (uint64_t)dctx->strtab;
> > -
> > - switch (id) {
> > - case DIF_VAR_PROBENAME:
> > - s += DTRACE_FUNCNAMELEN;
> > - case DIF_VAR_PROBEFUNC:
> > - s += DTRACE_MODNAMELEN;
> > - case DIF_VAR_PROBEMOD:
> > - s += DTRACE_PROVNAMELEN;
> > - case DIF_VAR_PROBEPROV:
> > - }
> > -
> > - return (uint64_t)s;
> > - }
> > - }
> > - case DIF_VAR_PID: {
> > - uint64_t val = bpf_get_current_pid_tgid();
> > - return val >> 32;
> > - }
> > - case DIF_VAR_TID: {
> > - uint64_t val = bpf_get_current_pid_tgid();
> > + return (uint64_t)val;
> > +}
> > - return val & 0x00000000ffffffffUL;
> > - }
> > - case DIF_VAR_EXECNAME: {
> > - uint64_t ptr;
> > - extern uint64_t TASK_COMM;
> > +noinline uint64_t dt_bvar_curthread(const dt_dctx_t *dctx)
> > +{
> > + return bpf_get_current_task();
> > +}
> > - /* &(current->comm) */
> > - ptr = bpf_get_current_task();
> > - if (ptr == 0)
> > - return error(dctx, DTRACEFLT_BADADDR, ptr);
> > +noinline uint64_t dt_bvar_epid(const dt_dctx_t *dctx)
> > +{
> > + dt_mstate_t *mst = dctx->mst;
> > - return (uint64_t)ptr + (uint64_t)&TASK_COMM;
> > - }
> > - case DIF_VAR_WALLTIMESTAMP:
> > - return bpf_ktime_get_ns() + ((uint64_t)&BOOTTM);
> > - case DIF_VAR_PPID: {
> > - uint64_t ptr;
> > - int32_t val = -1;
> > - extern uint64_t TASK_REAL_PARENT;
> > - extern uint64_t TASK_TGID;
> > -
> > - /* Chase pointers val = current->real_parent->tgid. */
> > - ptr = bpf_get_current_task();
> > - if (ptr == 0)
> > - return error(dctx, DTRACEFLT_BADADDR, ptr);
> > - if (bpf_probe_read((void *)&ptr, 8,
> > - (const void *)(ptr + (uint64_t)&TASK_REAL_PARENT)))
> > - return error(dctx, DTRACEFLT_BADADDR, ptr + (uint64_t)&TASK_REAL_PARENT);
> > - if (bpf_probe_read((void *)&val, 4,
> > - (const void *)(ptr + (uint64_t)&TASK_TGID)))
> > - return error(dctx, DTRACEFLT_BADADDR, ptr + (uint64_t)&TASK_TGID);
> > -
> > - return (uint64_t)val;
> > - }
> > - case DIF_VAR_UID: {
> > - uint64_t val = bpf_get_current_uid_gid();
> > + return (((uint64_t)mst->prid) << 32) | mst->stid;
> > +}
> > - return val & 0x00000000ffffffffUL;
> > - }
> > - case DIF_VAR_GID: {
> > - uint64_t val = bpf_get_current_uid_gid();
> > +noinline uint64_t dt_bvar_errno(const dt_dctx_t *dctx)
> > +{
> > + dt_mstate_t *mst = dctx->mst;
> > - return val >> 32;
> > - }
> > - case DIF_VAR_ERRNO:
> > - return mst->syscall_errno;
> > - case DIF_VAR_CURCPU: {
> > - uint32_t key = 0;
> > - void *val = bpf_map_lookup_elem(&cpuinfo, &key);
> > -
> > - if (val == NULL) {
> > - /*
> > - * Typically, we would use 'return error(...);' but
> > - * that confuses the verifier because it returns -1.
> > - * So, instead, we explicitly return 0.
> > - */
> > - error(dctx, DTRACEFLT_ILLOP, 0);
> > - return 0;
> > + return mst->syscall_errno;
> > +}
> > +
> > +noinline uint64_t dt_bvar_execname(const dt_dctx_t *dctx)
> > +{
> > + uint64_t ptr;
> > +
> > + /* &(current->comm) */
> > + ptr = bpf_get_current_task();
> > + if (ptr == 0)
> > + return error(dctx, DTRACEFLT_BADADDR, ptr);
> > +
> > + return (uint64_t)ptr + (uint64_t)&TASK_COMM;
> > +}
> > +
> > +noinline uint64_t dt_bvar_gid(const dt_dctx_t *dctx)
> > +{
> > + return bpf_get_current_uid_gid() >> 32;
> > +}
> > +
> > +noinline uint64_t dt_bvar_id(const dt_dctx_t *dctx)
> > +{
> > + dt_mstate_t *mst = dctx->mst;
> > +
> > + return mst->prid;
> > +}
> > +
> > +noinline uint64_t dt_bvar_pid(const dt_dctx_t *dctx)
> > +{
> > + return bpf_get_current_pid_tgid() >> 32;
> > +}
> > +
> > +noinline uint64_t dt_bvar_ppid(const dt_dctx_t *dctx)
> > +{
> > + uint64_t ptr;
> > + int32_t val = -1;
> > +
> > + /* Chase pointers val = current->real_parent->tgid. */
> > + ptr = bpf_get_current_task();
> > + if (ptr == 0)
> > + return error(dctx, DTRACEFLT_BADADDR, ptr);
> > + if (bpf_probe_read((void *)&ptr, 8,
> > + (const void *)(ptr + (uint64_t)&TASK_REAL_PARENT)))
> > + return error(dctx, DTRACEFLT_BADADDR, ptr + (uint64_t)&TASK_REAL_PARENT);
> > + if (bpf_probe_read((void *)&val, 4,
> > + (const void *)(ptr + (uint64_t)&TASK_TGID)))
> > + return error(dctx, DTRACEFLT_BADADDR, ptr + (uint64_t)&TASK_TGID);
> > +
> > + return (uint64_t)val;
> > +}
> > +
> > +noinline uint64_t dt_bvar_probedesc(const dt_dctx_t *dctx, uint32_t idx)
> > +{
> > + dt_mstate_t *mst = dctx->mst;
> > + uint32_t key = mst->prid;
> > +
> > + if (key < ((uint64_t)&NPROBES)) {
> > + dt_bpf_probe_t *pinfo;
> > + uint64_t off = 0;
> > +
> > + pinfo = bpf_map_lookup_elem(&probes, &key);
> > + if (pinfo == NULL)
> > + return (uint64_t)dctx->strtab;
> > +
> > + switch (idx) {
> > + case DIF_VAR_PROBEPROV:
> > + off = pinfo->prv;
> > + break;
> > + case DIF_VAR_PROBEMOD:
> > + off = pinfo->mod;
> > + break;
> > + case DIF_VAR_PROBEFUNC:
> > + off = pinfo->fun;
> > + break;
> > + case DIF_VAR_PROBENAME:
> > + off = pinfo->prb;
> > }
> > + if (off > (uint64_t)&STBSZ)
> > + return (uint64_t)dctx->strtab;
> > - return (uint64_t)val;
> > - }
> > - default:
> > - /* Not implemented yet. */
> > - return error(dctx, DTRACEFLT_ILLOP, 0);
> > + return (uint64_t)(dctx->strtab + off);
> > + } else {
> > + char *s;
> > +
> > + s = bpf_map_lookup_elem(&usdt_names, &key);
> > + if (s == NULL)
> > + return (uint64_t)dctx->strtab;
> > +
> > + switch (idx) {
> > + case DIF_VAR_PROBEPROV:
> > + s += DTRACE_FUNCNAMELEN;
> > + case DIF_VAR_PROBEMOD:
> > + s += DTRACE_MODNAMELEN;
> > + case DIF_VAR_PROBEFUNC:
> > + s += DTRACE_PROVNAMELEN;
> > + case DIF_VAR_PROBENAME:
> > + }
> > +
> > + return (uint64_t)s;
> > }
> > }
> > +
> > +noinline uint64_t dt_bvar_stackdepth(const dt_dctx_t *dctx)
> > +{
> > + uint32_t bufsiz = (uint32_t) (uint64_t) (&STKSIZ);
> > + char *buf = dctx->mem + (uint64_t)(&STACK_OFF);
> > + uint64_t retv;
> > +
> > + retv = bpf_get_stack(dctx->ctx, buf, bufsiz,
> > + (uint64_t)(&STACK_SKIP) & BPF_F_SKIP_FIELD_MASK);
> > + if (retv < 0)
> > + return error(dctx, DTRACEFLT_BADSTACK, 0 /* FIXME */);
> > +
> > + /*
> > + * While linux/bpf.h does not describe the meaning of bpf_get_stack()'s
> > + * return value outside of its sign, it is presumably the length of the
> > + * copied stack.
> > + *
> > + * If retv==bufsiz, presumably the stack is larger than what we
> > + * can retrieve. But it's also possible that the buffer was exactly
> > + * large enough. So, leave it to the user to interpret the result.
> > + */
> > + return retv / sizeof(uint64_t);
> > +}
> > +
> > +noinline uint64_t dt_bvar_tid(const dt_dctx_t *dctx)
> > +{
> > + return bpf_get_current_pid_tgid() & 0x00000000ffffffffUL;
> > +}
> > +
> > +noinline uint64_t dt_bvar_timestamp(const dt_dctx_t *dctx)
> > +{
> > + dt_mstate_t *mst = dctx->mst;
> > +
> > + if (mst->tstamp == 0)
> > + mst->tstamp = bpf_ktime_get_ns();
> > +
> > + return mst->tstamp;
> > +}
> > +
> > +noinline uint64_t dt_bvar_ucaller(const dt_dctx_t *dctx)
> > +{
> > + uint64_t buf[2] = { 0, };
> > +
> > + if (bpf_get_stack(dctx->ctx, buf, sizeof(buf), BPF_F_USER_STACK) < 0)
> > + return 0;
> > +
> > + return buf[1];
> > +}
> > +
> > +noinline uint64_t dt_bvar_uid(const dt_dctx_t *dctx)
> > +{
> > + return bpf_get_current_uid_gid() & 0x00000000ffffffffUL;
> > +}
> > +
> > +noinline uint64_t dt_bvar_ustackdepth(const dt_dctx_t *dctx)
> > +{
> > + uint32_t bufsiz = (uint32_t) (uint64_t) (&STKSIZ);
> > + char *buf = dctx->mem + (uint64_t)(&STACK_OFF);
> > + uint64_t retv;
> > +
> > + retv = bpf_get_stack(dctx->ctx, buf, bufsiz, BPF_F_USER_STACK);
> > + if (retv < 0)
> > + return error(dctx, DTRACEFLT_BADSTACK, 0 /* FIXME */);
> > +
> > + /* See dt_bvar_stackdepth() above. */
> > + return retv / sizeof(uint64_t);
> > +}
> > +
> > +noinline uint64_t dt_bvar_walltimestamp(const dt_dctx_t *dctx)
> > +{
> > + return bpf_ktime_get_ns() + ((uint64_t)&BOOTTM);
> > +}
> > diff --git a/include/dtrace/dif_defines.h b/include/dtrace/dif_defines.h
> > index c8c1d961..9f6e3b55 100644
> > --- a/include/dtrace/dif_defines.h
> > +++ b/include/dtrace/dif_defines.h
> > @@ -162,6 +162,7 @@
> > #define DIF_VAR_GID 0x011f
> > #define DIF_VAR_ERRNO 0x0120
> > #define DIF_VAR_CURCPU 0x0121
> > +#define DIF_VAR_EXECARGS 0x0122
> > #define DIF_SUBR_RAND 0
> > #define DIF_SUBR_MUTEX_OWNED 1
> > diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> > index e7e3a132..6e74b4b0 100644
> > --- a/libdtrace/dt_cg.c
> > +++ b/libdtrace/dt_cg.c
> > @@ -3197,6 +3197,7 @@ dt_cg_load_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > {
> > dt_ident_t *idp = dt_ident_resolve(dnp->dn_ident);
> > dt_ident_t *fnp;
> > + uint32_t idx = UINT32_MAX;
> > idp->di_flags |= DT_IDFLG_DIFR;
> > @@ -3298,15 +3299,38 @@ dt_cg_load_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > return;
> > }
> > - /* built-in variables */
> > + /* built-in variables (note: args[] is handled in dt_cg_array_op) */
> > + /* Special case for arg0 through arg9; encode as args[n] */
> > + if (idp->di_id >= DIF_VAR_ARG0 && idp->di_id <= DIF_VAR_ARG9) {
> > + fnp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_bvar_args");
> > + idx = idp->di_id - DIF_VAR_ARG0;
> > + } else if (idp->di_id == DIF_VAR_PROBEPROV ||
> > + idp->di_id == DIF_VAR_PROBEMOD ||
> > + idp->di_id == DIF_VAR_PROBEFUNC ||
> > + idp->di_id == DIF_VAR_PROBENAME) {
> > + fnp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_bvar_probedesc");
> > + idx = idp->di_id;
> > + } else {
> > + char *fn;
> > +
> > + if (asprintf(&fn, "dt_bvar_%s", idp->di_name) == -1)
> > + longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
> > +
> > + fnp = dt_dlib_get_func(yypcb->pcb_hdl, fn);
> > + free(fn);
> > + }
> > +
> > + /* No implementing function found - report ILLOP. */
> > + if (fnp == NULL)
> > + xyerror(D_IDENT_UNDEF,
> > + "built-in variable '%s' not implemented", idp->di_name);
> > +
> > if (dt_regset_xalloc_args(drp) == -1)
> > longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> > dt_cg_access_dctx(BPF_REG_1, dlp, drp, -1);
> > - emit(dlp, BPF_MOV_IMM(BPF_REG_2, idp->di_id));
> > - emit(dlp, BPF_MOV_IMM(BPF_REG_3, 0));
> > - fnp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_bvar");
> > - assert(fnp != NULL);
> > + if (idx != UINT32_MAX)
> > + emit(dlp, BPF_MOV_IMM(BPF_REG_2, idx));
> > dt_regset_xalloc(drp, BPF_REG_0);
> > emite(dlp, BPF_CALL_FUNC(fnp->di_id), fnp);
> > dt_regset_free_args(drp);
> > @@ -5065,7 +5089,7 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > dt_probe_t *prp = yypcb->pcb_probe;
> > uintmax_t saved = dnp->dn_args->dn_value;
> > dt_ident_t *idp = dnp->dn_ident;
> > - dt_ident_t *fidp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_bvar");
> > + dt_ident_t *fidp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_bvar_args");
> > size_t size;
> > int n;
> > int ustr = 0;
> > @@ -5135,8 +5159,7 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
> > if (dt_regset_xalloc_args(drp) == -1)
> > longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> > dt_cg_access_dctx(BPF_REG_1, dlp, drp, -1);
> > - emit(dlp, BPF_MOV_IMM(BPF_REG_2, idp->di_id));
> > - emit(dlp, BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
> > + emit(dlp, BPF_MOV_REG(BPF_REG_2, dnp->dn_reg));
> > dt_regset_xalloc(drp, BPF_REG_0);
> > emite(dlp, BPF_CALL_FUNC(fidp->di_id), fidp);
> > dt_regset_free_args(drp);
> > diff --git a/libdtrace/dt_dis.c b/libdtrace/dt_dis.c
> > index 9f319d70..d983c099 100644
> > --- a/libdtrace/dt_dis.c
> > +++ b/libdtrace/dt_dis.c
> > @@ -364,16 +364,57 @@ static char *
> > dt_dis_bpf_args(const dtrace_difo_t *dp, const char *fn,
> > const struct bpf_insn *in, char *buf, size_t len, uint_t addr)
> > {
> > - if (strcmp(fn, "dt_get_bvar") == 0) {
> > + if (strcmp(fn, "dt_bvar_args") == 0) {
> > /*
> > - * We know that the previous two instructions exist and move
> > - * the variable id to a register in the first instruction of
> > - * that sequence (because we wrote the code generator to emit
> > - * the instructions in this exact order.)
> > + * We need to support two cases:
> > + * - access to argN:
> > + * lddw %r1, dctx
> > + * mov %r2, N
> > + * call dt_bvar_args
> > + * - access to args[N]:
> > + * mov %rX, N
> > + * lddw %r1, dctx
> > + * mov %r2, %rX
> > + * call dt_bvar_args
> > */
> > - in -= 2;
> > - snprintf(buf, len, "%s",
> > - dt_dis_varname_id(dp, in->imm, DIFV_SCOPE_GLOBAL, addr));
> > + in--;
> > + if (BPF_OP(in->code) == BPF_MOV && in->dst_reg == 2) {
> > + if (BPF_SRC(in->code) == BPF_K) {
> > + snprintf(buf, len, "arg%d", in->imm);
> > + return buf;
> > + }
> > +
> > + in -= 2;
> > + if (BPF_OP(in->code) == BPF_MOV &&
> > + BPF_SRC(in->code) == BPF_K &&
> > + in->dst_reg == in[2].src_reg) {
> > + snprintf(buf, len, "args[%d]", in->imm);
> > + return buf;
> > + }
> > + }
> > +
> > + snprintf(buf, len, "args[?]");
> > + return buf;
> > + } else if (strcmp(fn, "dt_bvar_probedesc") == 0) {
> > + /*
> > + * Access to probe(prov|mod|func|name);
> > + * lddw %r1, dctx
> > + * mov %r2, N
> > + * call dt_bvar_probedesc
> > + */
> > + in--;
> > + if (BPF_OP(in->code) == BPF_MOV && in->dst_reg == 2 &&
> > + BPF_SRC(in->code) == BPF_K) {
> > + snprintf(buf, len, "%s",
> > + dt_dis_varname_id(dp, in->imm,
> > + DIFV_SCOPE_GLOBAL, addr));
> > + return buf;
> > + }
> > +
> > + return NULL;
> > + } else if (strncmp(fn, "dt_bvar_", 8) == 0) {
> > + /* The variable name is in the function name.*/
> > + snprintf(buf, len, "%s", fn + 8);
> > return buf;
> > } else if (strcmp(fn, "dt_get_agg") == 0) {
> > /*
> > diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
> > index a0205887..51c056b2 100644
> > --- a/libdtrace/dt_open.c
> > +++ b/libdtrace/dt_open.c
> > @@ -153,6 +153,8 @@ static const dt_ident_t _dtrace_globals[] = {
> > &dt_idops_type, "uint64_t" },
> > { "errno", DT_IDENT_SCALAR, 0, DIF_VAR_ERRNO, DT_ATTR_STABCMN, DT_VERS_1_0,
> > &dt_idops_type, "int" },
> > +{ "execargs", DT_IDENT_SCALAR, 0, DIF_VAR_EXECARGS,
> > + DT_ATTR_STABCMN, DT_VERS_2_0, &dt_idops_type, "string" },
> > { "execname", DT_IDENT_SCALAR, 0, DIF_VAR_EXECNAME,
> > DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "string" },
> > { "exit", DT_IDENT_ACTFUNC, 0, DT_ACT_EXIT, DT_ATTR_STABCMN, DT_VERS_1_0,
> > diff --git a/test/demo/builtin/ipl.d b/test/demo/builtin/ipl.d
> > index ca7f3bb7..f613bb70 100644
> > --- a/test/demo/builtin/ipl.d
> > +++ b/test/demo/builtin/ipl.d
> > @@ -1,3 +1,5 @@
> > +/* @@xfail: dtv2: need ipl support */
> > +
> > BEGIN {
> > trace(ipl);
> > exit(0);
> > diff --git a/test/demo/builtin/vtimestamp.d b/test/demo/builtin/vtimestamp.d
> > index 9f01bbf0..fcb708d0 100644
> > --- a/test/demo/builtin/vtimestamp.d
> > +++ b/test/demo/builtin/vtimestamp.d
> > @@ -1,3 +1,5 @@
> > +/* @@xfail: dtv2: need vtimestamp support */
> > +
> > BEGIN {
> > trace(vtimestamp);
> > exit(0);
> > diff --git a/test/demo/io/iocpu.d b/test/demo/io/iocpu.d
> > index c7b847e7..1230d6f6 100644
> > --- a/test/demo/io/iocpu.d
> > +++ b/test/demo/io/iocpu.d
> > @@ -5,6 +5,8 @@
> > * http://oss.oracle.com/licenses/upl.
> > */
> > +/* @@xfail: dtv2: need vtimestamp support */
> > +
> > #pragma D option quiet
> > sched:::on-cpu
> > diff --git a/test/unittest/buffering/tst.cputime.sh b/test/unittest/buffering/tst.cputime.sh
> > index 6a420e8d..c0e248a6 100755
> > --- a/test/unittest/buffering/tst.cputime.sh
> > +++ b/test/unittest/buffering/tst.cputime.sh
> > @@ -5,6 +5,7 @@
> > # Licensed under the Universal Permissive License v 1.0 as shown at
> > # http://oss.oracle.com/licenses/upl.
> > #
> > +# @@xfail: dtv2: need vtimestamp support
> > # @@timeout: 12
> > script()
> > diff --git a/test/unittest/disasm/tst.ann-bvar.r b/test/unittest/disasm/tst.ann-bvar.r
> > index b514dd99..a55fb6de 100644
> > --- a/test/unittest/disasm/tst.ann-bvar.r
> > +++ b/test/unittest/disasm/tst.ann-bvar.r
> > @@ -1,34 +1,35 @@
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg0
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg1
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg2
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg3
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg4
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg5
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg6
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg7
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg8
> > -85 0 1 0000 ffffffff call dt_get_bvar ! arg9
> > -85 0 1 0000 ffffffff call dt_get_bvar ! args
> > -85 0 1 0000 ffffffff call dt_get_bvar ! caller
> > -85 0 1 0000 ffffffff call dt_get_bvar ! curcpu
> > -85 0 1 0000 ffffffff call dt_get_bvar ! curthread
> > -85 0 1 0000 ffffffff call dt_get_bvar ! epid
> > -85 0 1 0000 ffffffff call dt_get_bvar ! errno
> > -85 0 1 0000 ffffffff call dt_get_bvar ! execname
> > -85 0 1 0000 ffffffff call dt_get_bvar ! gid
> > -85 0 1 0000 ffffffff call dt_get_bvar ! id
> > -85 0 1 0000 ffffffff call dt_get_bvar ! ipl
> > -85 0 1 0000 ffffffff call dt_get_bvar ! pid
> > -85 0 1 0000 ffffffff call dt_get_bvar ! ppid
> > -85 0 1 0000 ffffffff call dt_get_bvar ! probefunc
> > -85 0 1 0000 ffffffff call dt_get_bvar ! probemod
> > -85 0 1 0000 ffffffff call dt_get_bvar ! probename
> > -85 0 1 0000 ffffffff call dt_get_bvar ! probeprov
> > -85 0 1 0000 ffffffff call dt_get_bvar ! stackdepth
> > -85 0 1 0000 ffffffff call dt_get_bvar ! tid
> > -85 0 1 0000 ffffffff call dt_get_bvar ! timestamp
> > -85 0 1 0000 ffffffff call dt_get_bvar ! ucaller
> > -85 0 1 0000 ffffffff call dt_get_bvar ! uid
> > -85 0 1 0000 ffffffff call dt_get_bvar ! ustackdepth
> > -85 0 1 0000 ffffffff call dt_get_bvar ! vtimestamp
> > -85 0 1 0000 ffffffff call dt_get_bvar ! walltimestamp
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg0
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg1
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg2
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg3
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg4
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg5
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg6
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg7
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg8
> > +85 0 1 0000 ffffffff call dt_bvar_args ! arg9
> > +85 0 1 0000 ffffffff call dt_bvar_args ! args[0]
> > +85 0 1 0000 ffffffff call dt_bvar_args ! args[1]
> > +85 0 1 0000 ffffffff call dt_bvar_args ! args[2]
> > +85 0 1 0000 ffffffff call dt_bvar_args ! args[3]
> > +85 0 1 0000 ffffffff call dt_bvar_caller ! caller
> > +85 0 1 0000 ffffffff call dt_bvar_curcpu ! curcpu
> > +85 0 1 0000 ffffffff call dt_bvar_curthread ! curthread
> > +85 0 1 0000 ffffffff call dt_bvar_epid ! epid
> > +85 0 1 0000 ffffffff call dt_bvar_errno ! errno
> > +85 0 1 0000 ffffffff call dt_bvar_execname ! execname
> > +85 0 1 0000 ffffffff call dt_bvar_gid ! gid
> > +85 0 1 0000 ffffffff call dt_bvar_id ! id
> > +85 0 1 0000 ffffffff call dt_bvar_pid ! pid
> > +85 0 1 0000 ffffffff call dt_bvar_ppid ! ppid
> > +85 0 1 0000 ffffffff call dt_bvar_probedesc ! probefunc
> > +85 0 1 0000 ffffffff call dt_bvar_probedesc ! probemod
> > +85 0 1 0000 ffffffff call dt_bvar_probedesc ! probename
> > +85 0 1 0000 ffffffff call dt_bvar_probedesc ! probeprov
> > +85 0 1 0000 ffffffff call dt_bvar_stackdepth ! stackdepth
> > +85 0 1 0000 ffffffff call dt_bvar_tid ! tid
> > +85 0 1 0000 ffffffff call dt_bvar_timestamp ! timestamp
> > +85 0 1 0000 ffffffff call dt_bvar_ucaller ! ucaller
> > +85 0 1 0000 ffffffff call dt_bvar_uid ! uid
> > +85 0 1 0000 ffffffff call dt_bvar_ustackdepth ! ustackdepth
> > +85 0 1 0000 ffffffff call dt_bvar_walltimestamp ! walltimestamp
> > diff --git a/test/unittest/disasm/tst.ann-bvar.sh b/test/unittest/disasm/tst.ann-bvar.sh
> > index 6dc43424..61e838d1 100755
> > --- a/test/unittest/disasm/tst.ann-bvar.sh
> > +++ b/test/unittest/disasm/tst.ann-bvar.sh
> > @@ -22,6 +22,9 @@ sdt:task::task_rename
> > trace(arg8);
> > trace(arg9);
> > trace(args[0]);
> > + trace(args[1]);
> > + trace(args[2]);
> > + trace(args[3]);
> > trace(caller);
> > trace(curcpu);
> > trace(curthread);
> > @@ -30,7 +33,7 @@ sdt:task::task_rename
> > trace(execname);
> > trace(gid);
> > trace(id);
> > - trace(ipl);
> > +/* trace(ipl); */
> > trace(pid);
> > trace(ppid);
> > trace(probefunc);
> > @@ -43,10 +46,10 @@ sdt:task::task_rename
> > trace(ucaller);
> > trace(uid);
> > trace(ustackdepth);
> > - trace(vtimestamp);
> > +/* trace(vtimestamp); */
> > trace(walltimestamp);
> > exit(0);
> > }
> > -' 2>&1 | gawk '/ call dt_get_bvar/ { sub(/^[^:]+: /, ""); print; }'
> > +' 2>&1 | gawk '/ call dt_bvar_/ { sub(/^[^:]+: /, ""); print; }'
> > exit $?
> > diff --git a/test/unittest/disasm/tst.vartab-bvar.r b/test/unittest/disasm/tst.vartab-bvar.r
> > index 53e5f618..04fa3a8d 100644
> > --- a/test/unittest/disasm/tst.vartab-bvar.r
> > +++ b/test/unittest/disasm/tst.vartab-bvar.r
> > @@ -2,8 +2,6 @@ NAME OFFSET KND SCP FLAG TYPE
> > args arr glb r any (unknown) by ref (size 0)
> > curthread scl glb r D type (pointer) (size 8)
> > timestamp scl glb r D type (integer) (size 8)
> > -vtimestamp scl glb r D type (integer) (size 8)
> > -ipl scl glb r D type (integer) (size 4)
> > epid scl glb r D type (integer) (size 8)
> > id scl glb r D type (integer) (size 4)
> > arg0 scl glb r D type (integer) (size 8)
> > diff --git a/test/unittest/disasm/tst.vartab-bvar.sh b/test/unittest/disasm/tst.vartab-bvar.sh
> > index 098c1f45..ce489a24 100755
> > --- a/test/unittest/disasm/tst.vartab-bvar.sh
> > +++ b/test/unittest/disasm/tst.vartab-bvar.sh
> > @@ -30,6 +30,9 @@ sdt:task::task_rename
> > trace(arg8);
> > trace(arg9);
> > trace(args[0]);
> > + trace(args[1]);
> > + trace(args[2]);
> > + trace(args[3]);
> > trace(caller);
> > trace(curcpu);
> > trace(curthread);
> > @@ -38,7 +41,7 @@ sdt:task::task_rename
> > trace(execname);
> > trace(gid);
> > trace(id);
> > - trace(ipl);
> > +/* trace(ipl); */
> > trace(pid);
> > trace(ppid);
> > trace(probefunc);
> > @@ -52,7 +55,7 @@ sdt:task::task_rename
> > trace(uid);
> > /* trace(uregs[0]); */ /* test this separately until uregs[0] works on all kernels */
> > trace(ustackdepth);
> > - trace(vtimestamp);
> > +/* trace(vtimestamp); */
> > trace(walltimestamp);
> > exit(0);
> > }
More information about the DTrace-devel
mailing list