1 /* Type handling functions.
2 Copyright (C) 2019 Free Software Foundation, Inc.
4 This file is part of libctf.
6 libctf is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not see
18 <http://www.gnu.org/licenses/>. */
23 /* Determine whether a type is a parent or a child. */
26 ctf_type_isparent (ctf_file_t
*fp
, ctf_id_t id
)
28 return (LCTF_TYPE_ISPARENT (fp
, id
));
32 ctf_type_ischild (ctf_file_t
* fp
, ctf_id_t id
)
34 return (LCTF_TYPE_ISCHILD (fp
, id
));
37 /* Iterate over the members of a STRUCT or UNION. We pass the name, member
38 type, and offset of each member to the specified callback function. */
41 ctf_member_iter (ctf_file_t
*fp
, ctf_id_t type
, ctf_member_f
*func
, void *arg
)
45 ssize_t size
, increment
;
49 if ((type
= ctf_type_resolve (fp
, type
)) == CTF_ERR
)
50 return -1; /* errno is set for us. */
52 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
53 return -1; /* errno is set for us. */
55 (void) ctf_get_ctt_size (fp
, tp
, &size
, &increment
);
56 kind
= LCTF_INFO_KIND (fp
, tp
->ctt_info
);
58 if (kind
!= CTF_K_STRUCT
&& kind
!= CTF_K_UNION
)
59 return (ctf_set_errno (ofp
, ECTF_NOTSOU
));
61 if (size
< CTF_LSTRUCT_THRESH
)
63 const ctf_member_t
*mp
= (const ctf_member_t
*) ((uintptr_t) tp
+
66 for (n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
); n
!= 0; n
--, mp
++)
68 const char *name
= ctf_strptr (fp
, mp
->ctm_name
);
69 if ((rc
= func (name
, mp
->ctm_type
, mp
->ctm_offset
, arg
)) != 0)
76 const ctf_lmember_t
*lmp
= (const ctf_lmember_t
*) ((uintptr_t) tp
+
79 for (n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
); n
!= 0; n
--, lmp
++)
81 const char *name
= ctf_strptr (fp
, lmp
->ctlm_name
);
82 if ((rc
= func (name
, lmp
->ctlm_type
,
83 (unsigned long) CTF_LMEM_OFFSET (lmp
), arg
)) != 0)
91 /* Iterate over the members of an ENUM. We pass the string name and associated
92 integer value of each enum element to the specified callback function. */
95 ctf_enum_iter (ctf_file_t
*fp
, ctf_id_t type
, ctf_enum_f
*func
, void *arg
)
104 if ((type
= ctf_type_resolve_unsliced (fp
, type
)) == CTF_ERR
)
105 return -1; /* errno is set for us. */
107 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
108 return -1; /* errno is set for us. */
110 if (LCTF_INFO_KIND (fp
, tp
->ctt_info
) != CTF_K_ENUM
)
111 return (ctf_set_errno (ofp
, ECTF_NOTENUM
));
113 (void) ctf_get_ctt_size (fp
, tp
, NULL
, &increment
);
115 ep
= (const ctf_enum_t
*) ((uintptr_t) tp
+ increment
);
117 for (n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
); n
!= 0; n
--, ep
++)
119 const char *name
= ctf_strptr (fp
, ep
->cte_name
);
120 if ((rc
= func (name
, ep
->cte_value
, arg
)) != 0)
127 /* Iterate over every root (user-visible) type in the given CTF container.
128 We pass the type ID of each type to the specified callback function. */
131 ctf_type_iter (ctf_file_t
*fp
, ctf_type_f
*func
, void *arg
)
133 ctf_id_t id
, max
= fp
->ctf_typemax
;
134 int rc
, child
= (fp
->ctf_flags
& LCTF_CHILD
);
136 for (id
= 1; id
<= max
; id
++)
138 const ctf_type_t
*tp
= LCTF_INDEX_TO_TYPEPTR (fp
, id
);
139 if (LCTF_INFO_ISROOT (fp
, tp
->ctt_info
)
140 && (rc
= func (LCTF_INDEX_TO_TYPE (fp
, id
, child
), arg
)) != 0)
147 /* Iterate over every variable in the given CTF container, in arbitrary order.
148 We pass the name of each variable to the specified callback function. */
151 ctf_variable_iter (ctf_file_t
*fp
, ctf_variable_f
*func
, void *arg
)
156 if ((fp
->ctf_flags
& LCTF_CHILD
) && (fp
->ctf_parent
== NULL
))
157 return ECTF_NOPARENT
;
159 for (i
= 0; i
< fp
->ctf_nvars
; i
++)
160 if ((rc
= func (ctf_strptr (fp
, fp
->ctf_vars
[i
].ctv_name
),
161 fp
->ctf_vars
[i
].ctv_type
, arg
)) != 0)
167 /* Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
168 RESTRICT nodes until we reach a "base" type node. This is useful when
169 we want to follow a type ID to a node that has members or a size. To guard
170 against infinite loops, we implement simplified cycle detection and check
171 each link against itself, the previous node, and the topmost node.
173 Does not drill down through slices to their contained type. */
176 ctf_type_resolve (ctf_file_t
*fp
, ctf_id_t type
)
178 ctf_id_t prev
= type
, otype
= type
;
179 ctf_file_t
*ofp
= fp
;
180 const ctf_type_t
*tp
;
182 while ((tp
= ctf_lookup_by_id (&fp
, type
)) != NULL
)
184 switch (LCTF_INFO_KIND (fp
, tp
->ctt_info
))
190 if (tp
->ctt_type
== type
|| tp
->ctt_type
== otype
191 || tp
->ctt_type
== prev
)
193 ctf_dprintf ("type %ld cycle detected\n", otype
);
194 return (ctf_set_errno (ofp
, ECTF_CORRUPT
));
204 return CTF_ERR
; /* errno is set for us. */
207 /* Like ctf_type_resolve(), but traverse down through slices to their contained
211 ctf_type_resolve_unsliced (ctf_file_t
*fp
, ctf_id_t type
)
213 const ctf_type_t
*tp
;
215 if ((type
= ctf_type_resolve (fp
, type
)) == CTF_ERR
)
218 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
219 return CTF_ERR
; /* errno is set for us. */
221 if ((LCTF_INFO_KIND (fp
, tp
->ctt_info
)) == CTF_K_SLICE
)
222 return ctf_type_reference (fp
, type
);
226 /* Lookup the given type ID and return its name as a new dynamcally-allocated
230 ctf_type_aname (ctf_file_t
*fp
, ctf_id_t type
)
233 ctf_decl_node_t
*cdp
;
234 ctf_decl_prec_t prec
, lp
, rp
;
239 if (fp
== NULL
&& type
== CTF_ERR
)
240 return NULL
; /* Simplify caller code by permitting CTF_ERR. */
243 ctf_decl_push (&cd
, fp
, type
);
248 ctf_set_errno (fp
, cd
.cd_err
);
252 /* If the type graph's order conflicts with lexical precedence order
253 for pointers or arrays, then we need to surround the declarations at
254 the corresponding lexical precedence with parentheses. This can
255 result in either a parenthesized pointer (*) as in int (*)() or
256 int (*)[], or in a parenthesized pointer and array as in int (*[])(). */
258 ptr
= cd
.cd_order
[CTF_PREC_POINTER
] > CTF_PREC_POINTER
;
259 arr
= cd
.cd_order
[CTF_PREC_ARRAY
] > CTF_PREC_ARRAY
;
261 rp
= arr
? CTF_PREC_ARRAY
: ptr
? CTF_PREC_POINTER
: -1;
262 lp
= ptr
? CTF_PREC_POINTER
: arr
? CTF_PREC_ARRAY
: -1;
264 k
= CTF_K_POINTER
; /* Avoid leading whitespace (see below). */
266 for (prec
= CTF_PREC_BASE
; prec
< CTF_PREC_MAX
; prec
++)
268 for (cdp
= ctf_list_next (&cd
.cd_nodes
[prec
]);
269 cdp
!= NULL
; cdp
= ctf_list_next (cdp
))
271 ctf_file_t
*rfp
= fp
;
272 const ctf_type_t
*tp
= ctf_lookup_by_id (&rfp
, cdp
->cd_type
);
273 const char *name
= ctf_strptr (rfp
, tp
->ctt_name
);
275 if (k
!= CTF_K_POINTER
&& k
!= CTF_K_ARRAY
)
276 ctf_decl_sprintf (&cd
, " ");
280 ctf_decl_sprintf (&cd
, "(");
284 switch (cdp
->cd_kind
)
289 ctf_decl_sprintf (&cd
, "%s", name
);
292 ctf_decl_sprintf (&cd
, "*");
295 ctf_decl_sprintf (&cd
, "[%u]", cdp
->cd_n
);
298 ctf_decl_sprintf (&cd
, "()");
302 ctf_decl_sprintf (&cd
, "struct %s", name
);
305 ctf_decl_sprintf (&cd
, "union %s", name
);
308 ctf_decl_sprintf (&cd
, "enum %s", name
);
311 ctf_decl_sprintf (&cd
, "volatile");
314 ctf_decl_sprintf (&cd
, "const");
317 ctf_decl_sprintf (&cd
, "restrict");
320 /* No representation: just changes encoding of contained type,
321 which is not in any case printed. Skip it. */
329 ctf_decl_sprintf (&cd
, ")");
333 (void) ctf_set_errno (fp
, ENOMEM
);
335 buf
= ctf_decl_buf (&cd
);
341 /* Lookup the given type ID and print a string name for it into buf. Return
342 the actual number of bytes (not including \0) needed to format the name. */
345 ctf_type_lname (ctf_file_t
*fp
, ctf_id_t type
, char *buf
, size_t len
)
347 char *str
= ctf_type_aname (fp
, type
);
348 size_t slen
= strlen (str
);
351 return CTF_ERR
; /* errno is set for us */
353 snprintf (buf
, len
, "%s", str
);
357 (void) ctf_set_errno (fp
, ECTF_NAMELEN
);
362 /* Lookup the given type ID and print a string name for it into buf. If buf
363 is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us. */
366 ctf_type_name (ctf_file_t
*fp
, ctf_id_t type
, char *buf
, size_t len
)
368 ssize_t rv
= ctf_type_lname (fp
, type
, buf
, len
);
369 return (rv
>= 0 && (size_t) rv
< len
? buf
: NULL
);
372 /* Resolve the type down to a base type node, and then return the size
373 of the type storage in bytes. */
376 ctf_type_size (ctf_file_t
*fp
, ctf_id_t type
)
378 const ctf_type_t
*tp
;
382 if ((type
= ctf_type_resolve (fp
, type
)) == CTF_ERR
)
383 return -1; /* errno is set for us. */
385 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
386 return -1; /* errno is set for us. */
388 switch (LCTF_INFO_KIND (fp
, tp
->ctt_info
))
391 return fp
->ctf_dmodel
->ctd_pointer
;
394 return 0; /* Function size is only known by symtab. */
397 return fp
->ctf_dmodel
->ctd_int
;
400 /* ctf_add_array() does not directly encode the element size, but
401 requires the user to multiply to determine the element size.
403 If ctf_get_ctt_size() returns nonzero, then use the recorded
406 if ((size
= ctf_get_ctt_size (fp
, tp
, NULL
, NULL
)) > 0)
409 if (ctf_array_info (fp
, type
, &ar
) < 0
410 || (size
= ctf_type_size (fp
, ar
.ctr_contents
)) < 0)
411 return -1; /* errno is set for us. */
413 return size
* ar
.ctr_nelems
;
415 default: /* including slices of enums, etc */
416 return (ctf_get_ctt_size (fp
, tp
, NULL
, NULL
));
420 /* Resolve the type down to a base type node, and then return the alignment
421 needed for the type storage in bytes.
423 XXX may need arch-dependent attention. */
426 ctf_type_align (ctf_file_t
*fp
, ctf_id_t type
)
428 const ctf_type_t
*tp
;
429 ctf_file_t
*ofp
= fp
;
432 if ((type
= ctf_type_resolve (fp
, type
)) == CTF_ERR
)
433 return -1; /* errno is set for us. */
435 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
436 return -1; /* errno is set for us. */
438 kind
= LCTF_INFO_KIND (fp
, tp
->ctt_info
);
443 return fp
->ctf_dmodel
->ctd_pointer
;
448 if (ctf_array_info (fp
, type
, &r
) < 0)
449 return -1; /* errno is set for us. */
450 return (ctf_type_align (fp
, r
.ctr_contents
));
459 if ((dtd
= ctf_dynamic_type (ofp
, type
)) == NULL
)
461 uint32_t n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
);
462 ssize_t size
, increment
;
465 (void) ctf_get_ctt_size (fp
, tp
, &size
, &increment
);
466 vmp
= (unsigned char *) tp
+ increment
;
468 if (kind
== CTF_K_STRUCT
)
469 n
= MIN (n
, 1); /* Only use first member for structs. */
471 if (size
< CTF_LSTRUCT_THRESH
)
473 const ctf_member_t
*mp
= vmp
;
474 for (; n
!= 0; n
--, mp
++)
476 ssize_t am
= ctf_type_align (fp
, mp
->ctm_type
);
477 align
= MAX (align
, (size_t) am
);
482 const ctf_lmember_t
*lmp
= vmp
;
483 for (; n
!= 0; n
--, lmp
++)
485 ssize_t am
= ctf_type_align (fp
, lmp
->ctlm_type
);
486 align
= MAX (align
, (size_t) am
);
494 for (dmd
= ctf_list_next (&dtd
->dtd_u
.dtu_members
);
495 dmd
!= NULL
; dmd
= ctf_list_next (dmd
))
497 ssize_t am
= ctf_type_align (fp
, dmd
->dmd_type
);
498 align
= MAX (align
, (size_t) am
);
499 if (kind
== CTF_K_STRUCT
)
508 return fp
->ctf_dmodel
->ctd_int
;
510 default: /* including slices of enums, etc */
511 return (ctf_get_ctt_size (fp
, tp
, NULL
, NULL
));
515 /* Return the kind (CTF_K_* constant) for the specified type ID. */
518 ctf_type_kind_unsliced (ctf_file_t
*fp
, ctf_id_t type
)
520 const ctf_type_t
*tp
;
522 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
523 return -1; /* errno is set for us. */
525 return (LCTF_INFO_KIND (fp
, tp
->ctt_info
));
528 /* Return the kind (CTF_K_* constant) for the specified type ID.
529 Slices are considered to be of the same kind as the type sliced. */
532 ctf_type_kind (ctf_file_t
*fp
, ctf_id_t type
)
536 if ((kind
= ctf_type_kind_unsliced (fp
, type
)) < 0)
539 if (kind
== CTF_K_SLICE
)
541 if ((type
= ctf_type_reference (fp
, type
)) == CTF_ERR
)
543 kind
= ctf_type_kind_unsliced (fp
, type
);
549 /* If the type is one that directly references another type (such as POINTER),
550 then return the ID of the type to which it refers. */
553 ctf_type_reference (ctf_file_t
*fp
, ctf_id_t type
)
555 ctf_file_t
*ofp
= fp
;
556 const ctf_type_t
*tp
;
558 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
559 return CTF_ERR
; /* errno is set for us. */
561 switch (LCTF_INFO_KIND (fp
, tp
->ctt_info
))
569 /* Slices store their type in an unusual place. */
572 const ctf_slice_t
*sp
;
574 (void) ctf_get_ctt_size (fp
, tp
, NULL
, &increment
);
575 sp
= (const ctf_slice_t
*) ((uintptr_t) tp
+ increment
);
579 return (ctf_set_errno (ofp
, ECTF_NOTREF
));
583 /* Find a pointer to type by looking in fp->ctf_ptrtab. If we can't find a
584 pointer to the given type, see if we can compute a pointer to the type
585 resulting from resolving the type down to its base type and use that
586 instead. This helps with cases where the CTF data includes "struct foo *"
587 but not "foo_t *" and the user accesses "foo_t *" in the debugger.
589 XXX what about parent containers? */
592 ctf_type_pointer (ctf_file_t
*fp
, ctf_id_t type
)
594 ctf_file_t
*ofp
= fp
;
597 if (ctf_lookup_by_id (&fp
, type
) == NULL
)
598 return CTF_ERR
; /* errno is set for us. */
600 if ((ntype
= fp
->ctf_ptrtab
[LCTF_TYPE_TO_INDEX (fp
, type
)]) != 0)
601 return (LCTF_INDEX_TO_TYPE (fp
, ntype
, (fp
->ctf_flags
& LCTF_CHILD
)));
603 if ((type
= ctf_type_resolve (fp
, type
)) == CTF_ERR
)
604 return (ctf_set_errno (ofp
, ECTF_NOTYPE
));
606 if (ctf_lookup_by_id (&fp
, type
) == NULL
)
607 return (ctf_set_errno (ofp
, ECTF_NOTYPE
));
609 if ((ntype
= fp
->ctf_ptrtab
[LCTF_TYPE_TO_INDEX (fp
, type
)]) != 0)
610 return (LCTF_INDEX_TO_TYPE (fp
, ntype
, (fp
->ctf_flags
& LCTF_CHILD
)));
612 return (ctf_set_errno (ofp
, ECTF_NOTYPE
));
615 /* Return the encoding for the specified INTEGER or FLOAT. */
618 ctf_type_encoding (ctf_file_t
*fp
, ctf_id_t type
, ctf_encoding_t
*ep
)
620 ctf_file_t
*ofp
= fp
;
622 const ctf_type_t
*tp
;
626 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
627 return -1; /* errno is set for us. */
629 if ((dtd
= ctf_dynamic_type (ofp
, type
)) != NULL
)
631 *ep
= dtd
->dtd_u
.dtu_enc
;
635 (void) ctf_get_ctt_size (fp
, tp
, NULL
, &increment
);
637 switch (LCTF_INFO_KIND (fp
, tp
->ctt_info
))
640 data
= *(const uint32_t *) ((uintptr_t) tp
+ increment
);
641 ep
->cte_format
= CTF_INT_ENCODING (data
);
642 ep
->cte_offset
= CTF_INT_OFFSET (data
);
643 ep
->cte_bits
= CTF_INT_BITS (data
);
646 data
= *(const uint32_t *) ((uintptr_t) tp
+ increment
);
647 ep
->cte_format
= CTF_FP_ENCODING (data
);
648 ep
->cte_offset
= CTF_FP_OFFSET (data
);
649 ep
->cte_bits
= CTF_FP_BITS (data
);
653 const ctf_slice_t
*slice
;
654 ctf_encoding_t underlying_en
;
656 slice
= (ctf_slice_t
*) ((uintptr_t) tp
+ increment
);
657 data
= ctf_type_encoding (fp
, slice
->cts_type
, &underlying_en
);
659 ep
->cte_format
= underlying_en
.cte_format
;
660 ep
->cte_offset
= slice
->cts_offset
;
661 ep
->cte_bits
= slice
->cts_bits
;
665 return (ctf_set_errno (ofp
, ECTF_NOTINTFP
));
672 ctf_type_cmp (ctf_file_t
*lfp
, ctf_id_t ltype
, ctf_file_t
*rfp
,
679 else if (ltype
> rtype
)
687 if (LCTF_TYPE_ISPARENT (lfp
, ltype
) && lfp
->ctf_parent
!= NULL
)
688 lfp
= lfp
->ctf_parent
;
690 if (LCTF_TYPE_ISPARENT (rfp
, rtype
) && rfp
->ctf_parent
!= NULL
)
691 rfp
= rfp
->ctf_parent
;
702 /* Return a boolean value indicating if two types are compatible. This function
703 returns true if the two types are the same, or if they (or their ultimate
704 base type) have the same encoding properties, or (for structs / unions /
705 enums / forward declarations) if they have the same name and (for structs /
706 unions) member count. */
709 ctf_type_compat (ctf_file_t
*lfp
, ctf_id_t ltype
,
710 ctf_file_t
*rfp
, ctf_id_t rtype
)
712 const ctf_type_t
*ltp
, *rtp
;
713 ctf_encoding_t le
, re
;
715 uint32_t lkind
, rkind
;
718 if (ctf_type_cmp (lfp
, ltype
, rfp
, rtype
) == 0)
721 ltype
= ctf_type_resolve (lfp
, ltype
);
722 lkind
= ctf_type_kind (lfp
, ltype
);
724 rtype
= ctf_type_resolve (rfp
, rtype
);
725 rkind
= ctf_type_kind (rfp
, rtype
);
727 ltp
= ctf_lookup_by_id (&lfp
, ltype
);
728 rtp
= ctf_lookup_by_id (&rfp
, rtype
);
730 if (ltp
!= NULL
&& rtp
!= NULL
)
731 same_names
= (strcmp (ctf_strptr (lfp
, ltp
->ctt_name
),
732 ctf_strptr (rfp
, rtp
->ctt_name
)) == 0);
734 if (((lkind
== CTF_K_ENUM
) && (rkind
== CTF_K_INTEGER
)) ||
735 ((rkind
== CTF_K_ENUM
) && (lkind
== CTF_K_INTEGER
)))
745 memset (&le
, 0, sizeof (le
));
746 memset (&re
, 0, sizeof (re
));
747 return (ctf_type_encoding (lfp
, ltype
, &le
) == 0
748 && ctf_type_encoding (rfp
, rtype
, &re
) == 0
749 && memcmp (&le
, &re
, sizeof (ctf_encoding_t
)) == 0);
751 return (ctf_type_compat (lfp
, ctf_type_reference (lfp
, ltype
),
752 rfp
, ctf_type_reference (rfp
, rtype
)));
754 return (ctf_array_info (lfp
, ltype
, &la
) == 0
755 && ctf_array_info (rfp
, rtype
, &ra
) == 0
756 && la
.ctr_nelems
== ra
.ctr_nelems
757 && ctf_type_compat (lfp
, la
.ctr_contents
, rfp
, ra
.ctr_contents
)
758 && ctf_type_compat (lfp
, la
.ctr_index
, rfp
, ra
.ctr_index
));
761 return (same_names
&& (ctf_type_size (lfp
, ltype
)
762 == ctf_type_size (rfp
, rtype
)));
765 int lencoded
, rencoded
;
766 lencoded
= ctf_type_encoding (lfp
, ltype
, &le
);
767 rencoded
= ctf_type_encoding (rfp
, rtype
, &re
);
769 if ((lencoded
!= rencoded
) ||
770 ((lencoded
== 0) && memcmp (&le
, &re
, sizeof (ctf_encoding_t
)) != 0))
775 return same_names
; /* No other checks required for these type kinds. */
777 return 0; /* Should not get here since we did a resolve. */
781 /* Return the type and offset for a given member of a STRUCT or UNION. */
784 ctf_member_info (ctf_file_t
*fp
, ctf_id_t type
, const char *name
,
787 ctf_file_t
*ofp
= fp
;
788 const ctf_type_t
*tp
;
789 ssize_t size
, increment
;
792 if ((type
= ctf_type_resolve (fp
, type
)) == CTF_ERR
)
793 return -1; /* errno is set for us. */
795 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
796 return -1; /* errno is set for us. */
798 (void) ctf_get_ctt_size (fp
, tp
, &size
, &increment
);
799 kind
= LCTF_INFO_KIND (fp
, tp
->ctt_info
);
801 if (kind
!= CTF_K_STRUCT
&& kind
!= CTF_K_UNION
)
802 return (ctf_set_errno (ofp
, ECTF_NOTSOU
));
804 if (size
< CTF_LSTRUCT_THRESH
)
806 const ctf_member_t
*mp
= (const ctf_member_t
*) ((uintptr_t) tp
+
809 for (n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
); n
!= 0; n
--, mp
++)
811 if (strcmp (ctf_strptr (fp
, mp
->ctm_name
), name
) == 0)
813 mip
->ctm_type
= mp
->ctm_type
;
814 mip
->ctm_offset
= mp
->ctm_offset
;
821 const ctf_lmember_t
*lmp
= (const ctf_lmember_t
*) ((uintptr_t) tp
+
824 for (n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
); n
!= 0; n
--, lmp
++)
826 if (strcmp (ctf_strptr (fp
, lmp
->ctlm_name
), name
) == 0)
828 mip
->ctm_type
= lmp
->ctlm_type
;
829 mip
->ctm_offset
= (unsigned long) CTF_LMEM_OFFSET (lmp
);
835 return (ctf_set_errno (ofp
, ECTF_NOMEMBNAM
));
838 /* Return the array type, index, and size information for the specified ARRAY. */
841 ctf_array_info (ctf_file_t
*fp
, ctf_id_t type
, ctf_arinfo_t
*arp
)
843 ctf_file_t
*ofp
= fp
;
844 const ctf_type_t
*tp
;
845 const ctf_array_t
*ap
;
846 const ctf_dtdef_t
*dtd
;
849 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
850 return -1; /* errno is set for us. */
852 if (LCTF_INFO_KIND (fp
, tp
->ctt_info
) != CTF_K_ARRAY
)
853 return (ctf_set_errno (ofp
, ECTF_NOTARRAY
));
855 if ((dtd
= ctf_dynamic_type (ofp
, type
)) != NULL
)
857 *arp
= dtd
->dtd_u
.dtu_arr
;
861 (void) ctf_get_ctt_size (fp
, tp
, NULL
, &increment
);
863 ap
= (const ctf_array_t
*) ((uintptr_t) tp
+ increment
);
864 arp
->ctr_contents
= ap
->cta_contents
;
865 arp
->ctr_index
= ap
->cta_index
;
866 arp
->ctr_nelems
= ap
->cta_nelems
;
871 /* Convert the specified value to the corresponding enum tag name, if a
872 matching name can be found. Otherwise NULL is returned. */
875 ctf_enum_name (ctf_file_t
*fp
, ctf_id_t type
, int value
)
877 ctf_file_t
*ofp
= fp
;
878 const ctf_type_t
*tp
;
879 const ctf_enum_t
*ep
;
883 if ((type
= ctf_type_resolve_unsliced (fp
, type
)) == CTF_ERR
)
884 return NULL
; /* errno is set for us. */
886 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
887 return NULL
; /* errno is set for us. */
889 if (LCTF_INFO_KIND (fp
, tp
->ctt_info
) != CTF_K_ENUM
)
891 (void) ctf_set_errno (ofp
, ECTF_NOTENUM
);
895 (void) ctf_get_ctt_size (fp
, tp
, NULL
, &increment
);
897 ep
= (const ctf_enum_t
*) ((uintptr_t) tp
+ increment
);
899 for (n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
); n
!= 0; n
--, ep
++)
901 if (ep
->cte_value
== value
)
902 return (ctf_strptr (fp
, ep
->cte_name
));
905 (void) ctf_set_errno (ofp
, ECTF_NOENUMNAM
);
909 /* Convert the specified enum tag name to the corresponding value, if a
910 matching name can be found. Otherwise CTF_ERR is returned. */
913 ctf_enum_value (ctf_file_t
* fp
, ctf_id_t type
, const char *name
, int *valp
)
915 ctf_file_t
*ofp
= fp
;
916 const ctf_type_t
*tp
;
917 const ctf_enum_t
*ep
;
921 if ((type
= ctf_type_resolve_unsliced (fp
, type
)) == CTF_ERR
)
922 return -1; /* errno is set for us. */
924 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
925 return -1; /* errno is set for us. */
927 if (LCTF_INFO_KIND (fp
, tp
->ctt_info
) != CTF_K_ENUM
)
929 (void) ctf_set_errno (ofp
, ECTF_NOTENUM
);
933 (void) ctf_get_ctt_size (fp
, tp
, NULL
, &increment
);
935 ep
= (const ctf_enum_t
*) ((uintptr_t) tp
+ increment
);
937 for (n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
); n
!= 0; n
--, ep
++)
939 if (strcmp (ctf_strptr (fp
, ep
->cte_name
), name
) == 0)
942 *valp
= ep
->cte_value
;
947 (void) ctf_set_errno (ofp
, ECTF_NOENUMNAM
);
951 /* Recursively visit the members of any type. This function is used as the
952 engine for ctf_type_visit, below. We resolve the input type, recursively
953 invoke ourself for each type member if the type is a struct or union, and
954 then invoke the callback function on the current type. If any callback
955 returns non-zero, we abort and percolate the error code back up to the top. */
958 ctf_type_rvisit (ctf_file_t
*fp
, ctf_id_t type
, ctf_visit_f
*func
,
959 void *arg
, const char *name
, unsigned long offset
, int depth
)
961 ctf_id_t otype
= type
;
962 const ctf_type_t
*tp
;
963 ssize_t size
, increment
;
967 if ((type
= ctf_type_resolve (fp
, type
)) == CTF_ERR
)
968 return -1; /* errno is set for us. */
970 if ((tp
= ctf_lookup_by_id (&fp
, type
)) == NULL
)
971 return -1; /* errno is set for us. */
973 if ((rc
= func (name
, otype
, offset
, depth
, arg
)) != 0)
976 kind
= LCTF_INFO_KIND (fp
, tp
->ctt_info
);
978 if (kind
!= CTF_K_STRUCT
&& kind
!= CTF_K_UNION
)
981 (void) ctf_get_ctt_size (fp
, tp
, &size
, &increment
);
983 if (size
< CTF_LSTRUCT_THRESH
)
985 const ctf_member_t
*mp
= (const ctf_member_t
*) ((uintptr_t) tp
+
988 for (n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
); n
!= 0; n
--, mp
++)
990 if ((rc
= ctf_type_rvisit (fp
, mp
->ctm_type
,
991 func
, arg
, ctf_strptr (fp
, mp
->ctm_name
),
992 offset
+ mp
->ctm_offset
,
1000 const ctf_lmember_t
*lmp
= (const ctf_lmember_t
*) ((uintptr_t) tp
+
1003 for (n
= LCTF_INFO_VLEN (fp
, tp
->ctt_info
); n
!= 0; n
--, lmp
++)
1005 if ((rc
= ctf_type_rvisit (fp
, lmp
->ctlm_type
,
1006 func
, arg
, ctf_strptr (fp
,
1008 offset
+ (unsigned long) CTF_LMEM_OFFSET (lmp
),
1017 /* Recursively visit the members of any type. We pass the name, member
1018 type, and offset of each member to the specified callback function. */
1020 ctf_type_visit (ctf_file_t
*fp
, ctf_id_t type
, ctf_visit_f
*func
, void *arg
)
1022 return (ctf_type_rvisit (fp
, type
, func
, arg
, "", 0, 0));