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