[DTrace-devel] [PATCH v2 1/6] bpf: separate bvar implementation into separate functions

Kris Van Hees kris.van.hees at oracle.com
Tue Jan 28 06:31:40 UTC 2025


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 +++++++++++++-----------
 libdtrace/dt_cg.c                       |  39 ++-
 libdtrace/dt_dis.c                      |  57 +++-
 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 +-
 11 files changed, 357 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/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/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);
 }
-- 
2.45.2




More information about the DTrace-devel mailing list