git: 246787fcb824 - releng/13.1 - fbt: Add support for CTFv3 containers

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 18 Apr 2022 16:39:28 UTC
The branch releng/13.1 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=246787fcb82463ba8c052994d8674e3cb7425d6a

commit 246787fcb82463ba8c052994d8674e3cb7425d6a
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-03-07 13:45:53 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-04-18 16:38:28 +0000

    fbt: Add support for CTFv3 containers
    
    The general aim in this and subsequent patches is to minimize the
    amount of code that directly references CTF types such as ctf_type_t,
    ctf_array_t, etc.  To that end, introduce some routines similar to the
    existing fbt_get_ctt_size() (which exists to deal with differences
    between v1 and v2) and change ctf_lookup_by_id() to return a void
    pointer.
    
    Support for v2 containers is preserved.
    
    Approved by:    re (gjb)
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit d9175438c0e77ef2b400601aa8cf8098c82a77a7)
    (cherry picked from commit 2ecf3b58ebdfd6452b8ce269943da362b40c2e63)
---
 sys/cddl/dev/fbt/fbt.c | 309 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 231 insertions(+), 78 deletions(-)

diff --git a/sys/cddl/dev/fbt/fbt.c b/sys/cddl/dev/fbt/fbt.c
index 5b1aeab3bafb..aee5376d5981 100644
--- a/sys/cddl/dev/fbt/fbt.c
+++ b/sys/cddl/dev/fbt/fbt.c
@@ -370,12 +370,12 @@ fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
 	const Elf_Sym *symp = lc->symtab;
 	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
 	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
+	size_t idwidth;
 	int i;
 	uint32_t *ctfoff;
 	uint32_t objtoff = hp->cth_objtoff;
 	uint32_t funcoff = hp->cth_funcoff;
