Home | History | Annotate | Download | only in ctf
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 
     23 /*
     24  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     25  * Use is subject to license terms.
     26  */
     27 
     28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     29 
     30 #include <ctf_impl.h>
     31 
     32 ssize_t
     33 ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep,
     34     ssize_t *incrementp)
     35 {
     36 	ssize_t size, increment;
     37 
     38 	if (fp->ctf_version > CTF_VERSION_1 &&
     39 	    tp->ctt_size == CTF_LSIZE_SENT) {
     40 		size = CTF_TYPE_LSIZE(tp);
     41 		increment = sizeof (ctf_type_t);
     42 	} else {
     43 		size = tp->ctt_size;
     44 		increment = sizeof (ctf_stype_t);
     45 	}
     46 
     47 	if (sizep)
     48 		*sizep = size;
     49 	if (incrementp)
     50 		*incrementp = increment;
     51 
     52 	return (size);
     53 }
     54 
     55 /*
     56  * Iterate over the members of a STRUCT or UNION.  We pass the name, member
     57  * type, and offset of each member to the specified callback function.
     58  */
     59 int
     60 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
     61 {
     62 	ctf_file_t *ofp = fp;
     63 	const ctf_type_t *tp;
     64 	ssize_t size, increment;
     65 	uint_t kind, n;
     66 	int rc;
     67 
     68 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
     69 		return (CTF_ERR); /* errno is set for us */
     70 
     71 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
     72 		return (CTF_ERR); /* errno is set for us */
     73 
     74 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
     75 	kind = LCTF_INFO_KIND(fp, tp->ctt_info);
     76 
     77 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
     78 		return (ctf_set_errno(ofp, ECTF_NOTSOU));
     79 
     80 	if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) {
     81 		const ctf_member_t *mp = (const ctf_member_t *)
     82 		    ((uintptr_t)tp + increment);
     83 
     84 		for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) {
     85 			const char *name = ctf_strptr(fp, mp->ctm_name);
     86 			if ((rc = func(name, mp->ctm_type, mp->ctm_offset,
     87 			    arg)) != 0)
     88 				return (rc);
     89 		}
     90 
     91 	} else {
     92 		const ctf_lmember_t *lmp = (const ctf_lmember_t *)
     93 		    ((uintptr_t)tp + increment);
     94 
     95 		for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) {
     96 			const char *name = ctf_strptr(fp, lmp->ctlm_name);
     97 			if ((rc = func(name, lmp->ctlm_type,
     98 			    (ulong_t)CTF_LMEM_OFFSET(lmp), arg)) != 0)
     99 				return (rc);
    100 		}
    101 	}
    102 
    103 	return (0);
    104 }
    105 
    106 /*
    107  * Iterate over the members of an ENUM.  We pass the string name and associated
    108  * integer value of each enum element to the specified callback function.
    109  */
    110 int
    111 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
    112 {
    113 	ctf_file_t *ofp = fp;
    114 	const ctf_type_t *tp;
    115 	const ctf_enum_t *ep;
    116 	ssize_t increment;
    117 	uint_t n;
    118 	int rc;
    119 
    120 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    121 		return (CTF_ERR); /* errno is set for us */
    122 
    123 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    124 		return (CTF_ERR); /* errno is set for us */
    125 
    126 	if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM)
    127 		return (ctf_set_errno(ofp, ECTF_NOTENUM));
    128 
    129 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
    130 
    131 	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
    132 
    133 	for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
    134 		const char *name = ctf_strptr(fp, ep->cte_name);
    135 		if ((rc = func(name, ep->cte_value, arg)) != 0)
    136 			return (rc);
    137 	}
    138 
    139 	return (0);
    140 }
    141 
    142 /*
    143  * Iterate over every root (user-visible) type in the given CTF container.
    144  * We pass the type ID of each type to the specified callback function.
    145  */
    146 int
    147 ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
    148 {
    149 	ctf_id_t id, max = fp->ctf_typemax;
    150 	int rc, child = (fp->ctf_flags & LCTF_CHILD);
    151 
    152 	for (id = 1; id <= max; id++) {
    153 		const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
    154 		if (CTF_INFO_ISROOT(tp->ctt_info) &&
    155 		    (rc = func(CTF_INDEX_TO_TYPE(id, child), arg)) != 0)
    156 			return (rc);
    157 	}
    158 
    159 	return (0);
    160 }
    161 
    162 /*
    163  * Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
    164  * RESTRICT nodes until we reach a "base" type node.  This is useful when
    165  * we want to follow a type ID to a node that has members or a size.  To guard
    166  * against infinite loops, we implement simplified cycle detection and check
    167  * each link against itself, the previous node, and the topmost node.
    168  */
    169 ctf_id_t
    170 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
    171 {
    172 	ctf_id_t prev = type, otype = type;
    173 	ctf_file_t *ofp = fp;
    174 	const ctf_type_t *tp;
    175 
    176 	while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
    177 		switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
    178 		case CTF_K_TYPEDEF:
    179 		case CTF_K_VOLATILE:
    180 		case CTF_K_CONST:
    181 		case CTF_K_RESTRICT:
    182 			if (tp->ctt_type == type || tp->ctt_type == otype ||
    183 			    tp->ctt_type == prev) {
    184 				ctf_dprintf("type %ld cycle detected\n", otype);
    185 				return (ctf_set_errno(ofp, ECTF_CORRUPT));
    186 			}
    187 			prev = type;
    188 			type = tp->ctt_type;
    189 			break;
    190 		default:
    191 			return (type);
    192 		}
    193 	}
    194 
    195 	return (CTF_ERR); /* errno is set for us */
    196 }
    197 
    198 /*
    199  * Lookup the given type ID and print a string name for it into buf.  Return
    200  * the actual number of bytes (not including \0) needed to format the name.
    201  */
    202 ssize_t
    203 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
    204 {
    205 	ctf_decl_t cd;
    206 	ctf_decl_node_t *cdp;
    207 	ctf_decl_prec_t prec, lp, rp;
    208 	int ptr, arr;
    209 	uint_t k;
    210 
    211 	if (fp == NULL && type == CTF_ERR)
    212 		return (-1); /* simplify caller code by permitting CTF_ERR */
    213 
    214 	ctf_decl_init(&cd, buf, len);
    215 	ctf_decl_push(&cd, fp, type);
    216 
    217 	if (cd.cd_err != 0) {
    218 		ctf_decl_fini(&cd);
    219 		return (ctf_set_errno(fp, cd.cd_err));
    220 	}
    221 
    222 	/*
    223 	 * If the type graph's order conflicts with lexical precedence order
    224 	 * for pointers or arrays, then we need to surround the declarations at
    225 	 * the corresponding lexical precedence with parentheses.  This can
    226 	 * result in either a parenthesized pointer (*) as in int (*)() or
    227 	 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
    228 	 */
    229 	ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
    230 	arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
    231 
    232 	rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
    233 	lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
    234 
    235 	k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
    236 
    237 	for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
    238 		for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
    239 		    cdp != NULL; cdp = ctf_list_next(cdp)) {
    240 
    241 			ctf_file_t *rfp = fp;
    242 			const ctf_type_t *tp =
    243 			    ctf_lookup_by_id(&rfp, cdp->cd_type);
    244 			const char *name = ctf_strptr(rfp, tp->ctt_name);
    245 
    246 			if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
    247 				ctf_decl_sprintf(&cd, " ");
    248 
    249 			if (lp == prec) {
    250 				ctf_decl_sprintf(&cd, "(");
    251 				lp = -1;
    252 			}
    253 
    254 			switch (cdp->cd_kind) {
    255 			case CTF_K_INTEGER:
    256 			case CTF_K_FLOAT:
    257 			case CTF_K_TYPEDEF:
    258 				ctf_decl_sprintf(&cd, "%s", name);
    259 				break;
    260 			case CTF_K_POINTER:
    261 				ctf_decl_sprintf(&cd, "*");
    262 				break;
    263 			case CTF_K_ARRAY:
    264 				ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
    265 				break;
    266 			case CTF_K_FUNCTION:
    267 				ctf_decl_sprintf(&cd, "()");
    268 				break;
    269 			case CTF_K_STRUCT:
    270 			case CTF_K_FORWARD:
    271 				ctf_decl_sprintf(&cd, "struct %s", name);
    272 				break;
    273 			case CTF_K_UNION:
    274 				ctf_decl_sprintf(&cd, "union %s", name);
    275 				break;
    276 			case CTF_K_ENUM:
    277 				ctf_decl_sprintf(&cd, "enum %s", name);
    278 				break;
    279 			case CTF_K_VOLATILE:
    280 				ctf_decl_sprintf(&cd, "volatile");
    281 				break;
    282 			case CTF_K_CONST:
    283 				ctf_decl_sprintf(&cd, "const");
    284 				break;
    285 			case CTF_K_RESTRICT:
    286 				ctf_decl_sprintf(&cd, "restrict");
    287 				break;
    288 			}
    289 
    290 			k = cdp->cd_kind;
    291 		}
    292 
    293 		if (rp == prec)
    294 			ctf_decl_sprintf(&cd, ")");
    295 	}
    296 
    297 	if (cd.cd_len >= len)
    298 		(void) ctf_set_errno(fp, ECTF_NAMELEN);
    299 
    300 	ctf_decl_fini(&cd);
    301 	return (cd.cd_len);
    302 }
    303 
    304 /*
    305  * Lookup the given type ID and print a string name for it into buf.  If buf
    306  * is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
    307  */
    308 char *
    309 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
    310 {
    311 	ssize_t rv = ctf_type_lname(fp, type, buf, len);
    312 	return (rv >= 0 && rv < len ? buf : NULL);
    313 }
    314 
    315 /*
    316  * Resolve the type down to a base type node, and then return the size
    317  * of the type storage in bytes.
    318  */
    319 ssize_t
    320 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
    321 {
    322 	const ctf_type_t *tp;
    323 	ssize_t size;
    324 	ctf_arinfo_t ar;
    325 
    326 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    327 		return (-1); /* errno is set for us */
    328 
    329 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    330 		return (-1); /* errno is set for us */
    331 
    332 	switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
    333 	case CTF_K_POINTER:
    334 		return (fp->ctf_dmodel->ctd_pointer);
    335 
    336 	case CTF_K_FUNCTION:
    337 		return (0); /* function size is only known by symtab */
    338 
    339 	case CTF_K_ENUM:
    340 		return (fp->ctf_dmodel->ctd_int);
    341 
    342 	case CTF_K_ARRAY:
    343 		/*
    344 		 * Array size is not directly returned by stabs data.  Instead,
    345 		 * it defines the element type and requires the user to perform
    346 		 * the multiplication.  If ctf_get_ctt_size() returns zero, the
    347 		 * current version of ctfconvert does not compute member sizes
    348 		 * and we compute the size here on its behalf.
    349 		 */
    350 		if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
    351 			return (size);
    352 
    353 		if (ctf_array_info(fp, type, &ar) == CTF_ERR ||
    354 		    (size = ctf_type_size(fp, ar.ctr_contents)) == CTF_ERR)
    355 			return (-1); /* errno is set for us */
    356 
    357 		return (size * ar.ctr_nelems);
    358 
    359 	default:
    360 		return (ctf_get_ctt_size(fp, tp, NULL, NULL));
    361 	}
    362 }
    363 
    364 /*
    365  * Resolve the type down to a base type node, and then return the alignment
    366  * needed for the type storage in bytes.
    367  */
    368 ssize_t
    369 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
    370 {
    371 	const ctf_type_t *tp;
    372 	ctf_arinfo_t r;
    373 
    374 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    375 		return (-1); /* errno is set for us */
    376 
    377 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    378 		return (-1); /* errno is set for us */
    379 
    380 	switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
    381 	case CTF_K_POINTER:
    382 	case CTF_K_FUNCTION:
    383 		return (fp->ctf_dmodel->ctd_pointer);
    384 
    385 	case CTF_K_ARRAY:
    386 		if (ctf_array_info(fp, type, &r) == CTF_ERR)
    387 			return (-1); /* errno is set for us */
    388 		return (ctf_type_align(fp, r.ctr_contents));
    389 
    390 	case CTF_K_STRUCT:
    391 	case CTF_K_UNION: {
    392 		uint_t n = LCTF_INFO_VLEN(fp, tp->ctt_info);
    393 		ssize_t size, increment;
    394 		size_t align = 0;
    395 		const void *vmp;
    396 
    397 		(void) ctf_get_ctt_size(fp, tp, &size, &increment);
    398 		vmp = (uchar_t *)tp + increment;
    399 
    400 		if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_STRUCT)
    401 			n = MIN(n, 1); /* only use first member for structs */
    402 
    403 		if (fp->ctf_version == CTF_VERSION_1 ||
    404 		    size < CTF_LSTRUCT_THRESH) {
    405 			const ctf_member_t *mp = vmp;
    406 			for (; n != 0; n--, mp++) {
    407 				ssize_t am = ctf_type_align(fp, mp->ctm_type);
    408 				align = MAX(align, am);
    409 			}
    410 		} else {
    411 			const ctf_lmember_t *lmp = vmp;
    412 			for (; n != 0; n--, lmp++) {
    413 				ssize_t am = ctf_type_align(fp, lmp->ctlm_type);
    414 				align = MAX(align, am);
    415 			}
    416 		}
    417 
    418 		return (align);
    419 	}
    420 
    421 	case CTF_K_ENUM:
    422 		return (fp->ctf_dmodel->ctd_int);
    423 
    424 	default:
    425 		return (ctf_get_ctt_size(fp, tp, NULL, NULL));
    426 	}
    427 }
    428 
    429 /*
    430  * Return the kind (CTF_K_* constant) for the specified type ID.
    431  */
    432 int
    433 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
    434 {
    435 	const ctf_type_t *tp;
    436 
    437 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    438 		return (CTF_ERR); /* errno is set for us */
    439 
    440 	return (LCTF_INFO_KIND(fp, tp->ctt_info));
    441 }
    442 
    443 /*
    444  * If the type is one that directly references another type (such as POINTER),
    445  * then return the ID of the type to which it refers.
    446  */
    447 ctf_id_t
    448 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
    449 {
    450 	ctf_file_t *ofp = fp;
    451 	const ctf_type_t *tp;
    452 
    453 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    454 		return (CTF_ERR); /* errno is set for us */
    455 
    456 	switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
    457 	case CTF_K_POINTER:
    458 	case CTF_K_TYPEDEF:
    459 	case CTF_K_VOLATILE:
    460 	case CTF_K_CONST:
    461 	case CTF_K_RESTRICT:
    462 		return (tp->ctt_type);
    463 	default:
    464 		return (ctf_set_errno(ofp, ECTF_NOTREF));
    465 	}
    466 }
    467 
    468 /*
    469  * Find a pointer to type by looking in fp->ctf_ptrtab.  If we can't find a
    470  * pointer to the given type, see if we can compute a pointer to the type
    471  * resulting from resolving the type down to its base type and use that
    472  * instead.  This helps with cases where the CTF data includes "struct foo *"
    473  * but not "foo_t *" and the user accesses "foo_t *" in the debugger.
    474  */
    475 ctf_id_t
    476 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
    477 {
    478 	ctf_file_t *ofp = fp;
    479 	ctf_id_t ntype;
    480 
    481 	if (ctf_lookup_by_id(&fp, type) == NULL)
    482 		return (CTF_ERR); /* errno is set for us */
    483 
    484 	if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
    485 		return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
    486 
    487 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    488 		return (ctf_set_errno(ofp, ECTF_NOTYPE));
    489 
    490 	if (ctf_lookup_by_id(&fp, type) == NULL)
    491 		return (ctf_set_errno(ofp, ECTF_NOTYPE));
    492 
    493 	if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
    494 		return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
    495 
    496 	return (ctf_set_errno(ofp, ECTF_NOTYPE));
    497 }
    498 
    499 /*
    500  * Return the encoding for the specified INTEGER or FLOAT.
    501  */
    502 int
    503 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
    504 {
    505 	ctf_file_t *ofp = fp;
    506 	const ctf_type_t *tp;
    507 	ssize_t increment;
    508 	uint_t data;
    509 
    510 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    511 		return (CTF_ERR); /* errno is set for us */
    512 
    513 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
    514 
    515 	switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
    516 	case CTF_K_INTEGER:
    517 		data = *(const uint_t *)((uintptr_t)tp + increment);
    518 		ep->cte_format = CTF_INT_ENCODING(data);
    519 		ep->cte_offset = CTF_INT_OFFSET(data);
    520 		ep->cte_bits = CTF_INT_BITS(data);
    521 		break;
    522 	case CTF_K_FLOAT:
    523 		data = *(const uint_t *)((uintptr_t)tp + increment);
    524 		ep->cte_format = CTF_FP_ENCODING(data);
    525 		ep->cte_offset = CTF_FP_OFFSET(data);
    526 		ep->cte_bits = CTF_FP_BITS(data);
    527 		break;
    528 	default:
    529 		return (ctf_set_errno(ofp, ECTF_NOTINTFP));
    530 	}
    531 
    532 	return (0);
    533 }
    534 
    535 int
    536 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
    537 {
    538 	int rval;
    539 
    540 	if (ltype < rtype)
    541 		rval = -1;
    542 	else if (ltype > rtype)
    543 		rval = 1;
    544 	else
    545 		rval = 0;
    546 
    547 	if (lfp == rfp)
    548 		return (rval);
    549 
    550 	if (CTF_TYPE_ISPARENT(ltype) && lfp->ctf_parent != NULL)
    551 		lfp = lfp->ctf_parent;
    552 
    553 	if (CTF_TYPE_ISPARENT(rtype) && rfp->ctf_parent != NULL)
    554 		rfp = rfp->ctf_parent;
    555 
    556 	if (lfp < rfp)
    557 		return (-1);
    558 
    559 	if (lfp > rfp)
    560 		return (1);
    561 
    562 	return (rval);
    563 }
    564 
    565 /*
    566  * Return a boolean value indicating if two types are compatible integers or
    567  * floating-pointer values.  This function returns true if the two types are
    568  * the same, or if they have the same ASCII name and encoding properties.
    569  * This function could be extended to test for compatibility for other kinds.
    570  */
    571 int
    572 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
    573     ctf_file_t *rfp, ctf_id_t rtype)
    574 {
    575 	const ctf_type_t *ltp, *rtp;
    576 	ctf_encoding_t le, re;
    577 	ctf_arinfo_t la, ra;
    578 	uint_t lkind, rkind;
    579 
    580 	if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
    581 		return (1);
    582 
    583 	ltype = ctf_type_resolve(lfp, ltype);
    584 	lkind = ctf_type_kind(lfp, ltype);
    585 
    586 	rtype = ctf_type_resolve(rfp, rtype);
    587 	rkind = ctf_type_kind(rfp, rtype);
    588 
    589 	if (lkind != rkind ||
    590 	    (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL ||
    591 	    (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL ||
    592 	    strcmp(ctf_strptr(lfp, ltp->ctt_name),
    593 	    ctf_strptr(rfp, rtp->ctt_name)) != 0)
    594 		return (0);
    595 
    596 	switch (lkind) {
    597 	case CTF_K_INTEGER:
    598 	case CTF_K_FLOAT:
    599 		return (ctf_type_encoding(lfp, ltype, &le) == 0 &&
    600 		    ctf_type_encoding(rfp, rtype, &re) == 0 &&
    601 		    bcmp(&le, &re, sizeof (ctf_encoding_t)) == 0);
    602 	case CTF_K_POINTER:
    603 		return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype),
    604 		    rfp, ctf_type_reference(rfp, rtype)));
    605 	case CTF_K_ARRAY:
    606 		return (ctf_array_info(lfp, ltype, &la) == 0 &&
    607 		    ctf_array_info(rfp, rtype, &ra) == 0 &&
    608 		    la.ctr_nelems == ra.ctr_nelems && ctf_type_compat(
    609 		    lfp, la.ctr_contents, rfp, ra.ctr_contents) &&
    610 		    ctf_type_compat(lfp, la.ctr_index, rfp, ra.ctr_index));
    611 	case CTF_K_STRUCT:
    612 	case CTF_K_UNION:
    613 		return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype));
    614 	case CTF_K_ENUM:
    615 	case CTF_K_FORWARD:
    616 		return (1); /* no other checks required for these type kinds */
    617 	default:
    618 		return (0); /* should not get here since we did a resolve */
    619 	}
    620 }
    621 
    622 /*
    623  * Return the type and offset for a given member of a STRUCT or UNION.
    624  */
    625 int
    626 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
    627     ctf_membinfo_t *mip)
    628 {
    629 	ctf_file_t *ofp = fp;
    630 	const ctf_type_t *tp;
    631 	ssize_t size, increment;
    632 	uint_t kind, n;
    633 
    634 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    635 		return (CTF_ERR); /* errno is set for us */
    636 
    637 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    638 		return (CTF_ERR); /* errno is set for us */
    639 
    640 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
    641 	kind = LCTF_INFO_KIND(fp, tp->ctt_info);
    642 
    643 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
    644 		return (ctf_set_errno(ofp, ECTF_NOTSOU));
    645 
    646 	if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) {
    647 		const ctf_member_t *mp = (const ctf_member_t *)
    648 		    ((uintptr_t)tp + increment);
    649 
    650 		for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) {
    651 			if (strcmp(ctf_strptr(fp, mp->ctm_name), name) == 0) {
    652 				mip->ctm_type = mp->ctm_type;
    653 				mip->ctm_offset = mp->ctm_offset;
    654 				return (0);
    655 			}
    656 		}
    657 	} else {
    658 		const ctf_lmember_t *lmp = (const ctf_lmember_t *)
    659 		    ((uintptr_t)tp + increment);
    660 
    661 		for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) {
    662 			if (strcmp(ctf_strptr(fp, lmp->ctlm_name), name) == 0) {
    663 				mip->ctm_type = lmp->ctlm_type;
    664 				mip->ctm_offset = (ulong_t)CTF_LMEM_OFFSET(lmp);
    665 				return (0);
    666 			}
    667 		}
    668 	}
    669 
    670 	return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
    671 }
    672 
    673 /*
    674  * Return the array type, index, and size information for the specified ARRAY.
    675  */
    676 int
    677 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
    678 {
    679 	ctf_file_t *ofp = fp;
    680 	const ctf_type_t *tp;
    681 	const ctf_array_t *ap;
    682 	ssize_t increment;
    683 
    684 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    685 		return (CTF_ERR); /* errno is set for us */
    686 
    687 	if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ARRAY)
    688 		return (ctf_set_errno(ofp, ECTF_NOTARRAY));
    689 
    690 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
    691 
    692 	ap = (const ctf_array_t *)((uintptr_t)tp + increment);
    693 	arp->ctr_contents = ap->cta_contents;
    694 	arp->ctr_index = ap->cta_index;
    695 	arp->ctr_nelems = ap->cta_nelems;
    696 
    697 	return (0);
    698 }
    699 
    700 /*
    701  * Convert the specified value to the corresponding enum member name, if a
    702  * matching name can be found.  Otherwise NULL is returned.
    703  */
    704 const char *
    705 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
    706 {
    707 	ctf_file_t *ofp = fp;
    708 	const ctf_type_t *tp;
    709 	const ctf_enum_t *ep;
    710 	ssize_t increment;
    711 	uint_t n;
    712 
    713 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    714 		return (NULL); /* errno is set for us */
    715 
    716 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    717 		return (NULL); /* errno is set for us */
    718 
    719 	if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
    720 		(void) ctf_set_errno(ofp, ECTF_NOTENUM);
    721 		return (NULL);
    722 	}
    723 
    724 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
    725 
    726 	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
    727 
    728 	for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
    729 		if (ep->cte_value == value)
    730 			return (ctf_strptr(fp, ep->cte_name));
    731 	}
    732 
    733 	(void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
    734 	return (NULL);
    735 }
    736 
    737 /*
    738  * Convert the specified enum tag name to the corresponding value, if a
    739  * matching name can be found.  Otherwise CTF_ERR is returned.
    740  */
    741 int
    742 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
    743 {
    744 	ctf_file_t *ofp = fp;
    745 	const ctf_type_t *tp;
    746 	const ctf_enum_t *ep;
    747 	ssize_t size, increment;
    748 	uint_t n;
    749 
    750 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    751 		return (CTF_ERR); /* errno is set for us */
    752 
    753 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    754 		return (CTF_ERR); /* errno is set for us */
    755 
    756 	if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
    757 		(void) ctf_set_errno(ofp, ECTF_NOTENUM);
    758 		return (CTF_ERR);
    759 	}
    760 
    761 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
    762 
    763 	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
    764 
    765 	for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
    766 		if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
    767 			if (valp != NULL)
    768 				*valp = ep->cte_value;
    769 			return (0);
    770 		}
    771 	}
    772 
    773 	(void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
    774 	return (CTF_ERR);
    775 }
    776 
    777 /*
    778  * Recursively visit the members of any type.  This function is used as the
    779  * engine for ctf_type_visit, below.  We resolve the input type, recursively
    780  * invoke ourself for each type member if the type is a struct or union, and
    781  * then invoke the callback function on the current type.  If any callback
    782  * returns non-zero, we abort and percolate the error code back up to the top.
    783  */
    784 static int
    785 ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
    786     const char *name, ulong_t offset, int depth)
    787 {
    788 	ctf_id_t otype = type;
    789 	const ctf_type_t *tp;
    790 	ssize_t size, increment;
    791 	uint_t kind, n;
    792 	int rc;
    793 
    794 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    795 		return (CTF_ERR); /* errno is set for us */
    796 
    797 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    798 		return (CTF_ERR); /* errno is set for us */
    799 
    800 	if ((rc = func(name, otype, offset, depth, arg)) != 0)
    801 		return (rc);
    802 
    803 	kind = LCTF_INFO_KIND(fp, tp->ctt_info);
    804 
    805 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
    806 		return (0);
    807 
    808 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
    809 
    810 	if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) {
    811 		const ctf_member_t *mp = (const ctf_member_t *)
    812 		    ((uintptr_t)tp + increment);
    813 
    814 		for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) {
    815 			if ((rc = ctf_type_rvisit(fp, mp->ctm_type,
    816 			    func, arg, ctf_strptr(fp, mp->ctm_name),
    817 			    offset + mp->ctm_offset, depth + 1)) != 0)
    818 				return (rc);
    819 		}
    820 
    821 	} else {
    822 		const ctf_lmember_t *lmp = (const ctf_lmember_t *)
    823 		    ((uintptr_t)tp + increment);
    824 
    825 		for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) {
    826 			if ((rc = ctf_type_rvisit(fp, lmp->ctlm_type,
    827 			    func, arg, ctf_strptr(fp, lmp->ctlm_name),
    828 			    offset + (ulong_t)CTF_LMEM_OFFSET(lmp),
    829 			    depth + 1)) != 0)
    830 				return (rc);
    831 		}
    832 	}
    833 
    834 	return (0);
    835 }
    836 
    837 /*
    838  * Recursively visit the members of any type.  We pass the name, member
    839  * type, and offset of each member to the specified callback function.
    840  */
    841 int
    842 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
    843 {
    844 	return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
    845 }
    846