[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