-	ushort_t info;
-	ushort_t vlen;
+	uint_t kind, info, vlen;
 
 	/* Sanity check. */
 	if (hp->cth_magic != CTF_MAGIC) {
@@ -391,6 +391,8 @@ fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
 	ctfoff = malloc(sizeof(uint32_t) * lc->nsym, M_LINKER, M_WAITOK);
 	*lc->ctfoffp = ctfoff;
 
+	idwidth = hp->cth_version == CTF_VERSION_2 ? 2 : 4;
+
 	for (i = 0; i < lc->nsym; i++, ctfoff++, symp++) {
 		if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
 			*ctfoff = 0xffffffff;
@@ -400,13 +402,13 @@ fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
 		switch (ELF_ST_TYPE(symp->st_info)) {
 		case STT_OBJECT:
 			if (objtoff >= hp->cth_funcoff ||
-                            (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
+			    (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
 				*ctfoff = 0xffffffff;
-                                break;
-                        }
+				break;
+			}
 
-                        *ctfoff = objtoff;
-                        objtoff += sizeof (ushort_t);
+			*ctfoff = objtoff;
+			objtoff += idwidth;
 			break;
 
 		case STT_FUNC:
@@ -417,18 +419,25 @@ fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
 
 			*ctfoff = funcoff;
 
-			info = *((const ushort_t *)(ctfdata + funcoff));
-			vlen = CTF_INFO_VLEN(info);
+			info = 0;
+			memcpy(&info, ctfdata + funcoff, idwidth);
+			if (hp->cth_version == CTF_VERSION_2) {
+				kind = CTF_V2_INFO_KIND(info);
+				vlen = CTF_V2_INFO_VLEN(info);
+			} else {
+				kind = CTF_V3_INFO_KIND(info);
+				vlen = CTF_V3_INFO_VLEN(info);
+			}
 
 			/*
 			 * If we encounter a zero pad at the end, just skip it.
 			 * Otherwise skip over the function and its return type
 			 * (+2) and the argument list (vlen).
 			 */
-			if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
-				funcoff += sizeof (ushort_t); /* skip pad */
+			if (kind == CTF_K_UNKNOWN && vlen == 0)
+				funcoff += idwidth;
 			else
-				funcoff += sizeof (ushort_t) * (vlen + 2);
+				funcoff += idwidth * (vlen + 2);
 			break;
 
 		default:
@@ -440,18 +449,61 @@ fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
 	return (0);
 }
 
+static void
+fbt_get_ctt_index(uint8_t version, const void *v, uint_t *indexp,
+    uint_t *typep, int *ischildp)
+{
+	uint_t index, type;
+	int ischild;
+
+	if (version == CTF_VERSION_2) {
+		const struct ctf_type_v2 *ctt = v;
+
+		type = ctt->ctt_type;
+		index = CTF_V2_TYPE_TO_INDEX(ctt->ctt_type);
+		ischild = CTF_V2_TYPE_ISCHILD(ctt->ctt_type);
+	} else {
+		const struct ctf_type_v3 *ctt = v;
+
+		type = ctt->ctt_type;
+		index = CTF_V3_TYPE_TO_INDEX(ctt->ctt_type);
+		ischild = CTF_V3_TYPE_ISCHILD(ctt->ctt_type);
+	}
+
+	if (indexp != NULL)
+		*indexp = index;
+	if (typep != NULL)
+		*typep = type;
+	if (ischildp != NULL)
+		*ischildp = ischild;
+}
+
 static ssize_t
-fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep,
+fbt_get_ctt_size(uint8_t version, const void *tp, ssize_t *sizep,
     ssize_t *incrementp)
 {
 	ssize_t size, increment;
 
-	if (tp->ctt_size == CTF_LSIZE_SENT) {
-		size = CTF_TYPE_LSIZE(tp);
-		increment = sizeof (ctf_type_t);
+	if (version == CTF_VERSION_2) {
+		const struct ctf_type_v2 *ctt = tp;
+
+		if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
+			size = CTF_TYPE_LSIZE(ctt);
+			increment = sizeof (struct ctf_type_v2);
+		} else {
+			size = ctt->ctt_size;
+			increment = sizeof (struct ctf_stype_v2);
+		}
 	} else {
-		size = tp->ctt_size;
-		increment = sizeof (ctf_stype_t);
+		const struct ctf_type_v3 *ctt = tp;
+
+		if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
+			size = CTF_TYPE_LSIZE(ctt);
+			increment = sizeof (struct ctf_type_v3);
+		} else {
+			size = ctt->ctt_size;
+			increment = sizeof (struct ctf_stype_v3);
+		}
 	}
 
 	if (sizep)
@@ -462,41 +514,69 @@ fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep,
 	return (size);
 }
 
+static void
+fbt_get_ctt_info(uint8_t version, const void *tp, uint_t *kindp, uint_t *vlenp,
+    int *isrootp)
+{
+	uint_t kind, vlen;
+	int isroot;
+
+	if (version == CTF_VERSION_2) {
+		const struct ctf_type_v2 *ctt = tp;
+
+		kind = CTF_V2_INFO_KIND(ctt->ctt_info);
+		vlen = CTF_V2_INFO_VLEN(ctt->ctt_info);
+		isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info);
+	} else {
+		const struct ctf_type_v3 *ctt = tp;
+
+		kind = CTF_V3_INFO_KIND(ctt->ctt_info);
+		vlen = CTF_V3_INFO_VLEN(ctt->ctt_info);
+		isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info);
+	}
+
+	if (kindp != NULL)
+		*kindp = kind;
+	if (vlenp != NULL)
+		*vlenp = vlen;
+	if (isrootp != NULL)
+		*isrootp = isroot;
+}
+
 static int
 fbt_typoff_init(linker_ctf_t *lc)
 {
 	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
-	const ctf_type_t *tbuf;
-	const ctf_type_t *tend;
-	const ctf_type_t *tp;
+	const void *tbuf, *tend, *tp;
 	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
+	size_t idwidth;
 	int ctf_typemax = 0;
 	uint32_t *xp;
 	ulong_t pop[CTF_K_MAX + 1] = { 0 };
 	uint8_t version;
 
-
 	/* Sanity check. */
 	if (hp->cth_magic != CTF_MAGIC)
 		return (EINVAL);
 
 	version = hp->cth_version;
+	idwidth = version == CTF_VERSION_2 ? 2 : 4;
 
-	tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
-	tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
+	tbuf = (const void *) (ctfdata + hp->cth_typeoff);
+	tend = (const void *) (ctfdata + hp->cth_stroff);
 
 	/*
 	 * We make two passes through the entire type section.  In this first
 	 * pass, we count the number of each type and the total number of types.
 	 */
 	for (tp = tbuf; tp < tend; ctf_typemax++) {
-		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
-		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
+		uint_t kind, type, vlen;
 		ssize_t size, increment;
-
 		size_t vbytes;
 
 		(void) fbt_get_ctt_size(version, tp, &size, &increment);
+		fbt_get_ctt_info(version, tp, &kind, &vlen, NULL);
+		fbt_get_ctt_index(version, tp, NULL, &type, NULL);
 
 		switch (kind) {
 		case CTF_K_INTEGER:
@@ -504,17 +584,31 @@ fbt_typoff_init(linker_ctf_t *lc)
 			vbytes = sizeof (uint_t);
 			break;
 		case CTF_K_ARRAY:
-			vbytes = sizeof (ctf_array_t);
+			if (version == CTF_VERSION_2)
+				vbytes = sizeof (struct ctf_array_v2);
+			else
+				vbytes = sizeof (struct ctf_array_v3);
 			break;
 		case CTF_K_FUNCTION:
-			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
+			vbytes = roundup2(idwidth * vlen, sizeof(uint32_t));
 			break;
 		case CTF_K_STRUCT:
 		case CTF_K_UNION:
-			if (size < CTF_LSTRUCT_THRESH)
-				vbytes = sizeof (ctf_member_t) * vlen;
-			else
-				vbytes = sizeof (ctf_lmember_t) * vlen;
+			if (version == CTF_VERSION_2) {
+				if (size < CTF_V2_LSTRUCT_THRESH)
+					vbytes =
+					    sizeof (struct ctf_member_v2) * vlen;
+				else
+					vbytes =
+					    sizeof (struct ctf_lmember_v2) * vlen;
+			} else {
+				if (size < CTF_V3_LSTRUCT_THRESH)
+					vbytes =
+					    sizeof (struct ctf_member_v3) * vlen;
+				else
+					vbytes =
+					    sizeof (struct ctf_lmember_v3) * vlen;
+			}
 			break;
 		case CTF_K_ENUM:
 			vbytes = sizeof (ctf_enum_t) * vlen;
@@ -525,11 +619,10 @@ fbt_typoff_init(linker_ctf_t *lc)
 			 * kind for the tag, so bump that population count too.
 			 * If ctt_type is unknown, treat the tag as a struct.
 			 */
-			if (tp->ctt_type == CTF_K_UNKNOWN ||
-			    tp->ctt_type >= CTF_K_MAX)
+			if (type == CTF_K_UNKNOWN || type >= CTF_K_MAX)
 				pop[CTF_K_STRUCT]++;
 			else
-				pop[tp->ctt_type]++;
+				pop[type]++;
 			/*FALLTHRU*/
 		case CTF_K_UNKNOWN:
 			vbytes = 0;
@@ -545,7 +638,7 @@ fbt_typoff_init(linker_ctf_t *lc)
 			printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind);
 			return (EIO);
 		}
-		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
+		tp = (const void *)((uintptr_t)tp + increment + vbytes);
 		pop[kind]++;
 	}
 
