[DTrace-devel] [PATCH] bpf: separate bvar implementation into separate functions

Eugene Loh eugene.loh at oracle.com
Fri Jan 24 07:35:49 UTC 2025


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?

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.

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