The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=dabde7d97680cac7e0ead56693d424f4e5631019
commit dabde7d97680cac7e0ead56693d424f4e5631019 Author: Mark Johnston <ma...@freebsd.org> AuthorDate: 2025-07-21 13:34:30 +0000 Commit: Mark Johnston <ma...@freebsd.org> CommitDate: 2025-07-21 14:57:58 +0000 libdtrace: Permit taking the address of an identifier without type info Symbols defined using assembler directives lack type info, but in this case one ought to be able to cast a pointer to the symbol and dereference the pointer to get a value. Without this change, D disallows this trick since it requires all identifiers to have a type. Relax the rules slightly and allow an identifier to have type "void" if we know we're just taking its address. As a result, the following dtrace invocation works: dtrace -n 'tick-1s {printf("%d", *(int *)&`ticks);}' In particular, since commit b2b974f7ef4c ("clock: Simplify subr_ticks and rename"), "ticks" does not have any type info associated with it, so its value couldn't be printed. This trick provides a workaround and is probably generally useful. Add a regression test which exercises this functionality. PR: 287752 Reviewed by: avg MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D51417 --- .../dtrace/test/tst/common/profile-n/tst.ticks.d | 54 ++++++++++++++++++++++ .../opensolaris/lib/libdtrace/common/dt_parser.c | 25 ++++++++-- .../opensolaris/lib/libdtrace/common/dt_parser.h | 1 + .../dtrace/tests/common/profile-n/Makefile | 1 + 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/profile-n/tst.ticks.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/profile-n/tst.ticks.d new file mode 100644 index 000000000000..4061db9858c1 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/profile-n/tst.ticks.d @@ -0,0 +1,54 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2025 Mark Johnston <ma...@freebsd.org> + */ + +/* + * For 10s, verify that the value of `ticks goes up by `hz each second. + */ + +#pragma D option quiet + +BEGIN +{ + i = 0; +} + +tick-1s +{ + if (i == 0) { + t = *(int *)&`ticks; + i++; + } else { + u = *(int *)&`ticks; + if (u - t != `hz) { + printf("ticks: %d, expected %d\n", u - t, `hz); + exit(1); + } + t = u; + i++; + if (i == 10) { + exit(0); + } + } +} diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c index dd68f9278308..8cc504856567 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c @@ -1918,6 +1918,14 @@ dt_node_op1(int op, dt_node_t *cp) return (cp); } + /* + * When applying the addressof operator to an identifier, it's okay if + * we can't find type information for the identifier, so flag the node + * to ensure that we don't raise an error. + */ + if (op == DT_TOK_ADDROF && cp->dn_kind == DT_NODE_IDENT) + cp->dn_flags |= DT_NF_IDENTADDR; + dnp = dt_node_alloc(DT_NODE_OP1); assert(op <= USHRT_MAX); dnp->dn_op = (ushort_t)op; @@ -2786,10 +2794,21 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create) dt_module_modelname(dtp->dt_ddefs)); } - xyerror(D_SYM_NOTYPES, + /* + * If we're taking the address of an identifier that + * doesn't have type info, try to make it a void *. + * This lets us use identifiers that are defined in + * assembly and don't have type information. + */ + if ((dnp->dn_flags & DT_NF_IDENTADDR) == 0 || + dtrace_lookup_by_type(dtp, DTRACE_OBJ_CDEFS, + "void", &dtt) != 0) { + xyerror(D_SYM_NOTYPES, "no symbolic type information is available for " - "%s%s%s: %s\n", dts.dts_object, mark, dts.dts_name, - dtrace_errmsg(dtp, dtrace_errno(dtp))); + "%s%s%s: %s\n", dts.dts_object, mark, + dts.dts_name, + dtrace_errmsg(dtp, dtrace_errno(dtp))); + } } idp = dt_ident_create(name, DT_IDENT_SYMBOL, 0, 0, diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h index 3a146c5d2592..1d2f33beee0f 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h @@ -182,6 +182,7 @@ typedef struct dt_node { #define DT_NF_WRITABLE 0x10 /* node is writable (can be modified) */ #define DT_NF_BITFIELD 0x20 /* node is an integer bitfield */ #define DT_NF_USERLAND 0x40 /* data is a userland address */ +#define DT_NF_IDENTADDR 0x80 /* node is an identifier address */ #define DT_TYPE_NAMELEN 128 /* reasonable size for ctf_type_name() */ diff --git a/cddl/usr.sbin/dtrace/tests/common/profile-n/Makefile b/cddl/usr.sbin/dtrace/tests/common/profile-n/Makefile index 84f4706b61ee..ceb52fcf5bd0 100644 --- a/cddl/usr.sbin/dtrace/tests/common/profile-n/Makefile +++ b/cddl/usr.sbin/dtrace/tests/common/profile-n/Makefile @@ -37,6 +37,7 @@ ${PACKAGE}FILES= \ tst.profileusec.d \ tst.profileusec.d.out \ tst.sym.ksh \ + tst.ticks.d \ tst.ufunc.ksh \ tst.ufuncsort.ksh \ tst.ufuncsort.ksh.out \