@@ -565,13 +658,13 @@ fbt_typoff_init(linker_ctf_t *lc)
 	 * In the second pass, fill in the type offset.
 	 */
 	for (tp = tbuf; tp < tend; xp++) {
-		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
-		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);
 		ssize_t size, increment;
+		uint_t kind, vlen;
 
 		size_t vbytes;
 
 		(void) fbt_get_ctt_size(version, tp, &size, &increment);
+		fbt_get_ctt_info(version, tp, &kind, &vlen, NULL);
 
 		switch (kind) {
 		case CTF_K_INTEGER:
@@ -579,17 +672,31 @@ fbt_typoff_init(linker_ctf_t *lc)
 			vbytes = sizeof (uint_t);
 			break;
 		case CTF_K_ARRAY:
-			vbytes = sizeof (ctf_array_t);
+			if (version == CTF_VERSION_2)
+				vbytes = sizeof (struct ctf_array_v2);
+			else
+				vbytes = sizeof (struct ctf_array_v3);
 			break;
 		case CTF_K_FUNCTION:
-			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
+			vbytes = roundup2(idwidth * vlen, sizeof(uint32_t));
 			break;
 		case CTF_K_STRUCT:
 		case CTF_K_UNION:
-			if (size < CTF_LSTRUCT_THRESH)
-				vbytes = sizeof (ctf_member_t) * vlen;
-			else
-				vbytes = sizeof (ctf_lmember_t) * vlen;
+			if (version == CTF_VERSION_2) {
+				if (size < CTF_V2_LSTRUCT_THRESH)
+					vbytes =
+					    sizeof (struct ctf_member_v2) * vlen;
+				else
+					vbytes =
+					    sizeof (struct ctf_lmember_v2) * vlen;
+			} else {
+				if (size < CTF_V3_LSTRUCT_THRESH)
+					vbytes =
+					    sizeof (struct ctf_member_v3) * vlen;
+				else
+					vbytes =
+					    sizeof (struct ctf_lmember_v3) * vlen;
+			}
 			break;
 		case CTF_K_ENUM:
 			vbytes = sizeof (ctf_enum_t) * vlen;
@@ -610,7 +717,7 @@ fbt_typoff_init(linker_ctf_t *lc)
 			return (EIO);
 		}
 		*xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata);
