Home | History | Annotate | Line # | 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 #ifdef HAVE_NBTOOL_CONFIG_H
     23 #include "nbtool_config.h"
     24 #endif
     25 
     26 /*
     27  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     28  * Use is subject to license terms.
     29  */
     30 
     31 #include <ctf_impl.h>
     32 
     33 void
     34 ctf_get_ctt_index(const ctf_file_t *fp, const void *v, uint_t *indexp,
     35     uint_t *typep, int *ischildp)
     36 {
     37 	uint_t index, type;
     38 	int ischild;
     39 
     40 	if (fp->ctf_version == CTF_VERSION_2) {
     41 		const struct ctf_type_v2 *ctt = v;
     42 
     43 		type = ctt->ctt_type;
     44 		index = CTF_V2_TYPE_TO_INDEX(ctt->ctt_type);
     45 		ischild = CTF_V2_TYPE_ISCHILD(ctt->ctt_type);
     46 	} else {
     47 		const struct ctf_type_v3 *ctt = v;
     48 
     49 		type = ctt->ctt_type;
     50 		index = CTF_V3_TYPE_TO_INDEX(ctt->ctt_type);
     51 		ischild = CTF_V3_TYPE_ISCHILD(ctt->ctt_type);
     52 	}
     53 
     54 	if (indexp != NULL)
     55 		*indexp = index;
     56 	if (typep != NULL)
     57 		*typep = type;
     58 	if (ischildp != NULL)
     59 		*ischildp = ischild;
     60 }
     61 
     62 void
     63 ctf_get_ctt_info(const ctf_file_t *fp, const void *v, uint_t *kindp,
     64     uint_t *vlenp, uint_t *isrootp)
     65 {
     66 	uint_t kind, vlen;
     67 	int isroot;
     68 
     69 	if (fp->ctf_version == CTF_VERSION_2) {
     70 		const struct ctf_type_v2 *ctt = v;
     71 
     72 		kind = CTF_V2_INFO_KIND(ctt->ctt_info);
     73 		vlen = CTF_V2_INFO_VLEN(ctt->ctt_info);
     74 		isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info);
     75 	} else {
     76 		const struct ctf_type_v3 *ctt = v;
     77 
     78 		kind = CTF_V3_INFO_KIND(ctt->ctt_info);
     79 		vlen = CTF_V3_INFO_VLEN(ctt->ctt_info);
     80 		isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info);
     81 	}
     82 
     83 	if (kindp != NULL)
     84 		*kindp = kind;
     85 	if (vlenp != NULL)
     86 		*vlenp = vlen;
     87 	if (isrootp != NULL)
     88 		*isrootp = isroot;
     89 }
     90 
     91 ssize_t
     92 ctf_get_ctt_size(const ctf_file_t *fp, const void *v, ssize_t *sizep,
     93     ssize_t *incrementp)
     94 {
     95 	ssize_t size, increment;
     96 
     97 	if (fp->ctf_version == CTF_VERSION_2) {
     98 		const struct ctf_type_v2 *ctt = v;
     99 
    100 		if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
    101 			size = (size_t)CTF_TYPE_LSIZE(ctt);
    102 			increment = sizeof (struct ctf_type_v2);
    103 		} else {
    104 			size = ctt->ctt_size;
    105 			increment = sizeof (struct ctf_stype_v2);
    106 		}
    107 	} else {
    108 		const struct ctf_type_v3 *ctt = v;
    109 
    110 		if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
    111 			size = (size_t)CTF_TYPE_LSIZE(ctt);
    112 			increment = sizeof (struct ctf_type_v3);
    113 		} else {
    114 			size = ctt->ctt_size;
    115 			increment = sizeof (struct ctf_stype_v3);
    116 		}
    117 	}
    118 
    119 	if (sizep)
    120 		*sizep = size;
    121 	if (incrementp)
    122 		*incrementp = increment;
    123 
    124 	return (size);
    125 }
    126 
    127 /*
    128  * Fetch info for a struct or union member.
    129  */
    130 void
    131 ctf_get_ctm_info(const ctf_file_t *fp, const void *v, ssize_t size,
    132     ssize_t *incrementp, uint_t *typep, ulong_t *offsetp, const char **namep)
    133 {
    134 	size_t increment;
    135 	ulong_t offset;
    136 	uint_t name, type;
    137 
    138 	if (fp->ctf_version == CTF_VERSION_2) {
    139 		if (size < CTF_V2_LSTRUCT_THRESH) {
    140 			const struct ctf_member_v2 *ctm = v;
    141 
    142 			name = ctm->ctm_name;
    143 			type = ctm->ctm_type;
    144 			offset = ctm->ctm_offset;
    145 			increment = sizeof(*ctm);
    146 		} else {
    147 			const struct ctf_lmember_v2 *ctlm = v;
    148 
    149 			name = ctlm->ctlm_name;
    150 			type = ctlm->ctlm_type;
    151 			offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
    152 			increment = sizeof(*ctlm);
    153 		}
    154 	} else {
    155 		if (size < CTF_V3_LSTRUCT_THRESH) {
    156 			const struct ctf_member_v3 *ctm = v;
    157 
    158 			name = ctm->ctm_name;
    159 			type = ctm->ctm_type;
    160 			offset = ctm->ctm_offset;
    161 			increment = sizeof(*ctm);
    162 		} else {
    163 			const struct ctf_lmember_v3 *ctlm = v;
    164 
    165 			name = ctlm->ctlm_name;
    166 			type = ctlm->ctlm_type;
    167 			offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
    168 			increment = sizeof(*ctlm);
    169 		}
    170 	}
    171 
    172 	if (incrementp != NULL)
    173 		*incrementp = increment;
    174 	if (typep != NULL)
    175 		*typep = type;
    176 	if (offsetp != NULL)
    177 		*offsetp = offset;
    178 	if (namep != NULL)
    179 		*namep = ctf_strraw(fp, name);
    180 }
    181 
    182 /*
    183  * Iterate over the members of a STRUCT or UNION.  We pass the name, member
    184  * type, and offset of each member to the specified callback function.
    185  */
    186 int
    187 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
    188 {
    189 	ctf_file_t *ofp = fp;
    190 	const void *tp;
    191 	ssize_t size, increment;
    192 	uint_t kind, n, vlen;
    193 	int rc;
    194 
    195 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    196 		return (CTF_ERR); /* errno is set for us */
    197 
    198 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    199 		return (CTF_ERR); /* errno is set for us */
    200 
    201 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
    202 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
    203 
    204 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
    205 		return (ctf_set_errno(ofp, ECTF_NOTSOU));
    206 
    207 	const char *mp = (const char *)((uintptr_t)tp + increment);
    208 
    209 	for (n = vlen; n != 0; n--, mp += increment) {
    210 		const char *name;
    211 		ulong_t offset;
    212 		uint_t xtype;
    213 
    214 		ctf_get_ctm_info(fp, mp, size, &increment, &xtype, &offset,
    215 		    &name);
    216 		if ((rc = func(name, xtype, offset, arg)) != 0)
    217 			return (rc);
    218 	}
    219 
    220 	return (0);
    221 }
    222 
    223 /*
    224  * Iterate over the members of an ENUM.  We pass the string name and associated
    225  * integer value of each enum element to the specified callback function.
    226  */
    227 int
    228 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
    229 {
    230 	ctf_file_t *ofp = fp;
    231 	const void *tp;
    232 	const ctf_enum_t *ep;
    233 	ssize_t increment;
    234 	uint_t kind, n, vlen;
    235 	int rc;
    236 
    237 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    238 		return (CTF_ERR); /* errno is set for us */
    239 
    240 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    241 		return (CTF_ERR); /* errno is set for us */
    242 
    243 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
    244 	if (kind != CTF_K_ENUM)
    245 		return (ctf_set_errno(ofp, ECTF_NOTENUM));
    246 
    247 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
    248 
    249 	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
    250 
    251 	for (n = vlen; n != 0; n--, ep++) {
    252 		const char *name = ctf_strptr(fp, ep->cte_name);
    253 		if ((rc = func(name, ep->cte_value, arg)) != 0)
    254 			return (rc);
    255 	}
    256 
    257 	return (0);
    258 }
    259 
    260 /*
    261  * Iterate over every root (user-visible) type in the given CTF container.
    262  * We pass the type ID of each type to the specified callback function.
    263  */
    264 int
    265 ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
    266 {
    267 	ctf_id_t id, max = fp->ctf_typemax;
    268 	int rc, child = (fp->ctf_flags & LCTF_CHILD);
    269 	uint_t isroot;
    270 
    271 	for (id = 1; id <= max; id++) {
    272 		const void *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
    273 		ctf_get_ctt_info(fp, tp, NULL, NULL, &isroot);
    274 		if (isroot &&
    275 		    (rc = func(LCTF_INDEX_TO_TYPE(fp, id, child), arg)) != 0)
    276 			return (rc);
    277 	}
    278 
    279 	return (0);
    280 }
    281 
    282 /*
    283  * Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
    284  * RESTRICT nodes until we reach a "base" type node.  This is useful when
    285  * we want to follow a type ID to a node that has members or a size.  To guard
    286  * against infinite loops, we implement simplified cycle detection and check
    287  * each link against itself, the previous node, and the topmost node.
    288  */
    289 ctf_id_t
    290 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
    291 {
    292 	ctf_id_t prev = type, otype = type;
    293 	ctf_file_t *ofp = fp;
    294 	const void *tp;
    295 	uint_t kind, ctype;
    296 
    297 	while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
    298 		ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
    299 		switch (kind) {
    300 		case CTF_K_TYPEDEF:
    301 		case CTF_K_VOLATILE:
    302 		case CTF_K_CONST:
    303 		case CTF_K_RESTRICT:
    304 			ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
    305 			if (ctype == type || ctype == otype || ctype == prev) {
    306 				ctf_dprintf("type %ld cycle detected\n", otype);
    307 				return (ctf_set_errno(ofp, ECTF_CORRUPT));
    308 			}
    309 			prev = type;
    310 			type = ctype;
    311 			break;
    312 		default:
    313 			return (type);
    314 		}
    315 	}
    316 
    317 	return (CTF_ERR); /* errno is set for us */
    318 }
    319 
    320 /*
    321  * Lookup the given type ID and print a string name for it into buf.  Return
    322  * the actual number of bytes (not including \0) needed to format the name.
    323  */
    324 static ssize_t
    325 ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
    326     const char *qname)
    327 {
    328 	ctf_decl_t cd;
    329 	ctf_decl_node_t *cdp;
    330 	ctf_decl_prec_t prec, lp, rp;
    331 	int ptr, arr;
    332 	uint_t k;
    333 
    334 	if (fp == NULL && type == CTF_ERR)
    335 		return (-1); /* simplify caller code by permitting CTF_ERR */
    336 
    337 	ctf_decl_init(&cd, buf, len);
    338 	ctf_decl_push(&cd, fp, type);
    339 
    340 	if (cd.cd_err != 0) {
    341 		ctf_decl_fini(&cd);
    342 		return (ctf_set_errno(fp, cd.cd_err));
    343 	}
    344 
    345 	/*
    346 	 * If the type graph's order conflicts with lexical precedence order
    347 	 * for pointers or arrays, then we need to surround the declarations at
    348 	 * the corresponding lexical precedence with parentheses.  This can
    349 	 * result in either a parenthesized pointer (*) as in int (*)() or
    350 	 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
    351 	 */
    352 	ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
    353 	arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
    354 
    355 	rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
    356 	lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
    357 
    358 	k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
    359 
    360 	for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
    361 		for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
    362 		    cdp != NULL; cdp = ctf_list_next(cdp)) {
    363 
    364 			ctf_file_t *rfp = fp;
    365 			const void *tp = ctf_lookup_by_id(&rfp, cdp->cd_type);
    366 			const char *name = ctf_type_rname(rfp, tp);
    367 
    368 			if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
    369 				ctf_decl_sprintf(&cd, " ");
    370 
    371 			if (lp == prec) {
    372 				ctf_decl_sprintf(&cd, "(");
    373 				lp = -1;
    374 			}
    375 
    376 			switch (cdp->cd_kind) {
    377 			case CTF_K_INTEGER:
    378 			case CTF_K_FLOAT:
    379 			case CTF_K_TYPEDEF:
    380 				if (qname != NULL)
    381 					ctf_decl_sprintf(&cd, "%s`", qname);
    382 				ctf_decl_sprintf(&cd, "%s", name);
    383 				break;
    384 			case CTF_K_POINTER:
    385 				ctf_decl_sprintf(&cd, "*");
    386 				break;
    387 			case CTF_K_ARRAY:
    388 				ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
    389 				break;
    390 			case CTF_K_FUNCTION:
    391 				ctf_decl_sprintf(&cd, "()");
    392 				break;
    393 			case CTF_K_STRUCT:
    394 			case CTF_K_FORWARD:
    395 				ctf_decl_sprintf(&cd, "struct ");
    396 				if (qname != NULL)
    397 					ctf_decl_sprintf(&cd, "%s`", qname);
    398 				ctf_decl_sprintf(&cd, "%s", name);
    399 				break;
    400 			case CTF_K_UNION:
    401 				ctf_decl_sprintf(&cd, "union ");
    402 				if (qname != NULL)
    403 					ctf_decl_sprintf(&cd, "%s`", qname);
    404 				ctf_decl_sprintf(&cd, "%s", name);
    405 				break;
    406 			case CTF_K_ENUM:
    407 				ctf_decl_sprintf(&cd, "enum ");
    408 				if (qname != NULL)
    409 					ctf_decl_sprintf(&cd, "%s`", qname);
    410 				ctf_decl_sprintf(&cd, "%s", name);
    411 				break;
    412 			case CTF_K_VOLATILE:
    413 				ctf_decl_sprintf(&cd, "volatile");
    414 				break;
    415 			case CTF_K_CONST:
    416 				ctf_decl_sprintf(&cd, "const");
    417 				break;
    418 			case CTF_K_RESTRICT:
    419 				ctf_decl_sprintf(&cd, "restrict");
    420 				break;
    421 			}
    422 
    423 			k = cdp->cd_kind;
    424 		}
    425 
    426 		if (rp == prec)
    427 			ctf_decl_sprintf(&cd, ")");
    428 	}
    429 
    430 	if (cd.cd_len >= len)
    431 		(void) ctf_set_errno(fp, ECTF_NAMELEN);
    432 
    433 	ctf_decl_fini(&cd);
    434 	return (cd.cd_len);
    435 }
    436 
    437 ssize_t
    438 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
    439 {
    440 	return (ctf_type_qlname(fp, type, buf, len, NULL));
    441 }
    442 
    443 /*
    444  * Lookup the given type ID and print a string name for it into buf.  If buf
    445  * is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
    446  */
    447 char *
    448 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
    449 {
    450 	ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
    451 	return (rv >= 0 && rv < len ? buf : NULL);
    452 }
    453 
    454 char *
    455 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
    456     const char *qname)
    457 {
    458 	ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
    459 	return (rv >= 0 && rv < len ? buf : NULL);
    460 }
    461 
    462 const char *
    463 ctf_type_rname(ctf_file_t *fp, const void *v)
    464 {
    465 	uint_t name;
    466 
    467 	if (fp->ctf_version == CTF_VERSION_2) {
    468 		const struct ctf_type_v2 *ctt = v;
    469 
    470 		name = ctt->ctt_name;
    471 	} else {
    472 		const struct ctf_type_v3 *ctt = v;
    473 
    474 		name = ctt->ctt_name;
    475 	}
    476 
    477 	return (ctf_strptr(fp, name));
    478 }
    479 
    480 /*
    481  * Resolve the type down to a base type node, and then return the size
    482  * of the type storage in bytes.
    483  */
    484 ssize_t
    485 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
    486 {
    487 	const void *tp;
    488 	ssize_t size;
    489 	ctf_arinfo_t ar;
    490 	uint_t kind;
    491 
    492 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    493 		return (-1); /* errno is set for us */
    494 
    495 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    496 		return (-1); /* errno is set for us */
    497 
    498 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
    499 
    500 	switch (kind) {
    501 	case CTF_K_POINTER:
    502 		return (fp->ctf_dmodel->ctd_pointer);
    503 
    504 	case CTF_K_FUNCTION:
    505 		return (0); /* function size is only known by symtab */
    506 
    507 	case CTF_K_ENUM:
    508 		return (fp->ctf_dmodel->ctd_int);
    509 
    510 	case CTF_K_ARRAY:
    511 		/*
    512 		 * Array size is not directly returned by stabs data.  Instead,
    513 		 * it defines the element type and requires the user to perform
    514 		 * the multiplication.  If ctf_get_ctt_size() returns zero, the
    515 		 * current version of ctfconvert does not compute member sizes
    516 		 * and we compute the size here on its behalf.
    517 		 */
    518 		if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
    519 			return (size);
    520 
    521 		if (ctf_array_info(fp, type, &ar) == CTF_ERR ||
    522 		    (size = ctf_type_size(fp, ar.ctr_contents)) == CTF_ERR)
    523 			return (-1); /* errno is set for us */
    524 
    525 		return (size * ar.ctr_nelems);
    526 
    527 	default:
    528 		return (ctf_get_ctt_size(fp, tp, NULL, NULL));
    529 	}
    530 }
    531 
    532 /*
    533  * Resolve the type down to a base type node, and then return the alignment
    534  * needed for the type storage in bytes.
    535  */
    536 ssize_t
    537 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
    538 {
    539 	const void *tp;
    540 	ctf_arinfo_t r;
    541 	uint_t kind, vlen;
    542 
    543 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    544 		return (-1); /* errno is set for us */
    545 
    546 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    547 		return (-1); /* errno is set for us */
    548 
    549 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
    550 
    551 	switch (kind) {
    552 	case CTF_K_POINTER:
    553 	case CTF_K_FUNCTION:
    554 		return (fp->ctf_dmodel->ctd_pointer);
    555 
    556 	case CTF_K_ARRAY:
    557 		if (ctf_array_info(fp, type, &r) == CTF_ERR)
    558 			return (-1); /* errno is set for us */
    559 		return (ctf_type_align(fp, r.ctr_contents));
    560 
    561 	case CTF_K_STRUCT:
    562 	case CTF_K_UNION: {
    563 		uint_t n = vlen;
    564 		ssize_t size, increment;
    565 		size_t align = 0;
    566 		const void *vmp;
    567 
    568 		(void) ctf_get_ctt_size(fp, tp, &size, &increment);
    569 		vmp = (const uchar_t *)tp + increment;
    570 
    571 		if (kind == CTF_K_STRUCT)
    572 			n = MIN(n, 1); /* only use first member for structs */
    573 
    574 		for (const char *mp = vmp; n != 0; n--, mp += increment) {
    575 			uint_t xtype;
    576 
    577 			ctf_get_ctm_info(fp, mp, size, &increment, &xtype,
    578 			    NULL, NULL);
    579 			ssize_t am = ctf_type_align(fp, xtype);
    580 			align = MAX(align, am);
    581 		}
    582 
    583 		return (align);
    584 	}
    585 
    586 	case CTF_K_ENUM:
    587 		return (fp->ctf_dmodel->ctd_int);
    588 
    589 	default:
    590 		return (ctf_get_ctt_size(fp, tp, NULL, NULL));
    591 	}
    592 }
    593 
    594 /*
    595  * Return the kind (CTF_K_* constant) for the specified type ID.
    596  */
    597 int
    598 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
    599 {
    600 	const void *tp;
    601 	uint_t kind;
    602 
    603 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    604 		return (CTF_ERR); /* errno is set for us */
    605 
    606 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
    607 
    608 	return (kind);
    609 }
    610 
    611 /*
    612  * If the type is one that directly references another type (such as POINTER),
    613  * then return the ID of the type to which it refers.
    614  */
    615 ctf_id_t
    616 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
    617 {
    618 	ctf_file_t *ofp = fp;
    619 	const void *tp;
    620 	uint_t ctype, kind;
    621 
    622 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    623 		return (CTF_ERR); /* errno is set for us */
    624 
    625 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
    626 
    627 	switch (kind) {
    628 	case CTF_K_POINTER:
    629 	case CTF_K_TYPEDEF:
    630 	case CTF_K_VOLATILE:
    631 	case CTF_K_CONST:
    632 	case CTF_K_RESTRICT:
    633 		ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
    634 		return (ctype);
    635 	default:
    636 		return (ctf_set_errno(ofp, ECTF_NOTREF));
    637 	}
    638 }
    639 
    640 /*
    641  * Find a pointer to type by looking in fp->ctf_ptrtab.  If we can't find a
    642  * pointer to the given type, see if we can compute a pointer to the type
    643  * resulting from resolving the type down to its base type and use that
    644  * instead.  This helps with cases where the CTF data includes "struct foo *"
    645  * but not "foo_t *" and the user accesses "foo_t *" in the debugger.
    646  */
    647 ctf_id_t
    648 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
    649 {
    650 	ctf_file_t *ofp = fp;
    651 	ctf_id_t ntype;
    652 
    653 	if (ctf_lookup_by_id(&fp, type) == NULL)
    654 		return (CTF_ERR); /* errno is set for us */
    655 
    656 	if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
    657 		return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
    658 
    659 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    660 		return (ctf_set_errno(ofp, ECTF_NOTYPE));
    661 
    662 	if (ctf_lookup_by_id(&fp, type) == NULL)
    663 		return (ctf_set_errno(ofp, ECTF_NOTYPE));
    664 
    665 	if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
    666 		return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
    667 
    668 	return (ctf_set_errno(ofp, ECTF_NOTYPE));
    669 }
    670 
    671 /*
    672  * Return the encoding for the specified INTEGER or FLOAT.
    673  */
    674 int
    675 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
    676 {
    677 	ctf_file_t *ofp = fp;
    678 	const void *tp;
    679 	ssize_t increment;
    680 	uint_t data, kind;
    681 
    682 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    683 		return (CTF_ERR); /* errno is set for us */
    684 
    685 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
    686 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
    687 
    688 	switch (kind) {
    689 	case CTF_K_INTEGER:
    690 		data = *(const uint_t *)((uintptr_t)tp + increment);
    691 		ep->cte_format = CTF_INT_ENCODING(data);
    692 		ep->cte_offset = CTF_INT_OFFSET(data);
    693 		ep->cte_bits = CTF_INT_BITS(data);
    694 		break;
    695 	case CTF_K_FLOAT:
    696 		data = *(const uint_t *)((uintptr_t)tp + increment);
    697 		ep->cte_format = CTF_FP_ENCODING(data);
    698 		ep->cte_offset = CTF_FP_OFFSET(data);
    699 		ep->cte_bits = CTF_FP_BITS(data);
    700 		break;
    701 	default:
    702 		return (ctf_set_errno(ofp, ECTF_NOTINTFP));
    703 	}
    704 
    705 	return (0);
    706 }
    707 
    708 int
    709 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
    710 {
    711 	int rval;
    712 
    713 	if (ltype < rtype)
    714 		rval = -1;
    715 	else if (ltype > rtype)
    716 		rval = 1;
    717 	else
    718 		rval = 0;
    719 
    720 	if (lfp == rfp)
    721 		return (rval);
    722 
    723 	if (LCTF_TYPE_ISPARENT(lfp, ltype) && lfp->ctf_parent != NULL)
    724 		lfp = lfp->ctf_parent;
    725 
    726 	if (LCTF_TYPE_ISPARENT(rfp, rtype) && rfp->ctf_parent != NULL)
    727 		rfp = rfp->ctf_parent;
    728 
    729 	if (lfp < rfp)
    730 		return (-1);
    731 
    732 	if (lfp > rfp)
    733 		return (1);
    734 
    735 	return (rval);
    736 }
    737 
    738 /*
    739  * Return a boolean value indicating if two types are compatible integers or
    740  * floating-pointer values.  This function returns true if the two types are
    741  * the same, or if they have the same ASCII name and encoding properties.
    742  * This function could be extended to test for compatibility for other kinds.
    743  */
    744 int
    745 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
    746     ctf_file_t *rfp, ctf_id_t rtype)
    747 {
    748 	const void *ltp, *rtp;
    749 	ctf_encoding_t le, re;
    750 	ctf_arinfo_t la, ra;
    751 	uint_t lkind, rkind;
    752 
    753 	if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
    754 		return (1);
    755 
    756 	ltype = ctf_type_resolve(lfp, ltype);
    757 	lkind = ctf_type_kind(lfp, ltype);
    758 
    759 	rtype = ctf_type_resolve(rfp, rtype);
    760 	rkind = ctf_type_kind(rfp, rtype);
    761 
    762 	if (lkind != rkind ||
    763 	    (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL ||
    764 	    (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL ||
    765 	    strcmp(ctf_type_rname(lfp, ltp), ctf_type_rname(rfp, rtp)) != 0)
    766 		return (0);
    767 
    768 	switch (lkind) {
    769 	case CTF_K_INTEGER:
    770 	case CTF_K_FLOAT:
    771 		return (ctf_type_encoding(lfp, ltype, &le) == 0 &&
    772 		    ctf_type_encoding(rfp, rtype, &re) == 0 &&
    773 		    memcmp(&le, &re, sizeof (ctf_encoding_t)) == 0);
    774 	case CTF_K_POINTER:
    775 		return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype),
    776 		    rfp, ctf_type_reference(rfp, rtype)));
    777 	case CTF_K_ARRAY:
    778 		return (ctf_array_info(lfp, ltype, &la) == 0 &&
    779 		    ctf_array_info(rfp, rtype, &ra) == 0 &&
    780 		    la.ctr_nelems == ra.ctr_nelems && ctf_type_compat(
    781 		    lfp, la.ctr_contents, rfp, ra.ctr_contents) &&
    782 		    ctf_type_compat(lfp, la.ctr_index, rfp, ra.ctr_index));
    783 	case CTF_K_STRUCT:
    784 	case CTF_K_UNION:
    785 		return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype));
    786 	case CTF_K_ENUM:
    787 	case CTF_K_FORWARD:
    788 		return (1); /* no other checks required for these type kinds */
    789 	default:
    790 		return (0); /* should not get here since we did a resolve */
    791 	}
    792 }
    793 
    794 static int
    795 _ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, ulong_t off,
    796     ctf_membinfo_t *mip)
    797 {
    798 	ctf_file_t *ofp = fp;
    799 	const void *tp;
    800 	ssize_t size, increment;
    801 	uint_t kind, n, vlen;
    802 
    803 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    804 		return (CTF_ERR); /* errno is set for us */
    805 
    806 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    807 		return (CTF_ERR); /* errno is set for us */
    808 
    809 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
    810 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
    811 
    812 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
    813 		return (ctf_set_errno(ofp, ECTF_NOTSOU));
    814 
    815 	const char *mp = (const char *)((uintptr_t)tp + increment);
    816 
    817 	for (n = vlen; n != 0; n--, mp += increment) {
    818 		const char *name1;
    819 		ulong_t offset;
    820 		uint_t xtype;
    821 
    822 		ctf_get_ctm_info(fp, mp, size, &increment, &xtype, &offset,
    823 		    &name1);
    824 		if (name1[0] == '\0' &&
    825 		    _ctf_member_info(fp, xtype, name, offset + off, mip) == 0)
    826 			return (0);
    827 		if (strcmp(name1, name) == 0) {
    828 			mip->ctm_type = xtype;
    829 			mip->ctm_offset = offset + off;
    830 			return (0);
    831 		}
    832 	}
    833 
    834 	return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
    835 }
    836 
    837 /*
    838  * Return the type and offset for a given member of a STRUCT or UNION.
    839  */
    840 int
    841 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
    842     ctf_membinfo_t *mip)
    843 {
    844 
    845 	return (_ctf_member_info(fp, type, name, 0, mip));
    846 }
    847 
    848 /*
    849  * Return the array type, index, and size information for the specified ARRAY.
    850  */
    851 int
    852 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
    853 {
    854 	ctf_file_t *ofp = fp;
    855 	const void *ap, *tp;
    856 	ssize_t increment;
    857 	uint_t kind;
    858 
    859 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    860 		return (CTF_ERR); /* errno is set for us */
    861 
    862 	ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
    863 
    864 	if (kind != CTF_K_ARRAY)
    865 		return (ctf_set_errno(ofp, ECTF_NOTARRAY));
    866 
    867 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
    868 
    869 	ap = (const void *)((uintptr_t)tp + increment);
    870 	if (fp->ctf_version == CTF_VERSION_2) {
    871 		const struct ctf_array_v2 *ap2 = ap;
    872 
    873 		arp->ctr_contents = ap2->cta_contents;
    874 		arp->ctr_index = ap2->cta_index;
    875 		arp->ctr_nelems = ap2->cta_nelems;
    876 	} else {
    877 		const struct ctf_array_v3 *ap3 = ap;
    878 
    879 		arp->ctr_contents = ap3->cta_contents;
    880 		arp->ctr_index = ap3->cta_index;
    881 		arp->ctr_nelems = ap3->cta_nelems;
    882 	}
    883 
    884 	return (0);
    885 }
    886 
    887 /*
    888  * Convert the specified value to the corresponding enum member name, if a
    889  * matching name can be found.  Otherwise NULL is returned.
    890  */
    891 const char *
    892 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
    893 {
    894 	ctf_file_t *ofp = fp;
    895 	const void *tp;
    896 	const ctf_enum_t *ep;
    897 	ssize_t increment;
    898 	uint_t kind, n, vlen;
    899 
    900 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    901 		return (NULL); /* errno is set for us */
    902 
    903 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    904 		return (NULL); /* errno is set for us */
    905 
    906 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
    907 
    908 	if (kind != CTF_K_ENUM) {
    909 		(void) ctf_set_errno(ofp, ECTF_NOTENUM);
    910 		return (NULL);
    911 	}
    912 
    913 	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
    914 
    915 	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
    916 
    917 	for (n = vlen; n != 0; n--, ep++) {
    918 		if (ep->cte_value == value)
    919 			return (ctf_strptr(fp, ep->cte_name));
    920 	}
    921 
    922 	(void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
    923 	return (NULL);
    924 }
    925 
    926 /*
    927  * Convert the specified enum tag name to the corresponding value, if a
    928  * matching name can be found.  Otherwise CTF_ERR is returned.
    929  */
    930 int
    931 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
    932 {
    933 	ctf_file_t *ofp = fp;
    934 	const void *tp;
    935 	const ctf_enum_t *ep;
    936 	ssize_t size, increment;
    937 	uint_t kind, n, vlen;
    938 
    939 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    940 		return (CTF_ERR); /* errno is set for us */
    941 
    942 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    943 		return (CTF_ERR); /* errno is set for us */
    944 
    945 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
    946 
    947 	if (kind != CTF_K_ENUM) {
    948 		(void) ctf_set_errno(ofp, ECTF_NOTENUM);
    949 		return (CTF_ERR);
    950 	}
    951 
    952 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
    953 
    954 	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
    955 
    956 	for (n = vlen; n != 0; n--, ep++) {
    957 		if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
    958 			if (valp != NULL)
    959 				*valp = ep->cte_value;
    960 			return (0);
    961 		}
    962 	}
    963 
    964 	(void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
    965 	return (CTF_ERR);
    966 }
    967 
    968 /*
    969  * Recursively visit the members of any type.  This function is used as the
    970  * engine for ctf_type_visit, below.  We resolve the input type, recursively
    971  * invoke ourself for each type member if the type is a struct or union, and
    972  * then invoke the callback function on the current type.  If any callback
    973  * returns non-zero, we abort and percolate the error code back up to the top.
    974  */
    975 static int
    976 ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
    977     const char *name, ulong_t offset, int depth)
    978 {
    979 	ctf_id_t otype = type;
    980 	const void *tp;
    981 	ssize_t size, increment;
    982 	uint_t kind, n, vlen;
    983 	int rc;
    984 
    985 	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
    986 		return (CTF_ERR); /* errno is set for us */
    987 
    988 	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
    989 		return (CTF_ERR); /* errno is set for us */
    990 
    991 	if ((rc = func(name, otype, offset, depth, arg)) != 0)
    992 		return (rc);
    993 
    994 	ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
    995 
    996 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
    997 		return (0);
    998 
    999 	(void) ctf_get_ctt_size(fp, tp, &size, &increment);
   1000 
   1001 	const char *mp = (const char *)((uintptr_t)tp + increment);
   1002 	for (n = vlen; n != 0; n--, mp += increment) {
   1003 		const char *xname;
   1004 		ulong_t offset1;
   1005 		uint_t xtype;
   1006 
   1007 		ctf_get_ctm_info(fp, mp, size, &increment, &xtype, &offset1,
   1008 		    &xname);
   1009 		if ((rc = ctf_type_rvisit(fp, xtype, func, arg, xname,
   1010 		    offset + offset1, depth + 1)) != 0)
   1011 			return (rc);
   1012 	}
   1013 
   1014 	return (0);
   1015 }
   1016 
   1017 /*
   1018  * Recursively visit the members of any type.  We pass the name, member
   1019  * type, and offset of each member to the specified callback function.
   1020  */
   1021 int
   1022 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
   1023 {
   1024 	return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));
   1025 }
   1026