[DTrace-devel] [PATCH 3/3] parser, xlators, printf, cg, ident: resolve forwards to real types

Nick Alcock nick.alcock at oracle.com
Tue Sep 21 05:23:31 PDT 2021


In contrast to libdtrace-ctf (which didn't reliably handle conflicted
structs and unions at all and often just assumed they weren't
conflicting, leading to corrupted type graphs), libctf's deduplicator
reliably identifies conflicted structs and unions, and avoids getting
caught in cycles while maximizing the number of shared types by
routinely converting conflicted structs and unions into forwards and
leaving the forward in the shared dict as a marker.

This means that forwards can and do appear in the shared graph in places
where they would be forbidden in C because there are things you can't do
with incomplete types: you can see things like arrays of forwards.  We'd
rather not inflict this on our users, so introduce a new dt_type_resolve
which is like ctf_type_resolve except that rather than returning a
forward when called on a type in the shared dict, it hunts through the
module list for the first non-forward with a matching name and suitable
kind (so a forward to 'struct foo' will only match a real 'struct foo',
not 'union foo'), returning the dict as well.  It only returns a forward
if no suitable complete type is found in any module at all.

This search can be relatively expensive, because it might involve
loading lots of modules, but it only happens when conflicted forwards
are found, which isn't all that common: and correctness trumps
performance anyway.

This is made a bit more complex because there were several places where
we weren't bothering to call ctf_type_resolve at all but where a
resolution is nonetheless required in any case (e.g. dt_idsize_type)
and a number of places where we were just *assuming* that
ctf_type_resolve succeeded (most unwise).  There are also a number of
places where we need to track both the fp of the original type and the
fp of the resolved type, notably in xlator-related code.

A couple of places have to *avoid* searching for real types, in
particular if a forward is found in the C and D dicts: dt_type_resolve
takes a flag to turn this off.  This was spotted heuristically (i.e.
a test failed): I don't *think* there are any places where this needs
doing that I missed, but I could be wrong.

(In the future some of this commit may be unwindable, if and when libctf
gains the ability to search for forwards in archives in the same way we
are doing here.  It seems like a worthwhile API addition.)

Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
---
 libdtrace/dt_cg.c     |  25 +++--
 libdtrace/dt_decl.c   |  18 ++--
 libdtrace/dt_ident.c  |   8 +-
 libdtrace/dt_impl.h   |   6 ++
 libdtrace/dt_module.c | 129 ++++++++++++++++++++++-
 libdtrace/dt_parser.c | 230 ++++++++++++++++++++++++++++++------------
 libdtrace/dt_parser.h |   2 +-
 libdtrace/dt_printf.c |  19 ++--
 libdtrace/dt_xlator.c |  31 +++---
 libdtrace/dt_xlator.h |   2 +
 10 files changed, 362 insertions(+), 108 deletions(-)

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 467317de1a66..40f9a23883e2 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -1872,8 +1872,12 @@ dt_cg_load(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type)
 	if ((dnp->dn_flags & DT_NF_BITFIELD) &&
 	    ctf_type_encoding(ctfp, type, &e) != CTF_ERR)
 		size = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY);