-		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
+		tp = (const void *)((uintptr_t)tp + increment + vbytes);
 	}
 
 	return (0);
@@ -748,10 +855,10 @@ ctf_decl_fini(ctf_decl_t *cd)
 	}
 }
 
-static const ctf_type_t *
+static const void *
 ctf_lookup_by_id(linker_ctf_t *lc, ctf_id_t type)
 {
-	const ctf_type_t *tp;
+	const void *tp;
 	uint32_t offset;
 	uint32_t *typoff = *lc->typoffp;
 
@@ -766,7 +873,7 @@ ctf_lookup_by_id(linker_ctf_t *lc, ctf_id_t type)
 		return(NULL);
 	}
 
-	tp = (const ctf_type_t *)(lc->ctftab + offset + sizeof(ctf_header_t));
+	tp = (const void *) (lc->ctftab + offset + sizeof(ctf_header_t));
 
 	return (tp);
 }
@@ -775,24 +882,36 @@ static void
 fbt_array_info(linker_ctf_t *lc, ctf_id_t type, ctf_arinfo_t *arp)
 {
 	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
-	const ctf_type_t *tp;
-	const ctf_array_t *ap;
+	const void *tp;
 	ssize_t increment;
+	uint_t kind;
 
 	bzero(arp, sizeof(*arp));
 
 	if ((tp = ctf_lookup_by_id(lc, type)) == NULL)
 		return;
 
-	if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY)
+	fbt_get_ctt_info(hp->cth_version, tp, &kind, NULL, NULL);
+	if (kind != CTF_K_ARRAY)
 		return;
 
 	(void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment);
 
-	ap = (const ctf_array_t *)((uintptr_t)tp + increment);
-	arp->ctr_contents = ap->cta_contents;
-	arp->ctr_index = ap->cta_index;
-	arp->ctr_nelems = ap->cta_nelems;
+	if (hp->cth_version == CTF_VERSION_2) {
+		const struct ctf_array_v2 *ap;
+
+		ap = (const struct ctf_array_v2 *)((uintptr_t)tp + increment);
+		arp->ctr_contents = ap->cta_contents;
+		arp->ctr_index = ap->cta_index;
+		arp->ctr_nelems = ap->cta_nelems;
+	} else {
+		const struct ctf_array_v3 *ap;
+
+		ap = (const struct ctf_array_v3 *)((uintptr_t)tp + increment);
+		arp->ctr_contents = ap->cta_contents;
+		arp->ctr_index = ap->cta_index;
+		arp->ctr_nelems = ap->cta_nelems;
+	}
 }
 
 static const char *
@@ -809,15 +928,35 @@ ctf_strptr(linker_ctf_t *lc, int name)
 	return (strp);
 }
 
