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