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_index(const ctf_file_t *fp, const void *v, uint_t *indexp,
32 uint_t *typep, int *ischildp)
37 if (fp->ctf_version == CTF_VERSION_2) {
38 const struct ctf_type_v2 *ctt = v;
41 index = CTF_V2_TYPE_TO_INDEX(ctt->ctt_type);
42 ischild = CTF_V2_TYPE_ISCHILD(ctt->ctt_type);
44 const struct ctf_type_v3 *ctt = v;
47 index = CTF_V3_TYPE_TO_INDEX(ctt->ctt_type);
48 ischild = CTF_V3_TYPE_ISCHILD(ctt->ctt_type);
60 ctf_get_ctt_info(const ctf_file_t *fp, const void *v, uint_t *kindp,
61 uint_t *vlenp, int *isrootp)
66 if (fp->ctf_version == CTF_VERSION_2) {
67 const struct ctf_type_v2 *ctt = v;
69 kind = CTF_V2_INFO_KIND(ctt->ctt_info);
70 vlen = CTF_V2_INFO_VLEN(ctt->ctt_info);
71 isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info);
73 const struct ctf_type_v3 *ctt = v;
75 kind = CTF_V3_INFO_KIND(ctt->ctt_info);
76 vlen = CTF_V3_INFO_VLEN(ctt->ctt_info);
77 isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info);
89 ctf_get_ctt_size(const ctf_file_t *fp, const void *v, ssize_t *sizep,
92 ssize_t size, increment;
94 if (fp->ctf_version == CTF_VERSION_2) {
95 const struct ctf_type_v2 *ctt = v;
97 if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
98 size = (size_t)CTF_TYPE_LSIZE(ctt);
99 increment = sizeof (struct ctf_type_v2);
101 size = ctt->ctt_size;
102 increment = sizeof (struct ctf_stype_v2);
105 const struct ctf_type_v3 *ctt = v;
107 if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
108 size = (size_t)CTF_TYPE_LSIZE(ctt);
109 increment = sizeof (struct ctf_type_v3);
111 size = ctt->ctt_size;
112 increment = sizeof (struct ctf_stype_v3);
119 *incrementp = increment;
125 * Fetch info for a struct or union member.
128 ctf_get_ctm_info(const ctf_file_t *fp, const void *v, size_t size,
129 size_t *incrementp, uint_t *typep, ulong_t *offsetp, const char **namep)
135 if (fp->ctf_version == CTF_VERSION_2) {
136 if (size < CTF_V2_LSTRUCT_THRESH) {
137 const struct ctf_member_v2 *ctm = v;
139 name = ctm->ctm_name;
140 type = ctm->ctm_type;
141 offset = ctm->ctm_offset;
142 increment = sizeof(*ctm);
144 const struct ctf_lmember_v2 *ctlm = v;
146 name = ctlm->ctlm_name;
147 type = ctlm->ctlm_type;
148 offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
149 increment = sizeof(*ctlm);
152 if (size < CTF_V3_LSTRUCT_THRESH) {
153 const struct ctf_member_v3 *ctm = v;
155 name = ctm->ctm_name;
156 type = ctm->ctm_type;
157 offset = ctm->ctm_offset;
158 increment = sizeof(*ctm);
160 const struct ctf_lmember_v3 *ctlm = v;
162 name = ctlm->ctlm_name;
163 type = ctlm->ctlm_type;
164 offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
165 increment = sizeof(*ctlm);
169 if (incrementp != NULL)
170 *incrementp = increment;
176 *namep = ctf_strraw(fp, name);
180 * Iterate over the members of a STRUCT or UNION. We pass the name, member
181 * type, and offset of each member to the specified callback function.
184 ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
186 ctf_file_t *ofp = fp;
188 ssize_t size, increment;
189 uint_t kind, n, vlen;
192 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
193 return (CTF_ERR); /* errno is set for us */
195 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
196 return (CTF_ERR); /* errno is set for us */
198 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
199 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
201 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
202 return (ctf_set_errno(ofp, ECTF_NOTSOU));
204 const char *mp = (const char *)((uintptr_t)tp + increment);
206 for (n = vlen; n != 0; n--, mp += increment) {
211 ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset,
213 if ((rc = func(name, type, offset, arg)) != 0)
221 * Iterate over the members of an ENUM. We pass the string name and associated
222 * integer value of each enum element to the specified callback function.
225 ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
227 ctf_file_t *ofp = fp;
229 const ctf_enum_t *ep;
231 uint_t kind, n, vlen;
234 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
235 return (CTF_ERR); /* errno is set for us */
237 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
238 return (CTF_ERR); /* errno is set for us */
240 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
241 if (kind != CTF_K_ENUM)
242 return (ctf_set_errno(ofp, ECTF_NOTENUM));
244 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
246 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
248 for (n = vlen; n != 0; n--, ep++) {
249 const char *name = ctf_strptr(fp, ep->cte_name);
250 if ((rc = func(name, ep->cte_value, arg)) != 0)
258 * Iterate over every root (user-visible) type in the given CTF container.
259 * We pass the type ID of each type to the specified callback function.
262 ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
264 ctf_id_t id, max = fp->ctf_typemax;
265 int rc, child = (fp->ctf_flags & LCTF_CHILD);
268 for (id = 1; id <= max; id++) {
269 const void *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
270 ctf_get_ctt_info(fp, tp, NULL, NULL, &isroot);
272 (rc = func(LCTF_INDEX_TO_TYPE(fp, id, child), arg)) != 0)
280 * Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
281 * RESTRICT nodes until we reach a "base" type node. This is useful when
282 * we want to follow a type ID to a node that has members or a size. To guard
283 * against infinite loops, we implement simplified cycle detection and check
284 * each link against itself, the previous node, and the topmost node.
287 ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
289 ctf_id_t prev = type, otype = type;
290 ctf_file_t *ofp = fp;
294 while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
295 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
301 ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
302 if (ctype == type || ctype == otype || ctype == prev) {
303 ctf_dprintf("type %ld cycle detected\n", otype);
304 return (ctf_set_errno(ofp, ECTF_CORRUPT));
314 return (CTF_ERR); /* errno is set for us */
318 * Lookup the given type ID and print a string name for it into buf. Return
319 * the actual number of bytes (not including \0) needed to format the name.
322 ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
326 ctf_decl_node_t *cdp;
327 ctf_decl_prec_t prec, lp, rp;
331 if (fp == NULL && type == CTF_ERR)
332 return (-1); /* simplify caller code by permitting CTF_ERR */
334 ctf_decl_init(&cd, buf, len);
335 ctf_decl_push(&cd, fp, type);
337 if (cd.cd_err != 0) {
339 return (ctf_set_errno(fp, cd.cd_err));
343 * If the type graph's order conflicts with lexical precedence order
344 * for pointers or arrays, then we need to surround the declarations at
345 * the corresponding lexical precedence with parentheses. This can
346 * result in either a parenthesized pointer (*) as in int (*)() or
347 * int (*)[], or in a parenthesized pointer and array as in int (*[])().
349 ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER;
350 arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY;
352 rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1;
353 lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1;
355 k = CTF_K_POINTER; /* avoid leading whitespace (see below) */
357 for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) {
358 for (cdp = ctf_list_next(&cd.cd_nodes[prec]);
359 cdp != NULL; cdp = ctf_list_next(cdp)) {
361 ctf_file_t *rfp = fp;
362 const void *tp = ctf_lookup_by_id(&rfp, cdp->cd_type);
363 const char *name = ctf_type_rname(rfp, tp);
365 if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
366 ctf_decl_sprintf(&cd, " ");
369 ctf_decl_sprintf(&cd, "(");
373 switch (cdp->cd_kind) {
378 ctf_decl_sprintf(&cd, "%s`", qname);
379 ctf_decl_sprintf(&cd, "%s", name);
382 ctf_decl_sprintf(&cd, "*");
385 ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
388 ctf_decl_sprintf(&cd, "()");
392 ctf_decl_sprintf(&cd, "struct ");
394 ctf_decl_sprintf(&cd, "%s`", qname);
395 ctf_decl_sprintf(&cd, "%s", name);
398 ctf_decl_sprintf(&cd, "union ");
400 ctf_decl_sprintf(&cd, "%s`", qname);
401 ctf_decl_sprintf(&cd, "%s", name);
404 ctf_decl_sprintf(&cd, "enum ");
406 ctf_decl_sprintf(&cd, "%s`", qname);
407 ctf_decl_sprintf(&cd, "%s", name);
410 ctf_decl_sprintf(&cd, "volatile");
413 ctf_decl_sprintf(&cd, "const");
416 ctf_decl_sprintf(&cd, "restrict");
424 ctf_decl_sprintf(&cd, ")");
427 if (cd.cd_len >= len)
428 (void) ctf_set_errno(fp, ECTF_NAMELEN);
435 ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
437 return (ctf_type_qlname(fp, type, buf, len, NULL));
441 * Lookup the given type ID and print a string name for it into buf. If buf
442 * is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
445 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
447 ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
448 return (rv >= 0 && rv < len ? buf : NULL);
452 ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
455 ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
456 return (rv >= 0 && rv < len ? buf : NULL);
460 ctf_type_rname(ctf_file_t *fp, const void *v)
464 if (fp->ctf_version == CTF_VERSION_2) {
465 const struct ctf_type_v2 *ctt = v;
467 name = ctt->ctt_name;
469 const struct ctf_type_v3 *ctt = v;
471 name = ctt->ctt_name;
474 return (ctf_strptr(fp, name));
478 * Resolve the type down to a base type node, and then return the size
479 * of the type storage in bytes.
482 ctf_type_size(ctf_file_t *fp, ctf_id_t type)
489 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
490 return (-1); /* errno is set for us */
492 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
493 return (-1); /* errno is set for us */
495 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
499 return (fp->ctf_dmodel->ctd_pointer);
502 return (0); /* function size is only known by symtab */
505 return (fp->ctf_dmodel->ctd_int);
509 * Array size is not directly returned by stabs data. Instead,
510 * it defines the element type and requires the user to perform
511 * the multiplication. If ctf_get_ctt_size() returns zero, the
512 * current version of ctfconvert does not compute member sizes
513 * and we compute the size here on its behalf.
515 if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)
518 if (ctf_array_info(fp, type, &ar) == CTF_ERR ||
519 (size = ctf_type_size(fp, ar.ctr_contents)) == CTF_ERR)
520 return (-1); /* errno is set for us */
522 return (size * ar.ctr_nelems);
525 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
530 * Resolve the type down to a base type node, and then return the alignment
531 * needed for the type storage in bytes.
534 ctf_type_align(ctf_file_t *fp, ctf_id_t type)
540 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
541 return (-1); /* errno is set for us */
543 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
544 return (-1); /* errno is set for us */
546 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
551 return (fp->ctf_dmodel->ctd_pointer);
554 if (ctf_array_info(fp, type, &r) == CTF_ERR)
555 return (-1); /* errno is set for us */
556 return (ctf_type_align(fp, r.ctr_contents));
561 ssize_t size, increment;
565 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
566 vmp = (uchar_t *)tp + increment;
568 if (kind == CTF_K_STRUCT)
569 n = MIN(n, 1); /* only use first member for structs */
571 for (const char *mp = vmp; n != 0; n--, mp += increment) {
574 ctf_get_ctm_info(fp, mp, size, &increment, &type,
576 ssize_t am = ctf_type_align(fp, type);
577 align = MAX(align, am);
584 return (fp->ctf_dmodel->ctd_int);
587 return (ctf_get_ctt_size(fp, tp, NULL, NULL));
592 * Return the kind (CTF_K_* constant) for the specified type ID.
595 ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
600 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
601 return (CTF_ERR); /* errno is set for us */
603 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
609 * If the type is one that directly references another type (such as POINTER),
610 * then return the ID of the type to which it refers.
613 ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
615 ctf_file_t *ofp = fp;
619 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
620 return (CTF_ERR); /* errno is set for us */
622 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
630 ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
633 return (ctf_set_errno(ofp, ECTF_NOTREF));
638 * Find a pointer to type by looking in fp->ctf_ptrtab. If we can't find a
639 * pointer to the given type, see if we can compute a pointer to the type
640 * resulting from resolving the type down to its base type and use that
641 * instead. This helps with cases where the CTF data includes "struct foo *"
642 * but not "foo_t *" and the user accesses "foo_t *" in the debugger.
645 ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
647 ctf_file_t *ofp = fp;
650 if (ctf_lookup_by_id(&fp, type) == NULL)
651 return (CTF_ERR); /* errno is set for us */
653 if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
654 return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
656 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
657 return (ctf_set_errno(ofp, ECTF_NOTYPE));
659 if (ctf_lookup_by_id(&fp, type) == NULL)
660 return (ctf_set_errno(ofp, ECTF_NOTYPE));
662 if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
663 return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
665 return (ctf_set_errno(ofp, ECTF_NOTYPE));
669 * Return the encoding for the specified INTEGER or FLOAT.
672 ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
674 ctf_file_t *ofp = fp;
679 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
680 return (CTF_ERR); /* errno is set for us */
682 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
683 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
687 data = *(const uint_t *)((uintptr_t)tp + increment);
688 ep->cte_format = CTF_INT_ENCODING(data);
689 ep->cte_offset = CTF_INT_OFFSET(data);
690 ep->cte_bits = CTF_INT_BITS(data);
693 data = *(const uint_t *)((uintptr_t)tp + increment);
694 ep->cte_format = CTF_FP_ENCODING(data);
695 ep->cte_offset = CTF_FP_OFFSET(data);
696 ep->cte_bits = CTF_FP_BITS(data);
699 return (ctf_set_errno(ofp, ECTF_NOTINTFP));
706 ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
712 else if (ltype > rtype)
720 if (LCTF_TYPE_ISPARENT(lfp, ltype) && lfp->ctf_parent != NULL)
721 lfp = lfp->ctf_parent;
723 if (LCTF_TYPE_ISPARENT(rfp, rtype) && rfp->ctf_parent != NULL)
724 rfp = rfp->ctf_parent;
736 * Return a boolean value indicating if two types are compatible integers or
737 * floating-pointer values. This function returns true if the two types are
738 * the same, or if they have the same ASCII name and encoding properties.
739 * This function could be extended to test for compatibility for other kinds.
742 ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
743 ctf_file_t *rfp, ctf_id_t rtype)
745 const void *ltp, *rtp;
746 ctf_encoding_t le, re;
750 if (ctf_type_cmp(lfp, ltype, rfp, rtype) == 0)
753 ltype = ctf_type_resolve(lfp, ltype);
754 lkind = ctf_type_kind(lfp, ltype);
756 rtype = ctf_type_resolve(rfp, rtype);
757 rkind = ctf_type_kind(rfp, rtype);
759 if (lkind != rkind ||
760 (ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL ||
761 (rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL ||
762 strcmp(ctf_type_rname(lfp, ltp), ctf_type_rname(rfp, rtp)) != 0)
768 return (ctf_type_encoding(lfp, ltype, &le) == 0 &&
769 ctf_type_encoding(rfp, rtype, &re) == 0 &&
770 bcmp(&le, &re, sizeof (ctf_encoding_t)) == 0);
772 return (ctf_type_compat(lfp, ctf_type_reference(lfp, ltype),
773 rfp, ctf_type_reference(rfp, rtype)));
775 return (ctf_array_info(lfp, ltype, &la) == 0 &&
776 ctf_array_info(rfp, rtype, &ra) == 0 &&
777 la.ctr_nelems == ra.ctr_nelems && ctf_type_compat(
778 lfp, la.ctr_contents, rfp, ra.ctr_contents) &&
779 ctf_type_compat(lfp, la.ctr_index, rfp, ra.ctr_index));
782 return (ctf_type_size(lfp, ltype) == ctf_type_size(rfp, rtype));
785 return (1); /* no other checks required for these type kinds */
787 return (0); /* should not get here since we did a resolve */
792 _ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, ulong_t off,
795 ctf_file_t *ofp = fp;
797 ssize_t size, increment;
798 uint_t kind, n, vlen;
800 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
801 return (CTF_ERR); /* errno is set for us */
803 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
804 return (CTF_ERR); /* errno is set for us */
806 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
807 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
809 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
810 return (ctf_set_errno(ofp, ECTF_NOTSOU));
812 const char *mp = (const char *)((uintptr_t)tp + increment);
814 for (n = vlen; n != 0; n--, mp += increment) {
819 ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset,
821 if (name1[0] == '\0' &&
822 _ctf_member_info(fp, type, name, offset + off, mip) == 0)
824 if (strcmp(name1, name) == 0) {
825 mip->ctm_type = type;
826 mip->ctm_offset = offset + off;
831 return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
835 * Return the type and offset for a given member of a STRUCT or UNION.
838 ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
842 return (_ctf_member_info(fp, type, name, 0, mip));
846 * Return the array type, index, and size information for the specified ARRAY.
849 ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
851 ctf_file_t *ofp = fp;
856 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
857 return (CTF_ERR); /* errno is set for us */
859 ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
861 if (kind != CTF_K_ARRAY)
862 return (ctf_set_errno(ofp, ECTF_NOTARRAY));
864 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
866 ap = (const void *)((uintptr_t)tp + increment);
867 if (fp->ctf_version == CTF_VERSION_2) {
868 const struct ctf_array_v2 *ap2 = ap;
870 arp->ctr_contents = ap2->cta_contents;
871 arp->ctr_index = ap2->cta_index;
872 arp->ctr_nelems = ap2->cta_nelems;
874 const struct ctf_array_v3 *ap3 = ap;
876 arp->ctr_contents = ap3->cta_contents;
877 arp->ctr_index = ap3->cta_index;
878 arp->ctr_nelems = ap3->cta_nelems;
885 * Convert the specified value to the corresponding enum member name, if a
886 * matching name can be found. Otherwise NULL is returned.
889 ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
891 ctf_file_t *ofp = fp;
893 const ctf_enum_t *ep;
895 uint_t kind, n, vlen;
897 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
898 return (NULL); /* errno is set for us */
900 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
901 return (NULL); /* errno is set for us */
903 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
905 if (kind != CTF_K_ENUM) {
906 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
910 (void) ctf_get_ctt_size(fp, tp, NULL, &increment);
912 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
914 for (n = vlen; n != 0; n--, ep++) {
915 if (ep->cte_value == value)
916 return (ctf_strptr(fp, ep->cte_name));
919 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
924 * Convert the specified enum tag name to the corresponding value, if a
925 * matching name can be found. Otherwise CTF_ERR is returned.
928 ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
930 ctf_file_t *ofp = fp;
932 const ctf_enum_t *ep;
933 ssize_t size, increment;
934 uint_t kind, n, vlen;
936 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
937 return (CTF_ERR); /* errno is set for us */
939 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
940 return (CTF_ERR); /* errno is set for us */
942 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
944 if (kind != CTF_K_ENUM) {
945 (void) ctf_set_errno(ofp, ECTF_NOTENUM);
949 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
951 ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
953 for (n = vlen; n != 0; n--, ep++) {
954 if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
956 *valp = ep->cte_value;
961 (void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
966 * Recursively visit the members of any type. This function is used as the
967 * engine for ctf_type_visit, below. We resolve the input type, recursively
968 * invoke ourself for each type member if the type is a struct or union, and
969 * then invoke the callback function on the current type. If any callback
970 * returns non-zero, we abort and percolate the error code back up to the top.
973 ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
974 const char *name, ulong_t offset, int depth)
976 ctf_id_t otype = type;
978 ssize_t size, increment;
979 uint_t kind, n, vlen;
982 if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
983 return (CTF_ERR); /* errno is set for us */
985 if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
986 return (CTF_ERR); /* errno is set for us */
988 if ((rc = func(name, otype, offset, depth, arg)) != 0)
991 ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
993 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
996 (void) ctf_get_ctt_size(fp, tp, &size, &increment);
998 const char *mp = (const char *)((uintptr_t)tp + increment);
999 for (n = vlen; n != 0; n--, mp += increment) {
1004 ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset1,
1006 if ((rc = ctf_type_rvisit(fp, type, func, arg, name,
1007 offset + offset1, depth + 1)) != 0)
1015 * Recursively visit the members of any type. We pass the name, member
1016 * type, and offset of each member to the specified callback function.
1019 ctf_type_visit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg)
1021 return (ctf_type_rvisit(fp, type, func, arg, "", 0, 0));