-	else
+	else {
+		if (ctf_type_kind(ctfp, type) == CTF_K_FORWARD)
+			type = dt_type_resolve(yypcb->pcb_hdl, &ctfp,
+			    type, 0);
 		size = ctf_type_size(ctfp, type);
+	}
 
 	if (size < 1 || size > 8 || (size & (size - 1)) != 0) {
 		xyerror(D_UNKNOWN, "internal error -- cg cannot load "
@@ -1995,7 +1999,7 @@ dt_cg_ptrsize(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
 	uint_t kind;
 	ssize_t size;
 
-	type = ctf_type_resolve(ctfp, dnp->dn_type);
+	type = dt_type_resolve(yypcb->pcb_hdl, &ctfp, dnp->dn_type, 0);
 	kind = ctf_type_kind(ctfp, type);
 	assert(kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
 
@@ -2098,14 +2102,14 @@ dt_cg_field_set(dt_node_t *src, dt_irlist_t *dlp,
 	assert(dst->dn_right->dn_kind == DT_NODE_IDENT);
 
 	fp = dst->dn_left->dn_ctfp;
-	type = ctf_type_resolve(fp, dst->dn_left->dn_type);
+	type = dt_type_resolve(yypcb->pcb_hdl, &fp, dst->dn_left->dn_type, 0);
 
 	if (dst->dn_op == DT_TOK_PTR) {
 		type = ctf_type_reference(fp, type);
-		type = ctf_type_resolve(fp, type);
+		type = dt_type_resolve(yypcb->pcb_hdl, &fp, type, 0);
 	}
 
-	if ((fp = dt_cg_membinfo(ofp = fp, type,
+	if ((fp = dt_cg_membinfo(ofp = dst->dn_left->dn_ctfp, type,
 	    dst->dn_right->dn_string, &m)) == NULL) {
 		yypcb->pcb_hdl->dt_ctferr = ctf_errno(ofp);
 		longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
@@ -2485,7 +2489,7 @@ dt_cg_prearith_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
 	ssize_t size = 1;
 
 	if (dt_node_is_pointer(dnp)) {
-		type = ctf_type_resolve(ctfp, dnp->dn_type);
+		type = dt_type_resolve(yypcb->pcb_hdl, &ctfp, dnp->dn_type, 0);
 		assert(ctf_type_kind(ctfp, type) == CTF_K_POINTER);
 		size = ctf_type_size(ctfp, ctf_type_reference(ctfp, type));
 	}
@@ -2533,7 +2537,7 @@ dt_cg_postarith_op(dt_node_t *dnp, dt_irlist_t *dlp,
 	int oreg, nreg;
 
 	if (dt_node_is_pointer(dnp)) {
-		type = ctf_type_resolve(ctfp, dnp->dn_type);
+		type = dt_type_resolve(yypcb->pcb_hdl, &ctfp, dnp->dn_type, 0);
 		assert(ctf_type_kind(ctfp, type) == CTF_K_POINTER);
 		size = ctf_type_size(ctfp, ctf_type_reference(ctfp, type));
 	}
@@ -3581,14 +3585,15 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 		}
 
 		ctfp = dnp->dn_left->dn_ctfp;
-		type = ctf_type_resolve(ctfp, dnp->dn_left->dn_type);
+		type = dt_type_resolve(yypcb->pcb_hdl, &ctfp,
+		    dnp->dn_left->dn_type, 0);
 
 		if (dnp->dn_op == DT_TOK_PTR) {
 			type = ctf_type_reference(ctfp, type);
-			type = ctf_type_resolve(ctfp, type);
+			type = dt_type_resolve(yypcb->pcb_hdl, &ctfp, type, 0);
 		}
 
-		if ((ctfp = dt_cg_membinfo(octfp = ctfp, type,
+		if ((ctfp = dt_cg_membinfo(octfp = dnp->dn_left->dn_ctfp, type,
 		    dnp->dn_right->dn_string, &m)) == NULL) {
 			yypcb->pcb_hdl->dt_ctferr = ctf_errno(octfp);
 			longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
diff --git a/libdtrace/dt_decl.c b/libdtrace/dt_decl.c
index 1f4936ddc15b..e299f423eae0 100644
--- a/libdtrace/dt_decl.c
+++ b/libdtrace/dt_decl.c
@@ -527,9 +527,10 @@ dt_decl_member(dt_node_t *dnp)
 		    "cannot have dynamic member: %s\n", ident);
 	}
 
-	base = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type);
-	kind = ctf_type_kind(dtt.dtt_ctfp, base);
-	size = ctf_type_size(dtt.dtt_ctfp, base);
+	ctf_file_t *fp = dtt.dtt_ctfp;
+	base = dt_type_resolve(yypcb->pcb_hdl, &fp, dtt.dtt_type, 0);
+	kind = ctf_type_kind(fp, base);
+	size = ctf_type_size(fp, base);
 
 	if (kind == CTF_K_FORWARD || ((kind == CTF_K_STRUCT ||
 	    kind == CTF_K_UNION) && size == 0)) {
@@ -567,8 +568,8 @@ dt_decl_member(dt_node_t *dnp)
 			    "expression expected as bit-field size\n");
 		}
 
-		if (ctf_type_kind(dtt.dtt_ctfp, base) != CTF_K_INTEGER ||
-		    ctf_type_encoding(dtt.dtt_ctfp, base, &cte) == CTF_ERR ||
+		if (ctf_type_kind(fp, base) != CTF_K_INTEGER ||
+		    ctf_type_encoding(fp, base, &cte) == CTF_ERR ||
 		    IS_VOID(cte)) {
 			xyerror(D_DECL_BFTYPE, "invalid type for "
 			    "bit-field: %s\n", idname);
@@ -790,6 +791,10 @@ dt_decl_enumerator(char *s, dt_node_t *dnp)
  * the underlying type names is handled by dt_type_lookup().  We build up the
  * name from the specified string and prefixes and then lookup the type.  If
  * we fail, an errmsg is saved and the caller must abort with EDT_COMPILER.
+ *
+ * Pointers to forwards in the C and D dictionaries are not chased down in the
+ * original dicts, because they will likely have been added by dt_decl_type
+ * itself, and cannot be the result of the link-time deduplicator.
  */
 int
 dt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip)
@@ -852,7 +857,7 @@ dt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip)
 		}
 
 		if ((rv = dt_decl_type(ddp->dd_next, tip)) == 0 &&
-		    (rv = dt_type_pointer(tip)) != 0) {
+		    (rv = dt_type_pointer(tip, 1)) != 0) {
 			xywarn(D_UNKNOWN, "cannot find type: %s*: %s\n",
 			    dt_type_name(tip->dtt_ctfp, tip->dtt_type,
 			    n, sizeof(n)), ctf_errmsg(dtp->dt_ctferr));
@@ -1015,6 +1020,7 @@ dt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip)
 	}
 
 	if (type == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) {
+		dt_dprintf ("can't update dict for module %s\n", dmp->dm_name);
 		xywarn(D_UNKNOWN, "failed to add forward tag for %s: %s\n",
 		    name, ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
 		return -1;
diff --git a/libdtrace/dt_ident.c b/libdtrace/dt_ident.c
index d4a6e2a1711e..db49e134d5c0 100644
--- a/libdtrace/dt_ident.c
+++ b/libdtrace/dt_ident.c
@@ -552,7 +552,13 @@ dt_iddtor_difo(dt_ident_t *idp)
 static size_t
 dt_idsize_type(dt_ident_t *idp)
 {
-	return ctf_type_size(idp->di_ctfp, idp->di_type);
+	ctf_file_t *fp = idp->di_ctfp;
+	ctf_id_t type;
+
+	type = dt_type_resolve(yypcb->pcb_hdl, &fp, idp->di_type, 0);
+	if (type == CTF_ERR)
+		return type;
+	return ctf_type_size(fp, type);
 }
 
 /*ARGSUSED*/
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index fb8cc0447a6c..812d5d745f9b 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -489,6 +489,10 @@ struct dtrace_hdl {
 #define	DT_USYMADDR_CTFP(dtp)	((dtp)->dt_ddefs->dm_ctfp)
 #define	DT_USYMADDR_TYPE(dtp)	((dtp)->dt_type_usymaddr)
 
+#define DT_RESOLVE_CD_FORWARDS_OK 0x0001
+
+ctf_id_t dt_type_resolve(dtrace_hdl_t *, ctf_file_t **, ctf_id_t, int);
+
 /*
  * Actions and subroutines are both DT_NODE_FUNC nodes; to avoid confusing
  * an action for a subroutine (or vice versa), we assure that the DT_ACT_*
@@ -799,6 +803,8 @@ extern dt_lib_depend_t *dt_lib_depend_lookup(dt_list_t *, const char *);
 
 extern int dt_variable_read(caddr_t, size_t, uint64_t *);
 
+extern ctf_id_t dtrace_type_resolve(dtrace_hdl_t *, ctf_file_t *, ctf_id_t);
+
 extern dt_pcb_t *yypcb;		/* pointer to current parser control block */
 extern char yyintprefix;	/* int token prefix for macros (+/-) */
 extern char yyintsuffix[4];	/* int token suffix ([uUlL]*) */
diff --git a/libdtrace/dt_module.c b/libdtrace/dt_module.c
index aaf125b85701..2fd3dfa4ad42 100644
--- a/libdtrace/dt_module.c
+++ b/libdtrace/dt_module.c
@@ -1529,8 +1529,12 @@ dtrace_lookup_by_name(dtrace_hdl_t *dtp, const char *object, const char *name,
 				symp->st_other = 0;
 				symp->st_shndx = SHN_UNDEF;
 				symp->st_value = 0;
-				symp->st_size =
-				    ctf_type_size(idp->di_ctfp, idp->di_type);
+                                if (ctf_type_size (idp->di_ctfp,
+                                        idp->di_type) >= 0)
+                                        symp->st_size =
+                                            ctf_type_size(idp->di_ctfp, idp->di_type);
+                                else
+                                        symp->st_size = 0;
 			}
 
 			if (sip != NULL) {
@@ -1718,6 +1722,127 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
 	return 0;
 }
 
+/*
+ * Resolve a type, searching for a corresponding non-forward if a forward is
+ * found in the shared dict, or (unless suppressed via the
+ * DT_RESOLVE_CD_FORWARDS_OK flag) in the C or D dicts, from which it may have
+ * been copied from the shared dict via direct use in a D definition or a
+ * translator.
+ *
+ * This function wraps ctf_type_resolve and is treated just like it by callers,
+ * so it must not affect the DTrace error state except in utterly catastrophic
+ * cases like OOM.
+ */
+ctf_id_t
+dt_type_resolve(dtrace_hdl_t *dtp, ctf_file_t **fp, ctf_id_t type, int flags)
+{
+	dt_module_t *dmp = dt_list_next(&dtp->dt_modlist);
+	ctf_id_t forwarded_type = -1;
+	ssize_t namelen = 255;
+	char *name;
+	int err = 0;
+	int old_errno = dtp->dt_errno;
+	ctf_id_t oldtype = type;
+
+	/*
+	 * Getting a name in a libdtrace-ctf-compatible way is horribly
+	 * inconvenient.  DTrace v2 should use ctf_type_aname.
+	 */
+	if ((name = malloc(namelen)) == 0)
+		return (dt_set_errno(dtp, EDT_NOMEM));
+
+	if ((type = ctf_type_resolve(*fp, type)) == CTF_ERR ||
+	    ctf_type_kind(*fp, type) != CTF_K_FORWARD ||
+	    (*fp != dtp->dt_shared_ctf &&
+		((flags & DT_RESOLVE_CD_FORWARDS_OK) ||
+		    (*fp != dtp->dt_cdefs->dm_ctfp &&
+			*fp != dtp->dt_ddefs->dm_ctfp))))
+	{
+		dt_dprintf("dt_type_resolve: error %s, type kind %i: "
+		    "resolved %lx to %lx\n", (type == CTF_ERR ?
+			ctf_errmsg (ctf_errno (*fp)) : "(no error)"),
+		    ctf_type_kind (*fp, type), oldtype, type);
+		goto ret;
+	}
+
+	namelen = ctf_type_lname(*fp, type, name, namelen) + 1;
+
+	if (namelen > 255) {
+		char *newname;
+		if ((newname = realloc(name, namelen)) == NULL) {
+			free(name);
+			return (dt_set_errno(dtp, EDT_NOMEM));
+		}
+		name = newname;
+		ctf_type_lname(*fp, type, name, namelen);
+	}
+
+	dt_dprintf("dt_type_resolve: %s is a forward in the shared dict, "
+	    "hunting in sub-dictionaries\n", name);
+
+	/*
+	 * Forward in the shared dict or a translator.  Search modules for a
+	 * corresponding concrete type.  Any error terminates the check.
+	 * CTF_NOTYPE is impossible if this type is in the shared dict; if it is
+	 * *not* in the shared dict but was copied into the C or D dict from a
+	 * child dict, this cannot be a dedup-introduced ambiguous forward and
+	 * thus is not something we need to hunt for: so if we get a ECTF_NOTYPE
+	 * at any stage, return the original type unchanged, since the forward
+	 * is really the right thing to return.
+	 */
+	do {
+		if (dt_module_getctf(dtp, dmp) == NULL)
+			continue;
+
+		/*
+		 * We are only interested in searching the modules: i.e., the
+		 * shared dict, and dicts which have the shared dict as a
+		 * parent.
+		 */
+		if (dmp->dm_ctfp != dtp->dt_shared_ctf &&
+		    ctf_parent_file (dmp->dm_ctfp) != dtp->dt_shared_ctf)
+			continue;
+
+		forwarded_type = ctf_lookup_by_name(dmp->dm_ctfp, name);
+		if (forwarded_type == -1)
+			err = ctf_errno (dmp->dm_ctfp);
+
+		/*
+		 * Errors, or a successfully-found non-forward, terminate the
+		 * search.
+		 */
+		if (forwarded_type == -1 ||
+		    ctf_type_kind(dmp->dm_ctfp, forwarded_type) != CTF_K_FORWARD)
+		{
+			dt_dprintf ("Found real type, of kind %i in %s\n",
+			    ctf_type_kind (dmp->dm_ctfp, forwarded_type),
+			    dmp->dm_name);
+			break;
+		}
+	} while ((dmp = dt_list_next (dmp)) != NULL);
+
+	if (forwarded_type != -1 && dmp &&
+	    ctf_type_kind(dmp->dm_ctfp, forwarded_type) != CTF_K_FORWARD)
+	{
+		*fp = dmp->dm_ctfp;
+		type = forwarded_type;
+		goto ret;
+	}
+	/*
+	 * Pass back errors other than ECTF_NOTYPE untouched in the ctfp state;
+	 * otherwise, return the original type.
+	 */
+	if (err != 0 && err != ECTF_NOTYPE)
+	{
+		type = -1;
+		goto ret;
+	}
+
+ret:
+	dtp->dt_errno = old_errno;
+	return type;
+}
+
 int
 dtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp,
     const dtrace_syminfo_t *sip, dtrace_typeinfo_t *tip)
diff --git a/libdtrace/dt_parser.c b/libdtrace/dt_parser.c
index c2cfc511d241..e872f9a20433 100644
--- a/libdtrace/dt_parser.c
+++ b/libdtrace/dt_parser.c
@@ -225,24 +225,39 @@ dt_type_lookup(const char *s, dtrace_typeinfo_t *tip)
  * for the compiler that attempts to compute a pointer to either the given type
  * or its base (that is, we try both "foo_t *" and "struct foo *"), and also
  * to potentially construct the required type on-the-fly.
+ *
+ * If ACCEPT_CDEFS is set, return pointers to forwards in the C and D dicts
+ * rather than hunting for them elsewhere.
+ *
+ * TODO: rewrite in v2, when we can guarantee the pptrtab machinery
+ *       (binutils 2.36+).  Doing ctf_add_type on probably read-only
+ *       containers like this is basically not ever going to work right
+ *       and never did.
  */
 int
-dt_type_pointer(dtrace_typeinfo_t *tip)
+dt_type_pointer(dtrace_typeinfo_t *tip, int accept_cdefs)
 {
 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
 	ctf_file_t *ctfp = tip->dtt_ctfp;
 	ctf_id_t type = tip->dtt_type;
-	ctf_id_t base = ctf_type_resolve(ctfp, type);
+	ctf_file_t *basep = ctfp;
+	ctf_id_t base = dt_type_resolve(dtp, &basep, type,
+	    accept_cdefs ? DT_RESOLVE_CD_FORWARDS_OK : 0);
 
 	dt_module_t *dmp;
 	ctf_id_t ptr;
 
-	if ((ptr = ctf_type_pointer(ctfp, type)) != CTF_ERR ||
-	    (ptr = ctf_type_pointer(ctfp, base)) != CTF_ERR) {
+	if ((ptr = ctf_type_pointer(ctfp, type)) != CTF_ERR) {
 		tip->dtt_type = ptr;
 		return 0;
 	}
 
+	if ((ptr = ctf_type_pointer(basep, base)) != CTF_ERR) {
+		tip->dtt_type = ptr;
+		tip->dtt_ctfp = basep;
+		return (0);
+	}
+
 	if (yypcb->pcb_idepth != 0)
 		dmp = dtp->dt_cdefs;
 	else
@@ -294,6 +309,12 @@ dt_type_basetype(ctf_file_t *fp, ctf_id_t type)
 	ctf_id_t newtype;
 	uint_t kind;
 
+	/* We don't need to use dt_type_resolve here, and deal with the
+	 * complexities of the fp changing, because dt_type_resolve
+	 * differs from ctf_type_resolve only when peering through forwards,
+	 * and you can't have a forward to any sliceable type (nor are
+	 * sliceable types replaced with forwards when deduplicating).
+	 */
 	type = ctf_type_resolve(fp, type);
 	kind = ctf_type_kind(fp, type);
 
@@ -335,6 +356,9 @@ dt_type_promote(dt_node_t *lp, dt_node_t *rp, ctf_file_t **ofp, ctf_id_t *otype)
 	ctf_id_t rbasetype = dt_node_basetype(rp);
 	uint_t rkind = ctf_type_kind(rfp, rbasetype);
 
+	/*
+	 * Arithmetic types cannot be forwards: no need to use dt_type_resolve.
+	 */
 	ctf_id_t lbase = ctf_type_resolve(lfp, ltype);
 	ctf_id_t rbase = ctf_type_resolve(rfp, rtype);
 
@@ -670,6 +694,10 @@ dt_node_attr_assign(dt_node_t *dnp, dtrace_attribute_t attr)
 void
 dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
 {
+	/*
+	 * No need to use dt_type_resolve here: structs, unions
+	 * and forwards are treated identically.
+	 */
 	ctf_id_t base = ctf_type_resolve(fp, type);
 	ctf_id_t basetype = dt_type_basetype(fp, base);
 	uint_t kind = ctf_type_kind(fp, basetype);
@@ -743,7 +771,17 @@ dt_node_type_size(const dt_node_t *dnp)
 	if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL)
 		return dt_ident_size(dnp->dn_ident);
 
-	return ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
+	/*
+	 * libctf may be unhelpful here.  Ambiguous types have no size that we
+	 * can determine (because their size may vary depending on what child
+	 * dict this is viewed through): this is represented as zero, not what
+	 * libctf returns (-1 and an error of ECTF_INCOMPLETE).  (It can also
+	 * return other errors: we treat all of these as unknown size, too.)
+	 */
+	if (ctf_type_size(dnp->dn_ctfp, dnp->dn_type) >= 0)
+		return ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
+	else
+		return 0;
 }
 
 /*
@@ -814,6 +852,10 @@ dt_node_is_integer(const dt_node_t *dnp)
 
 	assert(dnp->dn_flags & DT_NF_COOKED);
 
+	/*
+	 * No need to use dt_type_resolve here: integral types cannot be
+	 * replaced with forwards when deduplicating.
+	 */
 	type = ctf_type_resolve(fp, dnp->dn_type);
 	basetype = dt_node_basetype(dnp);
 	kind = ctf_type_kind(fp, basetype);
@@ -835,6 +877,10 @@ dt_node_is_float(const dt_node_t *dnp)
 
 	assert(dnp->dn_flags & DT_NF_COOKED);
 
+	/*
+	 * No need to use dt_type_resolve here: float types cannot be
+	 * replaced with forwards when deduplicating.
+	 */
 	type = ctf_type_resolve(fp, dnp->dn_type);
 	basetype = dt_node_basetype(dnp);
 	kind = ctf_type_kind(fp, basetype);
@@ -855,7 +901,7 @@ dt_node_is_scalar(const dt_node_t *dnp)
 
 	assert(dnp->dn_flags & DT_NF_COOKED);
 
-	type = ctf_type_resolve(fp, dnp->dn_type);
+	type = dt_type_resolve(yypcb->pcb_hdl, &fp, dnp->dn_type, 0);
 	basetype = dt_node_basetype(dnp);
 	kind = ctf_type_kind(fp, basetype);
 
@@ -877,7 +923,7 @@ dt_node_is_arith(const dt_node_t *dnp)
 
 	assert(dnp->dn_flags & DT_NF_COOKED);
 
-	type = ctf_type_resolve(fp, dnp->dn_type);
+	type = dt_type_resolve(yypcb->pcb_hdl, &fp, dnp->dn_type, 0);
 	basetype = dt_node_basetype(dnp);
 	kind = ctf_type_kind(fp, basetype);
 
@@ -897,11 +943,12 @@ dt_node_is_vfptr(const dt_node_t *dnp)
 
 	assert(dnp->dn_flags & DT_NF_COOKED);
 
-	type = ctf_type_resolve(fp, dnp->dn_type);
+	type = dt_type_resolve(yypcb->pcb_hdl, &fp, dnp->dn_type, 0);
 	if (ctf_type_kind(fp, type) != CTF_K_POINTER)
 		return 0; /* type is not a pointer */
 
-	type = ctf_type_resolve(fp, ctf_type_reference(fp, type));
+	type = dt_type_resolve(yypcb->pcb_hdl, &fp,
+			       ctf_type_reference(fp, type), 0);
 	basetype = dt_type_basetype(fp, type);
 	kind = ctf_type_kind(fp, basetype);
 
@@ -961,17 +1008,18 @@ dt_node_is_strcompat(const dt_node_t *dnp)
 
 	assert(dnp->dn_flags & DT_NF_COOKED);
 
-	base = ctf_type_resolve(fp, dnp->dn_type);
+	base = dt_type_resolve(yypcb->pcb_hdl, &fp, dnp->dn_type, 0);
 	kind = ctf_type_kind(fp, base);
 
 	if (kind == CTF_K_POINTER &&
 	    (base = ctf_type_reference(fp, base)) != CTF_ERR &&
-	    (base = ctf_type_resolve(fp, base)) != CTF_ERR &&
+	    (base = dt_type_resolve(yypcb->pcb_hdl, &fp, base, 0)) != CTF_ERR &&
 	    ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e))
 		return 1; /* promote char pointer to string */
 
 	if (kind == CTF_K_ARRAY && ctf_array_info(fp, base, &r) == 0 &&
-	    (base = ctf_type_resolve(fp, r.ctr_contents)) != CTF_ERR &&
+	    (base = dt_type_resolve(yypcb->pcb_hdl, &fp,
+				    r.ctr_contents, 0)) != CTF_ERR &&
 	    ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e))
 		return 1; /* promote char array to string */
 
@@ -982,6 +1030,7 @@ int
 dt_node_is_pointer(const dt_node_t *dnp)
 {
 	ctf_file_t *fp = dnp->dn_ctfp;
+	ctf_id_t type;
 	uint_t kind;
 
 	assert(dnp->dn_flags & DT_NF_COOKED);
@@ -989,7 +1038,8 @@ dt_node_is_pointer(const dt_node_t *dnp)
 	if (dt_node_is_string(dnp))
 		return 0; /* string are pass-by-ref but act like structs */
 
-	kind = ctf_type_kind(fp, ctf_type_resolve(fp, dnp->dn_type));
+	type = dt_type_resolve(yypcb->pcb_hdl, &fp, dnp->dn_type, 0);
+	kind = ctf_type_kind(fp, type);
 	return kind == CTF_K_POINTER || kind == CTF_K_ARRAY;
 }
 
@@ -1009,7 +1059,10 @@ dt_node_is_void(const dt_node_t *dnp)
 	if (dt_node_is_symaddr(dnp) || dt_node_is_usymaddr(dnp))
 		return 0;
 
-	type = ctf_type_resolve(fp, dnp->dn_type);
+	if (dnp->dn_type == CTF_ERR)
+		return (0);
+
+	type = dt_type_resolve(yypcb->pcb_hdl, &fp, dnp->dn_type, 0);
 	basetype = dt_node_basetype(dnp);
 
 	return ctf_type_kind(fp, basetype) == CTF_K_INTEGER &&
@@ -1020,8 +1073,12 @@ int
 dt_node_is_ptrcompat(const dt_node_t *lp, const dt_node_t *rp,
     ctf_file_t **fpp, ctf_id_t *tp)
 {
+	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
+
 	ctf_file_t *lfp = lp->dn_ctfp;
 	ctf_file_t *rfp = rp->dn_ctfp;
+	ctf_file_t *lreffp = lp->dn_ctfp;
+	ctf_file_t *rreffp = rp->dn_ctfp;
 
 	ctf_id_t lbase = CTF_ERR, rbase = CTF_ERR;
 	ctf_id_t lref = CTF_ERR, rref = CTF_ERR;
@@ -1060,28 +1117,30 @@ dt_node_is_ptrcompat(const dt_node_t *lp, const dt_node_t *rp,
 	 * is CTF_K_POINTER or CTF_K_ARRAY).  Otherwise [lr]ref = CTF_ERR.
 	 */
 	if (!lp_is_int) {
-		lbase = ctf_type_resolve(lfp, lp->dn_type);
+		lbase = dt_type_resolve(dtp, &lfp, lp->dn_type, 0);
 		lkind = ctf_type_kind(lfp, lbase);
+		lreffp = lfp;
 
 		if (lkind == CTF_K_POINTER) {
-			lref = ctf_type_resolve(lfp,
-			    ctf_type_reference(lfp, lbase));
+			lref = dt_type_resolve(dtp, &lreffp,
+			    ctf_type_reference(lreffp, lbase), 0);
 		} else if (lkind == CTF_K_ARRAY &&
 		    ctf_array_info(lfp, lbase, &r) == 0) {
-			lref = ctf_type_resolve(lfp, r.ctr_contents);
+			lref = dt_type_resolve(dtp, &lreffp, r.ctr_contents, 0);
 		}
 	}
 
 	if (!rp_is_int) {
-		rbase = ctf_type_resolve(rfp, rp->dn_type);
+		rbase = dt_type_resolve(dtp, &rfp, rp->dn_type, 0);
 		rkind = ctf_type_kind(rfp, rbase);
+		rreffp = rfp;
 
 		if (rkind == CTF_K_POINTER) {
-			rref = ctf_type_resolve(rfp,
-			    ctf_type_reference(rfp, rbase));
+			rref = dt_type_resolve(dtp, &rreffp,
+			    ctf_type_reference(rreffp, rbase), 0);
 		} else if (rkind == CTF_K_ARRAY &&
 		    ctf_array_info(rfp, rbase, &r) == 0) {
-			rref = ctf_type_resolve(rfp, r.ctr_contents);
+			rref = dt_type_resolve(dtp, &rreffp, r.ctr_contents, 0);
 		}
 	}
 
@@ -1095,15 +1154,17 @@ dt_node_is_ptrcompat(const dt_node_t *lp, const dt_node_t *rp,
 		lkind = rkind;
 		lref = rref;
 		lfp = rfp;
+		lreffp = rreffp;
 	} else if (rp_is_int) {
 		rbase = lbase;
 		rkind = lkind;
 		rref = lref;
 		rfp = lfp;
+		rreffp = lreffp;
 	}
 
-	lp_is_void = ctf_type_encoding(lfp, lref, &e) == 0 && IS_VOID(e);
-	rp_is_void = ctf_type_encoding(rfp, rref, &e) == 0 && IS_VOID(e);
+	lp_is_void = ctf_type_encoding(lreffp, lref, &e) == 0 && IS_VOID(e);
+	rp_is_void = ctf_type_encoding(rreffp, rref, &e) == 0 && IS_VOID(e);
 
 	/*
 	 * The types are compatible if both are pointers to the same type, or
@@ -1112,7 +1173,7 @@ dt_node_is_ptrcompat(const dt_node_t *lp, const dt_node_t *rp,
 	 */
 	compat = (lkind == CTF_K_POINTER || lkind == CTF_K_ARRAY) &&
 	    (rkind == CTF_K_POINTER || rkind == CTF_K_ARRAY) &&
-	    (lp_is_void || rp_is_void || ctf_type_compat(lfp, lref, rfp, rref));
+	    (lp_is_void || rp_is_void || ctf_type_compat(lreffp, lref, rreffp, rref));
 
 	if (compat) {
 		if (fpp != NULL)
@@ -1153,11 +1214,14 @@ dt_node_is_argcompat(const dt_node_t *lp, const dt_node_t *rp)
 	if (dt_node_is_usymaddr(lp) && dt_node_is_usymaddr(rp))
 		return 1; /* usymaddr types are compatible */
 
-	switch (ctf_type_kind(lfp, ctf_type_resolve(lfp, lp->dn_type))) {
+	ctf_id_t ltype = dt_type_resolve(yypcb->pcb_hdl, &lfp, lp->dn_type, 0);
+	ctf_id_t rtype = dt_type_resolve(yypcb->pcb_hdl, &rfp, rp->dn_type, 0);
+
+	switch (ctf_type_kind(lfp, ltype)) {
 	case CTF_K_FUNCTION:
 	case CTF_K_STRUCT:
 	case CTF_K_UNION:
-		return ctf_type_compat(lfp, lp->dn_type, rfp, rp->dn_type);
+		return ctf_type_compat(lfp, ltype, rfp, rtype);
 	default:
 		return dt_node_is_ptrcompat(lp, rp, NULL, NULL);
 	}
@@ -1411,8 +1475,9 @@ dt_node_decl(void)
 		    ddp->dd_kind != CTF_K_UNION && ddp->dd_kind != CTF_K_ENUM)
 			xyerror(D_DECL_USELESS, "useless declaration\n");
 
-		dt_dprintf("type %s added as id %ld\n", dt_type_name(
-		    ddp->dd_ctfp, ddp->dd_type, n1, sizeof(n1)), ddp->dd_type);
+		dt_dprintf("type %s, kind %i, added as id %ld\n", dt_type_name(
+		    ddp->dd_ctfp, ddp->dd_type, n1, sizeof (n1)),
+		    ddp->dd_kind, ddp->dd_type);
 
 		return NULL;
 	}
@@ -1519,7 +1584,8 @@ dt_node_decl(void)
 			    dsp->ds_ident, ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
 		}
 
-		dt_dprintf("typedef %s added as id %ld\n", dsp->ds_ident, type);
+		dt_dprintf("typedef %s added to %p as id %lx\n", dsp->ds_ident,
+		    (void *) dmp->dm_ctfp, type);
 		break;
 
 	default: {
@@ -1665,7 +1731,7 @@ dt_node_decl(void)
 			uint_t alignment = 8;
 			uint_t size;
 
-			type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type);
+			type = dt_type_resolve(dtp, &dtt.dtt_ctfp, dtt.dtt_type, 0);
 			basetype = dt_type_basetype(dtt.dtt_ctfp, dtt.dtt_type);
 			kind = ctf_type_kind(dtt.dtt_ctfp, basetype);
 			size = ctf_type_size(dtt.dtt_ctfp, dtt.dtt_type);
@@ -1697,8 +1763,8 @@ dt_node_decl(void)
 				if (ctf_array_info(dtt.dtt_ctfp, dtt.dtt_type,
 						   &r) != 0)
 					break;
-				etype = ctf_type_resolve(dtt.dtt_ctfp,
-							 r.ctr_contents);
+				etype = dt_type_resolve(dtp, &dtt.dtt_ctfp,
+							r.ctr_contents, 0);
 				if (etype == CTF_ERR)
 					break;
 
@@ -1825,7 +1891,7 @@ dt_node_offsetof(dt_decl_t *ddp, char *s)
 	if (err != 0)
 		longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
 
-	type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type);
+	type = dt_type_resolve(yypcb->pcb_hdl, &dtt.dtt_ctfp, dtt.dtt_type, 0);
 	kind = ctf_type_kind(dtt.dtt_ctfp, type);
 
 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) {
@@ -2281,8 +2347,11 @@ dt_node_inline(dt_node_t *expr)
 		    "cannot declare void inline: %s\n", dsp->ds_ident);
 	}
 
-	if (ctf_type_kind(dnp->dn_ctfp, ctf_type_resolve(
-	    dnp->dn_ctfp, dnp->dn_type)) == CTF_K_FORWARD) {
+	ctf_id_t resolved = dt_type_resolve(dtp, &dnp->dn_ctfp, dnp->dn_type, 0);
+	if (resolved != CTF_ERR)
+		dnp->dn_type = resolved;
+
+	if (ctf_type_kind(dnp->dn_ctfp, resolved) == CTF_K_FORWARD) {
 		xyerror(D_DECL_INCOMPLETE,
 		    "incomplete struct/union/enum %s: %s\n",
 		    dt_node_type_name(dnp, n, sizeof(n)), dsp->ds_ident);
@@ -2438,6 +2507,7 @@ dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members)
 {
 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
 	dtrace_typeinfo_t src, dst;
+	ctf_id_t resolved;
 	dt_node_t sn, dn;
 	dt_xlator_t *dxp;
 	dt_node_t *dnp;
@@ -2471,8 +2541,11 @@ dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members)
 		    dt_node_type_name(&dn, n2, sizeof(n2)));
 	}
 
-	kind = ctf_type_kind(dst.dtt_ctfp,
-	    ctf_type_resolve(dst.dtt_ctfp, dst.dtt_type));
+
+	resolved = dt_type_resolve(dtp, &dst.dtt_ctfp, dst.dtt_type, 0);
+	if (resolved != CTF_ERR)
+		dst.dtt_type = resolved;
+	kind = ctf_type_kind(dst.dtt_ctfp, dst.dtt_type);
 
 	if (kind == CTF_K_FORWARD) {
 		xyerror(D_XLATE_SOU, "incomplete struct/union/enum %s\n",
@@ -2917,6 +2990,7 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
 
 	ctf_encoding_t e;
 	ctf_arinfo_t r;
+	ctf_file_t *basefp;
 	ctf_id_t type, base, basetype;
 	uint_t kind;
 
@@ -2966,7 +3040,7 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
 			break;
 		}
 
-		type = ctf_type_resolve(cp->dn_ctfp, cp->dn_type);
+		type = dt_type_resolve(dtp, &cp->dn_ctfp, cp->dn_type, 0);
 		kind = ctf_type_kind(cp->dn_ctfp, type);
 
 		if (kind == CTF_K_ARRAY) {
@@ -2983,8 +3057,9 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
 		}
 
 		dt_node_type_assign(dnp, cp->dn_ctfp, type);
-		base = ctf_type_resolve(cp->dn_ctfp, type);
-		basetype = dt_type_basetype (cp->dn_ctfp, type);
+		basefp = cp->dn_ctfp;
+		base = dt_type_resolve(dtp, &basefp, type, 0);
+		basetype = dt_type_basetype(basefp, type);
 		kind = ctf_type_kind(cp->dn_ctfp, basetype);
 
 		if (kind == CTF_K_INTEGER && ctf_type_encoding(cp->dn_ctfp,
@@ -3068,7 +3143,7 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
 		dtt.dtt_ctfp = cp->dn_ctfp;
 		dtt.dtt_type = cp->dn_type;
 
-		if (dt_type_pointer(&dtt) == -1) {
+		if (dt_type_pointer(&dtt, 0) == -1) {
 			xyerror(D_TYPE_ERR, "cannot find type for \"&\": %s*\n",
 			    dt_node_type_name(cp, n, sizeof(n)));
 		}
@@ -3149,7 +3224,7 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
 
 	ctf_membinfo_t m;
 	ctf_file_t *ctfp;
-	ctf_id_t type;
+	ctf_id_t type, resolved;
 	int kind, val, uref;
 	dt_ident_t *idp;
 
@@ -3289,8 +3364,11 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
 		 */
 		lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);
 
-		kind = ctf_type_kind(lp->dn_ctfp,
-		    ctf_type_resolve(lp->dn_ctfp, lp->dn_type));
+		resolved = dt_type_resolve(dtp, &lp->dn_ctfp, lp->dn_type, 0);
+		if (resolved != CTF_ERR)
+			lp->dn_type = resolved;
+
+		kind = ctf_type_kind(lp->dn_ctfp, lp->dn_type);
 
 		if (kind == CTF_K_ENUM && rp->dn_kind == DT_NODE_IDENT &&
 		    strchr(rp->dn_string, '`') == NULL && ctf_enum_value(
@@ -3360,6 +3438,7 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
 		int lp_is_ptr, lp_is_int, rp_is_ptr, rp_is_int;
 
 		ctf_arinfo_t r;
+		ctf_file_t *arfp;
 		ctf_id_t artype;
 		int arkind;
 
@@ -3400,13 +3479,14 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
 		 * Array bounds-checking.  (Non-associative arrays only.)
 		 */
 
-		artype = ctf_type_resolve(lp->dn_ctfp, lp->dn_type);
-		arkind = ctf_type_kind(lp->dn_ctfp, artype);
+		arfp = lp->dn_ctfp;
+		artype = dt_type_resolve(dtp, &arfp, lp->dn_type, 0);
+		arkind = ctf_type_kind(arfp, artype);
 
 		if (arkind == CTF_K_ARRAY &&
 		    !(lp->dn_kind == DT_NODE_VAR &&
 			lp->dn_ident->di_kind == DT_IDENT_ARRAY)) {
-			ctf_array_info(lp->dn_ctfp, artype, &r);
+			ctf_array_info(arfp, artype, &r);
 
 			if (rp->dn_kind == DT_NODE_INT &&
 			    ctf_array_info(lp->dn_ctfp, type, &r) == 0 &&
@@ -3589,8 +3669,11 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
 		 * most of this code with the argument list checking code.
 		 */
 		if (!dt_node_is_string(lp)) {
-			kind = ctf_type_kind(lp->dn_ctfp,
-			    ctf_type_resolve(lp->dn_ctfp, lp->dn_type));
+			ctf_file_t *tmp = lp->dn_ctfp;
+			ctf_id_t resolved;
+
+			resolved = dt_type_resolve(dtp, &tmp, lp->dn_type, 0);
+			kind = ctf_type_kind(tmp, resolved);
 
 			if (kind == CTF_K_ARRAY || kind == CTF_K_FUNCTION) {
 				xyerror(D_OP_ARRFUN, "operator %s may not be "
@@ -3733,11 +3816,11 @@ asgn_common:
 			}
 
 			ctfp = idp->di_ctfp;
-			type = ctf_type_resolve(ctfp, idp->di_type);
+			type = dt_type_resolve(dtp, &ctfp, idp->di_type, 0);
 			uref = idp->di_flags & DT_IDFLG_USER;
 		} else {
 			ctfp = lp->dn_ctfp;
-			type = ctf_type_resolve(ctfp, lp->dn_type);
+			type = dt_type_resolve(dtp, &ctfp, lp->dn_type, 0);
 			uref = lp->dn_flags & DT_NF_USERLAND;
 		}
 
@@ -3749,7 +3832,7 @@ asgn_common:
 				    "applied to a pointer\n", opstr(op));
 			}
 			type = ctf_type_reference(ctfp, type);
-			type = ctf_type_resolve(ctfp, type);
+			type = dt_type_resolve(dtp, &ctfp, type, 0);
 			kind = ctf_type_kind(ctfp, type);
 		}
 
@@ -3764,7 +3847,7 @@ asgn_common:
 			if (tag != NULL && dt_type_lookup(tag, &dtt) == 0 &&
 			    (dtt.dtt_ctfp != ctfp || dtt.dtt_type != type)) {
 				ctfp = dtt.dtt_ctfp;
-				type = ctf_type_resolve(ctfp, dtt.dtt_type);
+				type = dt_type_resolve(dtp, &ctfp, dtt.dtt_type, 0);
 				kind = ctf_type_kind(ctfp, type);
 			} else {
 				xyerror(D_OP_INCOMPLETE,
@@ -3792,8 +3875,9 @@ asgn_common:
 			    "%s is not a member of %s\n", rp->dn_string,
 			    ctf_type_name(ctfp, type, n1, sizeof(n1)));
 
-		type = ctf_type_resolve(ctfp, m.ctm_type);
-		kind = ctf_type_kind(ctfp, type);
+		ctf_file_t *tmp = ctfp;
+		type = dt_type_resolve(dtp, &tmp, m.ctm_type, 0);
+		kind = ctf_type_kind(tmp, type);
 
 		dt_node_type_assign(dnp, ctfp, m.ctm_type);
 		dt_node_attr_assign(dnp, lp->dn_attr);
@@ -3928,17 +4012,20 @@ asgn_common:
 	}
 
 	case DT_TOK_LPAR: {
+		ctf_file_t *lfp, *rfp;
 		ctf_id_t ltype, rtype;
 		uint_t lkind, rkind;
 
 		assert(lp->dn_kind == DT_NODE_TYPE);
 		rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);
 
-		ltype = ctf_type_resolve(lp->dn_ctfp, lp->dn_type);
-		lkind = ctf_type_kind(lp->dn_ctfp, ltype);
+		lfp = lp->dn_ctfp;
+		ltype = dt_type_resolve(dtp, &lfp, lp->dn_type, 0);
+		lkind = ctf_type_kind(lfp, ltype);
 
-		rtype = ctf_type_resolve(rp->dn_ctfp, rp->dn_type);
-		rkind = ctf_type_kind(rp->dn_ctfp, rtype);
+		rfp = rp->dn_ctfp;
+		rtype = dt_type_resolve(dtp, &rfp, rp->dn_type, 0);
+		rkind = ctf_type_kind(rfp, rtype);
 
 		/*
 		 * The rules for casting are loosely explained in K&R[A7.5]
@@ -4244,7 +4331,8 @@ dt_cook_inline(dt_node_t *dnp, uint_t idflags)
 	    (rdp = dt_node_resolve(inp->din_root, DT_IDENT_XLPTR)) != NULL) {
 
 		ctf_file_t *lctfp = dnp->dn_ctfp;
-		ctf_id_t ltype = ctf_type_resolve(lctfp, dnp->dn_type);
+		ctf_id_t ltype = dt_type_resolve(yypcb->pcb_hdl,
+		    &lctfp, dnp->dn_type, 0);
 
 		dt_xlator_t *dxp = rdp->di_data;
 		ctf_file_t *rctfp = dxp->dx_dst_ctfp;
@@ -4252,7 +4340,8 @@ dt_cook_inline(dt_node_t *dnp, uint_t idflags)
 
 		if (ctf_type_kind(lctfp, ltype) == CTF_K_POINTER) {
 			ltype = ctf_type_reference(lctfp, ltype);
-			ltype = ctf_type_resolve(lctfp, ltype);
+			ltype = dt_type_resolve(yypcb->pcb_hdl, &lctfp,
+						ltype, 0);
 		}
 
 		if (ctf_type_compat(lctfp, ltype, rctfp, rtype) == 0) {
@@ -4616,19 +4705,26 @@ dt_node_link(dt_node_t *lp, dt_node_t *rp)
 void
 dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp)
 {
-	if (dnp->dn_ctfp == DT_STR_CTFP(dtp) &&
-	    dnp->dn_type == DT_STR_TYPE(dtp)) {
+	ctf_file_t *fp = dnp->dn_ctfp;
+	ctf_id_t type = dnp->dn_type;
+
+	if (fp == DT_STR_CTFP(dtp) &&
+	    type == DT_STR_TYPE(dtp)) {
 		tp->dtdt_kind = DIF_TYPE_STRING;
 		tp->dtdt_ckind = CTF_K_UNKNOWN;
 	} else {
+		ctf_id_t tmp;
 		tp->dtdt_kind = DIF_TYPE_CTF;
-		tp->dtdt_ckind = ctf_type_kind(dnp->dn_ctfp,
-		    ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type));
+		tmp = dt_type_resolve(dtp, &fp, type, 0);
+		tp->dtdt_ckind = ctf_type_kind(fp, tmp);
 	}
 
 	tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ? DIF_TF_BYREF : 0;
 	tp->dtdt_pad = 0;
-	tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
+	if (ctf_type_kind(fp, type) != CTF_K_FORWARD)
+		tp->dtdt_size = ctf_type_size(fp, type);
+	else
+		tp->dtdt_size = 0;
 }
 
 void
diff --git a/libdtrace/dt_parser.h b/libdtrace/dt_parser.h
index 26e00aecf90f..70c5a9425790 100644
--- a/libdtrace/dt_parser.h
+++ b/libdtrace/dt_parser.h
@@ -238,7 +238,7 @@ struct dt_pcb;		/* see <dt_impl.h> */
 	((e).cte_offset == 0 && (e).cte_bits == 0)
 
 extern int dt_type_lookup(const char *, struct dtrace_typeinfo *);
-extern int dt_type_pointer(struct dtrace_typeinfo *);
+extern int dt_type_pointer(struct dtrace_typeinfo *, int);
 extern const char *dt_type_name(ctf_file_t *, ctf_id_t, char *, size_t);
 
 typedef enum {
diff --git a/libdtrace/dt_printf.c b/libdtrace/dt_printf.c
index 703c37b32807..9f7c78bf0518 100644
--- a/libdtrace/dt_printf.c
+++ b/libdtrace/dt_printf.c
@@ -79,11 +79,11 @@ pfcheck_str(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
 		return 1;
 
 	ctfp = dnp->dn_ctfp;
-	base = ctf_type_resolve(ctfp, dnp->dn_type);
+	base = dt_type_resolve(pfv->pfv_dtp, &ctfp, dnp->dn_type, 0);
 	kind = ctf_type_kind(ctfp, base);
 
 	return kind == CTF_K_ARRAY && ctf_array_info(ctfp, base, &r) == 0 &&
-	    (base = ctf_type_resolve(ctfp, r.ctr_contents)) != CTF_ERR &&
+	    (base = dt_type_resolve(pfv->pfv_dtp, &ctfp, r.ctr_contents, 0)) != CTF_ERR &&
 	    ctf_type_encoding(ctfp, base, &e) == 0 && IS_CHAR(e);
 }
 
@@ -92,14 +92,14 @@ static int
 pfcheck_wstr(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
 {
 	ctf_file_t *ctfp = dnp->dn_ctfp;
-	ctf_id_t base = ctf_type_resolve(ctfp, dnp->dn_type);
+	ctf_id_t base = dt_type_resolve(pfv->pfv_dtp, &ctfp, dnp->dn_type, 0);
 	uint_t kind = ctf_type_kind(ctfp, base);
 
 	ctf_encoding_t e;
 	ctf_arinfo_t r;
 
 	return kind == CTF_K_ARRAY && ctf_array_info(ctfp, base, &r) == 0 &&
-	    (base = ctf_type_resolve(ctfp, r.ctr_contents)) != CTF_ERR &&
+	    (base = dt_type_resolve(pfv->pfv_dtp, &ctfp, r.ctr_contents, 0)) != CTF_ERR &&
 	    ctf_type_kind(ctfp, base) == CTF_K_INTEGER &&
 	    ctf_type_encoding(ctfp, base, &e) == 0 && e.cte_bits == 32;
 }
@@ -143,7 +143,7 @@ static int
 pfcheck_xshort(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
 {
 	ctf_file_t *ctfp = dnp->dn_ctfp;
-	ctf_id_t type = ctf_type_resolve(ctfp, dnp->dn_type);
+	ctf_id_t type = dt_type_resolve(pfv->pfv_dtp, &ctfp, dnp->dn_type, 0);
 	char n[DT_TYPE_NAMELEN];
 
 	return ctf_type_name(ctfp, type, n, sizeof(n)) != NULL && (
@@ -156,7 +156,7 @@ static int
 pfcheck_xlong(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
 {
 	ctf_file_t *ctfp = dnp->dn_ctfp;
-	ctf_id_t type = ctf_type_resolve(ctfp, dnp->dn_type);
+	ctf_id_t type = dt_type_resolve(pfv->pfv_dtp, &ctfp, dnp->dn_type, 0);
 	char n[DT_TYPE_NAMELEN];
 
 	return ctf_type_name(ctfp, type, n, sizeof(n)) != NULL && (
@@ -199,8 +199,11 @@ pfcheck_xlonglong(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
 static int
 pfcheck_type(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
 {
-	return ctf_type_compat(dnp->dn_ctfp, ctf_type_resolve(dnp->dn_ctfp,
-	    dnp->dn_type), pfd->pfd_conv->pfc_dctfp, pfd->pfd_conv->pfc_dtype);
+	ctf_file_t *ctfp = dnp->dn_ctfp;
+	ctf_id_t type = dt_type_resolve(pfv->pfv_dtp, &ctfp, dnp->dn_type, 0);
+
+	return ctf_type_compat(ctfp, type, pfd->pfd_conv->pfc_dctfp,
+		pfd->pfd_conv->pfc_dtype);
 }
 
 /*ARGSUSED*/
diff --git a/libdtrace/dt_xlator.c b/libdtrace/dt_xlator.c
index f8d65ea35032..5d68216824c5 100644
--- a/libdtrace/dt_xlator.c
+++ b/libdtrace/dt_xlator.c
@@ -101,7 +101,7 @@ dt_xlator_create(dtrace_hdl_t *dtp,
 	dtp->dt_xlatormap = map;
 	dtp->dt_xlatormap[dxp->dx_id] = dxp;
 
-	if (dt_type_pointer(&ptr) == -1) {
+	if (dt_type_pointer(&ptr, 0) == -1) {
 		ptr.dtt_ctfp = NULL;
 		ptr.dtt_type = CTF_ERR;
 	}
@@ -164,14 +164,18 @@ dt_xlator_create(dtrace_hdl_t *dtp,
 	}
 
 	dxp->dx_src_ctfp = src->dtt_ctfp;
+	dxp->dx_src_base_ctfp = src->dtt_ctfp;
 	dxp->dx_src_type = src->dtt_type;
-	dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type);
+	dxp->dx_src_base = dt_type_resolve(dtp, &dxp->dx_src_base_ctfp,
+	    src->dtt_type, 0);
 
 	dxp->dx_dst_ctfp = dst->dtt_ctfp;
+	dxp->dx_dst_base_ctfp = dst->dtt_ctfp;
 	dxp->dx_dst_type = dst->dtt_type;
-	dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type);
+	dxp->dx_dst_base = dt_type_resolve(dtp, &dxp->dx_dst_base_ctfp,
+	    dst->dtt_type, 0);
 
-	kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base);
+	kind = ctf_type_kind(dxp->dx_dst_base_ctfp, dxp->dx_dst_base);
 	assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION);
 
 	/*
@@ -180,7 +184,7 @@ dt_xlator_create(dtrace_hdl_t *dtp,
 	 * retain the member and allocation node lists presented by the parser.
 	 */
 	if (name == NULL) {
-		if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base,
+		if (ctf_member_iter(dxp->dx_dst_base_ctfp, dxp->dx_dst_base,
 		    dt_xlator_create_member, dxp) != 0)
 			goto err;
 	} else {
@@ -240,6 +244,7 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
 
 	ctf_file_t *dst_ctfp = dst->dn_ctfp;
 	ctf_id_t dst_type = dst->dn_type;
+	ctf_file_t *dst_base_ctfp = dst->dn_ctfp;
 	ctf_id_t dst_base = ctf_type_resolve(dst_ctfp, dst_type);
 	uint_t dst_kind = ctf_type_kind(dst_ctfp, dst_base);
 
@@ -258,8 +263,8 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
 	 */
 	if (ptr) {
 		dst_type = ctf_type_reference(dst_ctfp, dst_type);
-		dst_base = ctf_type_resolve(dst_ctfp, dst_type);
-		dst_kind = ctf_type_kind(dst_ctfp, dst_base);
+		dst_base = dt_type_resolve(dtp, &dst_base_ctfp, dst_type, 0);
+		dst_kind = ctf_type_kind(dst_base_ctfp, dst_base);
 	}
 
 	if (dst_kind != CTF_K_UNION && dst_kind != CTF_K_STRUCT)
@@ -278,8 +283,8 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
 	    dxp = dt_list_next(dxp)) {
 		if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_type,
 		    src_ctfp, src_type) &&
-		    ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
-		    dst_ctfp, dst_base))
+		    ctf_type_compat(dxp->dx_dst_base_ctfp, dxp->dx_dst_base,
+		    dst_base_ctfp, dst_base))
 			goto out;
 	}
 
@@ -288,9 +293,9 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
 
 	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
 	    dxp = dt_list_next(dxp)) {
-		if (ctf_type_compat(dxp->dx_src_ctfp, dxp->dx_src_base,
+		if (ctf_type_compat(dxp->dx_src_base_ctfp, dxp->dx_src_base,
 		    src_ctfp, src_type) &&
-		    ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
+		    ctf_type_compat(dxp->dx_dst_base_ctfp, dxp->dx_dst_base,
 		    dst_ctfp, dst_base))
 			goto out;
 	}
@@ -298,8 +303,8 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
 	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
 	    dxp = dt_list_next(dxp)) {
 		dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type);
-		if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
-		    dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
+		if (ctf_type_compat(dxp->dx_dst_base_ctfp, dxp->dx_dst_base,
+		    dst_base_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
 			goto out;
 	}
 
diff --git a/libdtrace/dt_xlator.h b/libdtrace/dt_xlator.h
index f64cf0dab906..d2d2470871dd 100644
--- a/libdtrace/dt_xlator.h
+++ b/libdtrace/dt_xlator.h
@@ -26,8 +26,10 @@ typedef struct dt_xlator {
 	dt_ident_t dx_souid;		/* fake identifier for sou output */
 	dt_ident_t dx_ptrid;		/* fake identifier for ptr output */
 	ctf_file_t *dx_src_ctfp;	/* CTF container for input type */
+	ctf_file_t *dx_src_base_ctfp;	/* CTF container for input base type */
 	ctf_id_t dx_src_type;		/* CTF reference for input type */
 	ctf_id_t dx_src_base;		/* CTF reference for input base */
+	ctf_file_t *dx_dst_base_ctfp;	/* CTF container for output base type */
 	ctf_file_t *dx_dst_ctfp;	/* CTF container for output type */
 	ctf_id_t dx_dst_type;		/* CTF reference for output type */
 	ctf_id_t dx_dst_base;		/* CTF reference for output base */
-- 
2.33.0.256.gb827f06fa9




More information about the DTrace-devel mailing list