+static const char *
+ctf_type_rname(linker_ctf_t *lc, const void *v)
+{
+	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
+	uint_t name;
+
+	if (hp->cth_version == CTF_VERSION_2) {
+		const struct ctf_type_v2 *ctt = v;
+
+		name = ctt->ctt_name;
+	} else {
+		const struct ctf_type_v3 *ctt = v;
+
+		name = ctt->ctt_name;
+	}
+
+	return (ctf_strptr(lc, name));
+}
+
 static void
 ctf_decl_push(ctf_decl_t *cd, linker_ctf_t *lc, ctf_id_t type)
 {
+	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
 	ctf_decl_node_t *cdp;
 	ctf_decl_prec_t prec;
-	uint_t kind, n = 1;
+	uint_t kind, n = 1, t;
 	int is_qual = 0;
 
-	const ctf_type_t *tp;
+	const void *tp;
 	ctf_arinfo_t ar;
 
 	if ((tp = ctf_lookup_by_id(lc, type)) == NULL) {
@@ -825,7 +964,10 @@ ctf_decl_push(ctf_decl_t *cd, linker_ctf_t *lc, ctf_id_t type)
 		return;
 	}
 
-	switch (kind = CTF_INFO_KIND(tp->ctt_info)) {
+	fbt_get_ctt_info(hp->cth_version, tp, &kind, NULL, NULL);
+	fbt_get_ctt_index(hp->cth_version, tp, NULL, &t, NULL);
+
+	switch (kind) {
 	case CTF_K_ARRAY:
 		fbt_array_info(lc, type, &ar);
 		ctf_decl_push(cd, lc, ar.ctr_contents);
@@ -834,27 +976,27 @@ ctf_decl_push(ctf_decl_t *cd, linker_ctf_t *lc, ctf_id_t type)
 		break;
 
 	case CTF_K_TYPEDEF:
-		if (ctf_strptr(lc, tp->ctt_name)[0] == '\0') {
-			ctf_decl_push(cd, lc, tp->ctt_type);
+		if (ctf_type_rname(lc, tp)[0] == '\0') {
+			ctf_decl_push(cd, lc, t);
 			return;
 		}
 		prec = CTF_PREC_BASE;
 		break;
 
 	case CTF_K_FUNCTION:
-		ctf_decl_push(cd, lc, tp->ctt_type);
+		ctf_decl_push(cd, lc, t);
 		prec = CTF_PREC_FUNCTION;
 		break;
 
 	case CTF_K_POINTER:
-		ctf_decl_push(cd, lc, tp->ctt_type);
+		ctf_decl_push(cd, lc, t);
 		prec = CTF_PREC_POINTER;
 		break;
 
 	case CTF_K_VOLATILE:
 	case CTF_K_CONST:
 	case CTF_K_RESTRICT:
-		ctf_decl_push(cd, lc, tp->ctt_type);
+		ctf_decl_push(cd, lc, t);
 		prec = cd->cd_qualp;
 		is_qual++;
 		break;
@@ -943,9 +1085,8 @@ fbt_type_name(linker_ctf_t *lc, ctf_id_t type, char *buf, size_t len)
 		for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
 		    cdp != NULL; cdp = ctf_list_next(cdp)) {
 
-			const ctf_type_t *tp =
-			    ctf_lookup_by_id(lc, cdp->cd_type);
-			const char *name = ctf_strptr(lc, tp->ctt_name);
+			const void *tp = ctf_lookup_by_id(lc, cdp->cd_type);
+			const char *name = ctf_type_rname(lc, tp);
 
 			if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
 				ctf_decl_sprintf(&cd, " ");
@@ -1005,15 +1146,18 @@ fbt_type_name(linker_ctf_t *lc, ctf_id_t type, char *buf, size_t len)
 static void
 fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc)
 {
-	const ushort_t *dp;
+	const ctf_header_t *hp;
+	const char *dp;
 	fbt_probe_t *fbt = parg;
 	linker_ctf_t lc;
 	modctl_t *ctl = fbt->fbtp_ctl;
+	size_t idwidth;
 	int ndx = desc->dtargd_ndx;
 	int symindx = fbt->fbtp_symindx;
 	uint32_t *ctfoff;
-	uint32_t offset;
-	ushort_t info, kind, n;
+	uint32_t offset, type;
+	uint_t info, n;
+	ushort_t kind;
 
 	if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) {
 		(void) strcpy(desc->dtargd_native, "int");
@@ -1054,11 +1198,20 @@ fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_a
 	if ((offset = ctfoff[symindx]) == 0xffffffff)
 		return;
 
-	dp = (const ushort_t *)(lc.ctftab + offset + sizeof(ctf_header_t));
+	hp = (const ctf_header_t *) lc.ctftab;
+	idwidth = hp->cth_version == CTF_VERSION_2 ? 2 : 4;
+	dp = (const char *)(lc.ctftab + offset + sizeof(ctf_header_t));
 
-	info = *dp++;
-	kind = CTF_INFO_KIND(info);
-	n = CTF_INFO_VLEN(info);
+	info = 0;
+	memcpy(&info, dp, idwidth);
+	dp += idwidth;
+	if (hp->cth_version == CTF_VERSION_2) {
+		kind = CTF_V2_INFO_KIND(info);
+		n = CTF_V2_INFO_VLEN(info);
+	} else {
+		kind = CTF_V3_INFO_KIND(info);
+		n = CTF_V3_INFO_VLEN(info);
+	}
 
 	if (kind == CTF_K_UNKNOWN && n == 0) {
 		printf("%s(%d): Unknown function!\n",__func__,__LINE__);
@@ -1081,13 +1234,13 @@ fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_a
 			return;
 
 		/* Skip the return type and arguments up to the one requested. */
-		dp += ndx + 1;
+		dp += idwidth * (ndx + 1);
 	}
 
-	if (fbt_type_name(&lc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0)
+	type = 0;
+	memcpy(&type, dp, idwidth);
+	if (fbt_type_name(&lc, type, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0)
 		desc->dtargd_ndx = ndx;
-
-	return;
 }
 
 static int