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
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.
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]
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #pragma ident "%Z%%M% %I% %E% SMI"
33 ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep,
36 ssize_t size, increment;
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);
44 increment = sizeof (ctf_stype_t);
50 *incrementp = increment;
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.
60 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
64 ssize_t size, increment;
68 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
69 return (CTF_ERR); /* errno is set for us */
71 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
72 return (CTF_ERR); /* errno is set for us */
74 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
75 kind = LCTF_INFO_KIND(fp, tp->ctt_info);
77 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
78 return (ctf_set_errno(ofp, ECTF_NOTSOU));
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);
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,
92 const ctf_lmember_t *lmp = (const ctf_lmember_t *)
93 ((uintptr_t)tp + increment);
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)
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.
111 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
113 ctf_file_t *ofp = fp;
114 const ctf_type_t *tp;
115 const ctf_enum_t *ep;
120 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
121 return (CTF_ERR); /* errno is set for us */
123 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
124 return (CTF_ERR); /* errno is set for us */
126 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM)
127 return (ctf_set_errno(ofp, ECTF_NOTENUM));
129 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
131 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
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)
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.
147 ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
149 ctf_id_t id, max = fp->ctf_typemax;
150 int rc, child = (fp->ctf_flags & LCTF_CHILD);
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)
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.
170 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
172 ctf_id_t prev = type, otype = type;
173 ctf_file_t *ofp = fp;
174 const ctf_type_t *tp;
176 while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
177 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
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));
195 return (CTF_ERR); /* errno is set for us */
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.
203 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
206 ctf_decl_node_t *cdp;
207 ctf_decl_prec_t prec, lp, rp;
211 if (fp == NULL && type == CTF_ERR)
212 return (-1); /* simplify caller code by permitting CTF_ERR */
214 ctf_decl_init(&cd, buf, len);
215 ctf_decl_push(&cd, fp, type);
217 if (cd.cd_err != 0) {
219 return (ctf_set_errno(fp, cd.cd_err));
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 (*[])().
229 ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
230 arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
232 rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
233 lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
235 k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
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)) {
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);
246 if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
247 ctf_decl_sprintf(&cd, " ");
250 ctf_decl_sprintf(&cd, "(");
254 switch (cdp->cd_kind) {
258 ctf_decl_sprintf(&cd, "%s", name);
261 ctf_decl_sprintf(&cd, "*");
264 ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
267 ctf_decl_sprintf(&cd, "()");
271 ctf_decl_sprintf(&cd, "struct %s", name);
274 ctf_decl_sprintf(&cd, "union %s", name);
277 ctf_decl_sprintf(&cd, "enum %s", name);
280 ctf_decl_sprintf(&cd, "volatile");
283 ctf_decl_sprintf(&cd, "const");
286 ctf_decl_sprintf(&cd, "restrict");
294 ctf_decl_sprintf(&cd, ")");
297 if (cd.cd_len >= len)
298 (void) ctf_set_errno(fp, ECTF_NAMELEN);
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.
309 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
311 ssize_t rv = ctf_type_lname(fp, type, buf, len);
312 return (rv >= 0 && rv < len ? buf : NULL);
316 * Resolve the type down to a base type node, and then return the size
317 * of the type storage in bytes.
320 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
322 const ctf_type_t *tp;
326 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
327 return (-1); /* errno is set for us */
329 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
330 return (-1); /* errno is set for us */
332 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
334 return (fp->ctf_dmodel->ctd_pointer);
337 return (0); /* function size is only known by symtab */
340 return (fp->ctf_dmodel->ctd_int);
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.
350 if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
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 */
357 return (size * ar.ctr_nelems);
360 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
365 * Resolve the type down to a base type node, and then return the alignment
366 * needed for the type storage in bytes.
369 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
371 const ctf_type_t *tp;
374 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
375 return (-1); /* errno is set for us */
377 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
378 return (-1); /* errno is set for us */
380 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
383 return (fp->ctf_dmodel->ctd_pointer);
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));
392 uint_t n = LCTF_INFO_VLEN(fp, tp->ctt_info);
393 ssize_t size, increment;
397 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
398 vmp = (uchar_t *)tp + increment;
400 if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_STRUCT)
401 n = MIN(n, 1); /* only use first member for structs */
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);
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);
422 return (fp->ctf_dmodel->ctd_int);
425 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
430 * Return the kind (CTF_K_* constant) for the specified type ID.
433 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
435 const ctf_type_t *tp;
437 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
438 return (CTF_ERR); /* errno is set for us */
440 return (LCTF_INFO_KIND(fp, tp->ctt_info));
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.
448 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
450 ctf_file_t *ofp = fp;
451 const ctf_type_t *tp;
453 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
454 return (CTF_ERR); /* errno is set for us */
456 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
462 return (tp->ctt_type);
464 return (ctf_set_errno(ofp, ECTF_NOTREF));
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.
476 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
478 ctf_file_t *ofp = fp;
481 if (ctf_lookup_by_id(&fp, type) == NULL)
482 return (CTF_ERR); /* errno is set for us */
484 if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
485 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
487 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
488 return (ctf_set_errno(ofp, ECTF_NOTYPE));
490 if (ctf_lookup_by_id(&fp, type) == NULL)
491 return (ctf_set_errno(ofp, ECTF_NOTYPE));
493 if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
494 return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
496 return (ctf_set_errno(ofp, ECTF_NOTYPE));
500 * Return the encoding for the specified INTEGER or FLOAT.
503 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
505 ctf_file_t *ofp = fp;
506 const ctf_type_t *tp;
510 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
511 return (CTF_ERR); /* errno is set for us */
513 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
515 switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
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);
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);
529 return (ctf_set_errno(ofp, ECTF_NOTINTFP));
536 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
542 else if (ltype > rtype)
550 if (CTF_TYPE_ISPARENT(ltype) && lfp->ctf_parent != NULL)
551 lfp = lfp->ctf_parent;
553 if (CTF_TYPE_ISPARENT(rtype) && rfp->ctf_parent != NULL)
554 rfp = rfp->ctf_parent;
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.
572 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
573 ctf_file_t *rfp, ctf_id_t rtype)
575 const ctf_type_t *ltp, *rtp;
576 ctf_encoding_t le, re;
580 if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
583 ltype = ctf_type_resolve(lfp, ltype);
584 lkind = ctf_type_kind(lfp, ltype);
586 rtype = ctf_type_resolve(rfp, rtype);
587 rkind = ctf_type_kind(rfp, rtype);
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)
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);
603 return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype),
604 rfp, ctf_type_reference(rfp, rtype)));
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));
613 return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype));
616 return (1); /* no other checks required for these type kinds */
618 return (0); /* should not get here since we did a resolve */
623 * Return the type and offset for a given member of a STRUCT or UNION.
626 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
629 ctf_file_t *ofp = fp;
630 const ctf_type_t *tp;
631 ssize_t size, increment;
634 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
635 return (CTF_ERR); /* errno is set for us */
637 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
638 return (CTF_ERR); /* errno is set for us */
640 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
641 kind = LCTF_INFO_KIND(fp, tp->ctt_info);
643 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
644 return (ctf_set_errno(ofp, ECTF_NOTSOU));
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);
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;
658 const ctf_lmember_t *lmp = (const ctf_lmember_t *)
659 ((uintptr_t)tp + increment);
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);
670 return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
674 * Return the array type, index, and size information for the specified ARRAY.
677 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
679 ctf_file_t *ofp = fp;
680 const ctf_type_t *tp;
681 const ctf_array_t *ap;
684 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
685 return (CTF_ERR); /* errno is set for us */
687 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ARRAY)
688 return (ctf_set_errno(ofp, ECTF_NOTARRAY));
690 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
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;
701 * Convert the specified value to the corresponding enum member name, if a
702 * matching name can be found. Otherwise NULL is returned.
705 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
707 ctf_file_t *ofp = fp;
708 const ctf_type_t *tp;
709 const ctf_enum_t *ep;
713 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
714 return (NULL); /* errno is set for us */
716 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
717 return (NULL); /* errno is set for us */
719 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
720 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
724 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
726 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
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));
733 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
738 * Convert the specified enum tag name to the corresponding value, if a
739 * matching name can be found. Otherwise CTF_ERR is returned.
742 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
744 ctf_file_t *ofp = fp;
745 const ctf_type_t *tp;
746 const ctf_enum_t *ep;
747 ssize_t size, increment;
750 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
751 return (CTF_ERR); /* errno is set for us */
753 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
754 return (CTF_ERR); /* errno is set for us */
756 if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
757 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
761 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
763 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
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) {
768 *valp = ep->cte_value;
773 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
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.
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)
788 ctf_id_t otype = type;
789 const ctf_type_t *tp;
790 ssize_t size, increment;
794 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
795 return (CTF_ERR); /* errno is set for us */
797 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
798 return (CTF_ERR); /* errno is set for us */
800 if ((rc = func(name, otype, offset, depth, arg)) != 0)
803 kind = LCTF_INFO_KIND(fp, tp->ctt_info);
805 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
808 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
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);
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)
822 const ctf_lmember_t *lmp = (const ctf_lmember_t *)
823 ((uintptr_t)tp + increment);
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),
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.
842 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
844 return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));