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.
31 ctf_get_ctt_size(const ctf_file_t
*fp
, const ctf_type_t
*tp
, ssize_t
*sizep
,
34 ssize_t size
, increment
;
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
);
42 increment
= sizeof (ctf_stype_t
);
48 *incrementp
= increment
;
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.
58 ctf_member_iter(ctf_file_t
*fp
, ctf_id_t type
, ctf_member_f
*func
, void *arg
)
62 ssize_t size
, increment
;
66 if ((type
= ctf_type_resolve(fp
, type
)) == CTF_ERR
)
67 return (CTF_ERR
); /* errno is set for us */
69 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
70 return (CTF_ERR
); /* errno is set for us */
72 (void) ctf_get_ctt_size(fp
, tp
, &size
, &increment
);
73 kind
= LCTF_INFO_KIND(fp
, tp
->ctt_info
);
75 if (kind
!= CTF_K_STRUCT
&& kind
!= CTF_K_UNION
)
76 return (ctf_set_errno(ofp
, ECTF_NOTSOU
));
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
);
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
,
90 const ctf_lmember_t
*lmp
= (const ctf_lmember_t
*)
91 ((uintptr_t)tp
+ increment
);
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)
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.
109 ctf_enum_iter(ctf_file_t
*fp
, ctf_id_t type
, ctf_enum_f
*func
, void *arg
)
111 ctf_file_t
*ofp
= fp
;
112 const ctf_type_t
*tp
;
113 const ctf_enum_t
*ep
;
118 if ((type
= ctf_type_resolve(fp
, type
)) == CTF_ERR
)
119 return (CTF_ERR
); /* errno is set for us */
121 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
122 return (CTF_ERR
); /* errno is set for us */
124 if (LCTF_INFO_KIND(fp
, tp
->ctt_info
) != CTF_K_ENUM
)
125 return (ctf_set_errno(ofp
, ECTF_NOTENUM
));
127 (void) ctf_get_ctt_size(fp
, tp
, NULL
, &increment
);
129 ep
= (const ctf_enum_t
*)((uintptr_t)tp
+ increment
);
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)
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.
145 ctf_type_iter(ctf_file_t
*fp
, ctf_type_f
*func
, void *arg
)
147 ctf_id_t id
, max
= fp
->ctf_typemax
;
148 int rc
, child
= (fp
->ctf_flags
& LCTF_CHILD
);
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)
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.
168 ctf_type_resolve(ctf_file_t
*fp
, ctf_id_t type
)
170 ctf_id_t prev
= type
, otype
= type
;
171 ctf_file_t
*ofp
= fp
;
172 const ctf_type_t
*tp
;
174 while ((tp
= ctf_lookup_by_id(&fp
, type
)) != NULL
) {
175 switch (LCTF_INFO_KIND(fp
, tp
->ctt_info
)) {
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
));
193 return (CTF_ERR
); /* errno is set for us */
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.
201 ctf_type_qlname(ctf_file_t
*fp
, ctf_id_t type
, char *buf
, size_t len
,
205 ctf_decl_node_t
*cdp
;
206 ctf_decl_prec_t prec
, lp
, rp
;
210 if (fp
== NULL
&& type
== CTF_ERR
)
211 return (-1); /* simplify caller code by permitting CTF_ERR */
213 ctf_decl_init(&cd
, buf
, len
);
214 ctf_decl_push(&cd
, fp
, type
);
216 if (cd
.cd_err
!= 0) {
218 return (ctf_set_errno(fp
, cd
.cd_err
));
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 (*[])().
228 ptr
= cd
.cd_order
[CTF_PREC_POINTER
] > CTF_PREC_POINTER
;
229 arr
= cd
.cd_order
[CTF_PREC_ARRAY
] > CTF_PREC_ARRAY
;
231 rp
= arr
? CTF_PREC_ARRAY
: ptr
? CTF_PREC_POINTER
: -1;
232 lp
= ptr
? CTF_PREC_POINTER
: arr
? CTF_PREC_ARRAY
: -1;
234 k
= CTF_K_POINTER
; /* avoid leading whitespace (see below) */
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
)) {
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
);
245 if (k
!= CTF_K_POINTER
&& k
!= CTF_K_ARRAY
)
246 ctf_decl_sprintf(&cd
, " ");
249 ctf_decl_sprintf(&cd
, "(");
253 switch (cdp
->cd_kind
) {
258 ctf_decl_sprintf(&cd
, "%s`", qname
);
259 ctf_decl_sprintf(&cd
, "%s", name
);
262 ctf_decl_sprintf(&cd
, "*");
265 ctf_decl_sprintf(&cd
, "[%u]", cdp
->cd_n
);
268 ctf_decl_sprintf(&cd
, "()");
272 ctf_decl_sprintf(&cd
, "struct ");
274 ctf_decl_sprintf(&cd
, "%s`", qname
);
275 ctf_decl_sprintf(&cd
, "%s", name
);
278 ctf_decl_sprintf(&cd
, "union ");
280 ctf_decl_sprintf(&cd
, "%s`", qname
);
281 ctf_decl_sprintf(&cd
, "%s", name
);
284 ctf_decl_sprintf(&cd
, "enum ");
286 ctf_decl_sprintf(&cd
, "%s`", qname
);
287 ctf_decl_sprintf(&cd
, "%s", name
);
290 ctf_decl_sprintf(&cd
, "volatile");
293 ctf_decl_sprintf(&cd
, "const");
296 ctf_decl_sprintf(&cd
, "restrict");
304 ctf_decl_sprintf(&cd
, ")");
307 if (cd
.cd_len
>= len
)
308 (void) ctf_set_errno(fp
, ECTF_NAMELEN
);
315 ctf_type_lname(ctf_file_t
*fp
, ctf_id_t type
, char *buf
, size_t len
)
317 return (ctf_type_qlname(fp
, type
, buf
, len
, NULL
));
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.
325 ctf_type_name(ctf_file_t
*fp
, ctf_id_t type
, char *buf
, size_t len
)
327 ssize_t rv
= ctf_type_qlname(fp
, type
, buf
, len
, NULL
);
328 return (rv
>= 0 && rv
< len
? buf
: NULL
);
332 ctf_type_qname(ctf_file_t
*fp
, ctf_id_t type
, char *buf
, size_t len
,
335 ssize_t rv
= ctf_type_qlname(fp
, type
, buf
, len
, qname
);
336 return (rv
>= 0 && rv
< len
? buf
: NULL
);
341 * Resolve the type down to a base type node, and then return the size
342 * of the type storage in bytes.
345 ctf_type_size(ctf_file_t
*fp
, ctf_id_t type
)
347 const ctf_type_t
*tp
;
351 if ((type
= ctf_type_resolve(fp
, type
)) == CTF_ERR
)
352 return (-1); /* errno is set for us */
354 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
355 return (-1); /* errno is set for us */
357 switch (LCTF_INFO_KIND(fp
, tp
->ctt_info
)) {
359 return (fp
->ctf_dmodel
->ctd_pointer
);
362 return (0); /* function size is only known by symtab */
365 return (fp
->ctf_dmodel
->ctd_int
);
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.
375 if ((size
= ctf_get_ctt_size(fp
, tp
, NULL
, NULL
)) > 0)
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 */
382 return (size
* ar
.ctr_nelems
);
385 return (ctf_get_ctt_size(fp
, tp
, NULL
, NULL
));
390 * Resolve the type down to a base type node, and then return the alignment
391 * needed for the type storage in bytes.
394 ctf_type_align(ctf_file_t
*fp
, ctf_id_t type
)
396 const ctf_type_t
*tp
;
399 if ((type
= ctf_type_resolve(fp
, type
)) == CTF_ERR
)
400 return (-1); /* errno is set for us */
402 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
403 return (-1); /* errno is set for us */
405 switch (LCTF_INFO_KIND(fp
, tp
->ctt_info
)) {
408 return (fp
->ctf_dmodel
->ctd_pointer
);
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
));
417 uint_t n
= LCTF_INFO_VLEN(fp
, tp
->ctt_info
);
418 ssize_t size
, increment
;
422 (void) ctf_get_ctt_size(fp
, tp
, &size
, &increment
);
423 vmp
= (uchar_t
*)tp
+ increment
;
425 if (LCTF_INFO_KIND(fp
, tp
->ctt_info
) == CTF_K_STRUCT
)
426 n
= MIN(n
, 1); /* only use first member for structs */
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
);
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
);
447 return (fp
->ctf_dmodel
->ctd_int
);
450 return (ctf_get_ctt_size(fp
, tp
, NULL
, NULL
));
455 * Return the kind (CTF_K_* constant) for the specified type ID.
458 ctf_type_kind(ctf_file_t
*fp
, ctf_id_t type
)
460 const ctf_type_t
*tp
;
462 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
463 return (CTF_ERR
); /* errno is set for us */
465 return (LCTF_INFO_KIND(fp
, tp
->ctt_info
));
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.
473 ctf_type_reference(ctf_file_t
*fp
, ctf_id_t type
)
475 ctf_file_t
*ofp
= fp
;
476 const ctf_type_t
*tp
;
478 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
479 return (CTF_ERR
); /* errno is set for us */
481 switch (LCTF_INFO_KIND(fp
, tp
->ctt_info
)) {
487 return (tp
->ctt_type
);
489 return (ctf_set_errno(ofp
, ECTF_NOTREF
));
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.
501 ctf_type_pointer(ctf_file_t
*fp
, ctf_id_t type
)
503 ctf_file_t
*ofp
= fp
;
506 if (ctf_lookup_by_id(&fp
, type
) == NULL
)
507 return (CTF_ERR
); /* errno is set for us */
509 if ((ntype
= fp
->ctf_ptrtab
[CTF_TYPE_TO_INDEX(type
)]) != 0)
510 return (CTF_INDEX_TO_TYPE(ntype
, (fp
->ctf_flags
& LCTF_CHILD
)));
512 if ((type
= ctf_type_resolve(fp
, type
)) == CTF_ERR
)
513 return (ctf_set_errno(ofp
, ECTF_NOTYPE
));
515 if (ctf_lookup_by_id(&fp
, type
) == NULL
)
516 return (ctf_set_errno(ofp
, ECTF_NOTYPE
));
518 if ((ntype
= fp
->ctf_ptrtab
[CTF_TYPE_TO_INDEX(type
)]) != 0)
519 return (CTF_INDEX_TO_TYPE(ntype
, (fp
->ctf_flags
& LCTF_CHILD
)));
521 return (ctf_set_errno(ofp
, ECTF_NOTYPE
));
525 * Return the encoding for the specified INTEGER or FLOAT.
528 ctf_type_encoding(ctf_file_t
*fp
, ctf_id_t type
, ctf_encoding_t
*ep
)
530 ctf_file_t
*ofp
= fp
;
531 const ctf_type_t
*tp
;
535 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
536 return (CTF_ERR
); /* errno is set for us */
538 (void) ctf_get_ctt_size(fp
, tp
, NULL
, &increment
);
540 switch (LCTF_INFO_KIND(fp
, tp
->ctt_info
)) {
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
);
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
);
554 return (ctf_set_errno(ofp
, ECTF_NOTINTFP
));
561 ctf_type_cmp(ctf_file_t
*lfp
, ctf_id_t ltype
, ctf_file_t
*rfp
, ctf_id_t rtype
)
567 else if (ltype
> rtype
)
575 if (CTF_TYPE_ISPARENT(ltype
) && lfp
->ctf_parent
!= NULL
)
576 lfp
= lfp
->ctf_parent
;
578 if (CTF_TYPE_ISPARENT(rtype
) && rfp
->ctf_parent
!= NULL
)
579 rfp
= rfp
->ctf_parent
;
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.
597 ctf_type_compat(ctf_file_t
*lfp
, ctf_id_t ltype
,
598 ctf_file_t
*rfp
, ctf_id_t rtype
)
600 const ctf_type_t
*ltp
, *rtp
;
601 ctf_encoding_t le
, re
;
605 if (ctf_type_cmp(lfp
, ltype
, rfp
, rtype
) == 0)
608 ltype
= ctf_type_resolve(lfp
, ltype
);
609 lkind
= ctf_type_kind(lfp
, ltype
);
611 rtype
= ctf_type_resolve(rfp
, rtype
);
612 rkind
= ctf_type_kind(rfp
, rtype
);
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)
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);
628 return (ctf_type_compat(lfp
, ctf_type_reference(lfp
, ltype
),
629 rfp
, ctf_type_reference(rfp
, rtype
)));
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
));
638 return (ctf_type_size(lfp
, ltype
) == ctf_type_size(rfp
, rtype
));
641 return (1); /* no other checks required for these type kinds */
643 return (0); /* should not get here since we did a resolve */
648 * Return the type and offset for a given member of a STRUCT or UNION.
651 ctf_member_info(ctf_file_t
*fp
, ctf_id_t type
, const char *name
,
654 ctf_file_t
*ofp
= fp
;
655 const ctf_type_t
*tp
;
656 ssize_t size
, increment
;
659 if ((type
= ctf_type_resolve(fp
, type
)) == CTF_ERR
)
660 return (CTF_ERR
); /* errno is set for us */
662 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
663 return (CTF_ERR
); /* errno is set for us */
665 (void) ctf_get_ctt_size(fp
, tp
, &size
, &increment
);
666 kind
= LCTF_INFO_KIND(fp
, tp
->ctt_info
);
668 if (kind
!= CTF_K_STRUCT
&& kind
!= CTF_K_UNION
)
669 return (ctf_set_errno(ofp
, ECTF_NOTSOU
));
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
);
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
;
683 const ctf_lmember_t
*lmp
= (const ctf_lmember_t
*)
684 ((uintptr_t)tp
+ increment
);
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
);
695 return (ctf_set_errno(ofp
, ECTF_NOMEMBNAM
));
699 * Return the array type, index, and size information for the specified ARRAY.
702 ctf_array_info(ctf_file_t
*fp
, ctf_id_t type
, ctf_arinfo_t
*arp
)
704 ctf_file_t
*ofp
= fp
;
705 const ctf_type_t
*tp
;
706 const ctf_array_t
*ap
;
709 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
710 return (CTF_ERR
); /* errno is set for us */
712 if (LCTF_INFO_KIND(fp
, tp
->ctt_info
) != CTF_K_ARRAY
)
713 return (ctf_set_errno(ofp
, ECTF_NOTARRAY
));
715 (void) ctf_get_ctt_size(fp
, tp
, NULL
, &increment
);
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
;
726 * Convert the specified value to the corresponding enum member name, if a
727 * matching name can be found. Otherwise NULL is returned.
730 ctf_enum_name(ctf_file_t
*fp
, ctf_id_t type
, int value
)
732 ctf_file_t
*ofp
= fp
;
733 const ctf_type_t
*tp
;
734 const ctf_enum_t
*ep
;
738 if ((type
= ctf_type_resolve(fp
, type
)) == CTF_ERR
)
739 return (NULL
); /* errno is set for us */
741 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
742 return (NULL
); /* errno is set for us */
744 if (LCTF_INFO_KIND(fp
, tp
->ctt_info
) != CTF_K_ENUM
) {
745 (void) ctf_set_errno(ofp
, ECTF_NOTENUM
);
749 (void) ctf_get_ctt_size(fp
, tp
, NULL
, &increment
);
751 ep
= (const ctf_enum_t
*)((uintptr_t)tp
+ increment
);
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
));
758 (void) ctf_set_errno(ofp
, ECTF_NOENUMNAM
);
763 * Convert the specified enum tag name to the corresponding value, if a
764 * matching name can be found. Otherwise CTF_ERR is returned.
767 ctf_enum_value(ctf_file_t
*fp
, ctf_id_t type
, const char *name
, int *valp
)
769 ctf_file_t
*ofp
= fp
;
770 const ctf_type_t
*tp
;
771 const ctf_enum_t
*ep
;
772 ssize_t size
, increment
;
775 if ((type
= ctf_type_resolve(fp
, type
)) == CTF_ERR
)
776 return (CTF_ERR
); /* errno is set for us */
778 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
779 return (CTF_ERR
); /* errno is set for us */
781 if (LCTF_INFO_KIND(fp
, tp
->ctt_info
) != CTF_K_ENUM
) {
782 (void) ctf_set_errno(ofp
, ECTF_NOTENUM
);
786 (void) ctf_get_ctt_size(fp
, tp
, &size
, &increment
);
788 ep
= (const ctf_enum_t
*)((uintptr_t)tp
+ increment
);
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) {
793 *valp
= ep
->cte_value
;
798 (void) ctf_set_errno(ofp
, ECTF_NOENUMNAM
);
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.
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
)
813 ctf_id_t otype
= type
;
814 const ctf_type_t
*tp
;
815 ssize_t size
, increment
;
819 if ((type
= ctf_type_resolve(fp
, type
)) == CTF_ERR
)
820 return (CTF_ERR
); /* errno is set for us */
822 if ((tp
= ctf_lookup_by_id(&fp
, type
)) == NULL
)
823 return (CTF_ERR
); /* errno is set for us */
825 if ((rc
= func(name
, otype
, offset
, depth
, arg
)) != 0)
828 kind
= LCTF_INFO_KIND(fp
, tp
->ctt_info
);
830 if (kind
!= CTF_K_STRUCT
&& kind
!= CTF_K_UNION
)
833 (void) ctf_get_ctt_size(fp
, tp
, &size
, &increment
);
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
);
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)
847 const ctf_lmember_t
*lmp
= (const ctf_lmember_t
*)
848 ((uintptr_t)tp
+ increment
);
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
),
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.
867 ctf_type_visit(ctf_file_t
*fp
, ctf_id_t type
, ctf_visit_f
*func
, void *arg
)
869 return (ctf_type_rvisit(fp
, type
, func
, arg
, "", 0, 0));